raw
smg_comms_c_wrappers    1 /* secmem.c  -	memory allocation from a secure heap
smg_comms_c_wrappers 2 * Modified by No Such Labs. (C) 2015. See README.
smg_comms_c_wrappers 3 *
smg_comms_c_wrappers 4 * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10,
smg_comms_c_wrappers 5 * SHA256(gnupg-1.4.10.tar.gz):
smg_comms_c_wrappers 6 * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a
smg_comms_c_wrappers 7 * (C) 1994-2005 Free Software Foundation, Inc.
smg_comms_c_wrappers 8 *
smg_comms_c_wrappers 9 * This program is free software: you can redistribute it and/or modify
smg_comms_c_wrappers 10 * it under the terms of the GNU General Public License as published by
smg_comms_c_wrappers 11 * the Free Software Foundation, either version 3 of the License, or
smg_comms_c_wrappers 12 * (at your option) any later version.
smg_comms_c_wrappers 13 *
smg_comms_c_wrappers 14 * This program is distributed in the hope that it will be useful,
smg_comms_c_wrappers 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
smg_comms_c_wrappers 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
smg_comms_c_wrappers 17 * GNU General Public License for more details.
smg_comms_c_wrappers 18 *
smg_comms_c_wrappers 19 * You should have received a copy of the GNU General Public License
smg_comms_c_wrappers 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
smg_comms_c_wrappers 21 */
smg_comms_c_wrappers 22
smg_comms_c_wrappers 23 #include "knobs.h"
smg_comms_c_wrappers 24
smg_comms_c_wrappers 25 #include <stdio.h>
smg_comms_c_wrappers 26 #include <stdlib.h>
smg_comms_c_wrappers 27 #include <string.h>
smg_comms_c_wrappers 28 #include <errno.h>
smg_comms_c_wrappers 29 #include <stdarg.h>
smg_comms_c_wrappers 30 #include <unistd.h>
smg_comms_c_wrappers 31 #if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
smg_comms_c_wrappers 32 #include <sys/mman.h>
smg_comms_c_wrappers 33 #include <sys/types.h>
smg_comms_c_wrappers 34 #include <fcntl.h>
smg_comms_c_wrappers 35 #ifdef USE_CAPABILITIES
smg_comms_c_wrappers 36 #include <sys/capability.h>
smg_comms_c_wrappers 37 #endif
smg_comms_c_wrappers 38 #ifdef HAVE_PLOCK
smg_comms_c_wrappers 39 #include <sys/lock.h>
smg_comms_c_wrappers 40 #endif
smg_comms_c_wrappers 41 #endif
smg_comms_c_wrappers 42
smg_comms_c_wrappers 43 #include "types.h"
smg_comms_c_wrappers 44 #include "memory.h"
smg_comms_c_wrappers 45 #include "util.h"
smg_comms_c_wrappers 46
smg_comms_c_wrappers 47 /* MinGW doesn't seem to prototype getpagesize, though it does have
smg_comms_c_wrappers 48 it. */
smg_comms_c_wrappers 49 #if !HAVE_DECL_GETPAGESIZE
smg_comms_c_wrappers 50 int getpagesize(void);
smg_comms_c_wrappers 51 #endif
smg_comms_c_wrappers 52
smg_comms_c_wrappers 53 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
smg_comms_c_wrappers 54 #define MAP_ANONYMOUS MAP_ANON
smg_comms_c_wrappers 55 #endif
smg_comms_c_wrappers 56 /* It seems that Slackware 7.1 does not know about EPERM */
smg_comms_c_wrappers 57 #if !defined(EPERM) && defined(ENOMEM)
smg_comms_c_wrappers 58 #define EPERM ENOMEM
smg_comms_c_wrappers 59 #endif
smg_comms_c_wrappers 60
smg_comms_c_wrappers 61
smg_comms_c_wrappers 62 #define DEFAULT_POOLSIZE 16384
smg_comms_c_wrappers 63
smg_comms_c_wrappers 64 typedef struct memblock_struct MEMBLOCK;
smg_comms_c_wrappers 65 struct memblock_struct {
smg_comms_c_wrappers 66 unsigned size;
smg_comms_c_wrappers 67 union {
smg_comms_c_wrappers 68 MEMBLOCK *next;
smg_comms_c_wrappers 69 PROPERLY_ALIGNED_TYPE aligned;
smg_comms_c_wrappers 70 } u;
smg_comms_c_wrappers 71 };
smg_comms_c_wrappers 72
smg_comms_c_wrappers 73
smg_comms_c_wrappers 74
smg_comms_c_wrappers 75 static void *pool;
smg_comms_c_wrappers 76 static volatile int pool_okay; /* may be checked in an atexit function */
smg_comms_c_wrappers 77 #ifdef HAVE_MMAP
smg_comms_c_wrappers 78 static volatile int pool_is_mmapped;
smg_comms_c_wrappers 79 #endif
smg_comms_c_wrappers 80 static size_t poolsize; /* allocated length */
smg_comms_c_wrappers 81 static size_t poollen; /* used length */
smg_comms_c_wrappers 82 static MEMBLOCK *unused_blocks;
smg_comms_c_wrappers 83 static unsigned max_alloced;
smg_comms_c_wrappers 84 static unsigned cur_alloced;
smg_comms_c_wrappers 85 static unsigned max_blocks;
smg_comms_c_wrappers 86 static unsigned cur_blocks;
smg_comms_c_wrappers 87 static int disable_secmem;
smg_comms_c_wrappers 88 static int show_warning;
smg_comms_c_wrappers 89 static int no_warning;
smg_comms_c_wrappers 90 static int suspend_warning;
smg_comms_c_wrappers 91
smg_comms_c_wrappers 92
smg_comms_c_wrappers 93 static void
smg_comms_c_wrappers 94 print_warn(void)
smg_comms_c_wrappers 95 {
smg_comms_c_wrappers 96 if (!no_warning)
smg_comms_c_wrappers 97 {
smg_comms_c_wrappers 98 log_info("WARNING: using insecure memory!\n");
smg_comms_c_wrappers 99 }
smg_comms_c_wrappers 100 }
smg_comms_c_wrappers 101
smg_comms_c_wrappers 102
smg_comms_c_wrappers 103 static void
smg_comms_c_wrappers 104 lock_pool( void *p, size_t n )
smg_comms_c_wrappers 105 {
smg_comms_c_wrappers 106 #if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK)
smg_comms_c_wrappers 107 int err;
smg_comms_c_wrappers 108
smg_comms_c_wrappers 109 cap_set_proc( cap_from_text("cap_ipc_lock+ep") );
smg_comms_c_wrappers 110 err = mlock( p, n );
smg_comms_c_wrappers 111 if( err && errno )
smg_comms_c_wrappers 112 err = errno;
smg_comms_c_wrappers 113 cap_set_proc( cap_from_text("cap_ipc_lock+p") );
smg_comms_c_wrappers 114
smg_comms_c_wrappers 115 if( err ) {
smg_comms_c_wrappers 116 if( errno != EPERM
smg_comms_c_wrappers 117 #ifdef EAGAIN /* OpenBSD returns this */
smg_comms_c_wrappers 118 && errno != EAGAIN
smg_comms_c_wrappers 119 #endif
smg_comms_c_wrappers 120 #ifdef ENOSYS /* Some SCOs return this (function not implemented) */
smg_comms_c_wrappers 121 && errno != ENOSYS
smg_comms_c_wrappers 122 #endif
smg_comms_c_wrappers 123 #ifdef ENOMEM /* Linux can return this */
smg_comms_c_wrappers 124 && errno != ENOMEM
smg_comms_c_wrappers 125 #endif
smg_comms_c_wrappers 126 )
smg_comms_c_wrappers 127 log_error("can't lock memory: %s\n", strerror(err));
smg_comms_c_wrappers 128 show_warning = 1;
smg_comms_c_wrappers 129 }
smg_comms_c_wrappers 130
smg_comms_c_wrappers 131 #elif defined(HAVE_MLOCK)
smg_comms_c_wrappers 132 uid_t uid;
smg_comms_c_wrappers 133 int err;
smg_comms_c_wrappers 134
smg_comms_c_wrappers 135 uid = getuid();
smg_comms_c_wrappers 136
smg_comms_c_wrappers 137 #ifdef HAVE_BROKEN_MLOCK
smg_comms_c_wrappers 138 /* ick. but at least we get secured memory. about to lock
smg_comms_c_wrappers 139 entire data segment. */
smg_comms_c_wrappers 140 #ifdef HAVE_PLOCK
smg_comms_c_wrappers 141 # ifdef _AIX
smg_comms_c_wrappers 142 /* The configure for AIX returns broken mlock but the plock has
smg_comms_c_wrappers 143 the strange requirement to somehow set the stack limit first.
smg_comms_c_wrappers 144 The problem might turn out in indeterministic program behaviour
smg_comms_c_wrappers 145 and hanging processes which can somehow be solved when enough
smg_comms_c_wrappers 146 processes are clogging up the memory. To get this problem out
smg_comms_c_wrappers 147 of the way we simply don't try to lock the memory at all.
smg_comms_c_wrappers 148 */
smg_comms_c_wrappers 149 errno = EPERM;
smg_comms_c_wrappers 150 err = errno;
smg_comms_c_wrappers 151 # else /* !_AIX */
smg_comms_c_wrappers 152 err = plock( DATLOCK );
smg_comms_c_wrappers 153 if( err && errno )
smg_comms_c_wrappers 154 err = errno;
smg_comms_c_wrappers 155 # endif /*_AIX*/
smg_comms_c_wrappers 156 #else /*!HAVE_PLOCK*/
smg_comms_c_wrappers 157 if( uid ) {
smg_comms_c_wrappers 158 errno = EPERM;
smg_comms_c_wrappers 159 err = errno;
smg_comms_c_wrappers 160 }
smg_comms_c_wrappers 161 else {
smg_comms_c_wrappers 162 err = mlock( p, n );
smg_comms_c_wrappers 163 if( err && errno )
smg_comms_c_wrappers 164 err = errno;
smg_comms_c_wrappers 165 }
smg_comms_c_wrappers 166 #endif /*!HAVE_PLOCK*/
smg_comms_c_wrappers 167 #else
smg_comms_c_wrappers 168 err = mlock( p, n );
smg_comms_c_wrappers 169 if( err && errno )
smg_comms_c_wrappers 170 err = errno;
smg_comms_c_wrappers 171 #endif
smg_comms_c_wrappers 172
smg_comms_c_wrappers 173 if( uid && !geteuid() ) {
smg_comms_c_wrappers 174 /* check that we really dropped the privs.
smg_comms_c_wrappers 175 * Note: setuid(0) should always fail */
smg_comms_c_wrappers 176 if( setuid( uid ) || getuid() != geteuid() || !setuid(0) )
smg_comms_c_wrappers 177 log_fatal("failed to reset uid: %s\n", strerror(errno));
smg_comms_c_wrappers 178 }
smg_comms_c_wrappers 179
smg_comms_c_wrappers 180 if( err ) {
smg_comms_c_wrappers 181 if( errno != EPERM
smg_comms_c_wrappers 182 #ifdef EAGAIN /* OpenBSD returns this */
smg_comms_c_wrappers 183 && errno != EAGAIN
smg_comms_c_wrappers 184 #endif
smg_comms_c_wrappers 185 #ifdef ENOSYS /* Some SCOs return this (function not implemented) */
smg_comms_c_wrappers 186 && errno != ENOSYS
smg_comms_c_wrappers 187 #endif
smg_comms_c_wrappers 188 #ifdef ENOMEM /* Linux can return this */
smg_comms_c_wrappers 189 && errno != ENOMEM
smg_comms_c_wrappers 190 #endif
smg_comms_c_wrappers 191 )
smg_comms_c_wrappers 192 log_error("can't lock memory: %s\n", strerror(err));
smg_comms_c_wrappers 193 show_warning = 1;
smg_comms_c_wrappers 194 }
smg_comms_c_wrappers 195
smg_comms_c_wrappers 196 #elif defined ( __QNX__ )
smg_comms_c_wrappers 197 /* QNX does not page at all, so the whole secure memory stuff does
smg_comms_c_wrappers 198 * not make much sense. However it is still of use because it
smg_comms_c_wrappers 199 * wipes out the memory on a free().
smg_comms_c_wrappers 200 * Therefore it is sufficient to suppress the warning
smg_comms_c_wrappers 201 */
smg_comms_c_wrappers 202 #elif defined (HAVE_DOSISH_SYSTEM) || defined (__CYGWIN__)
smg_comms_c_wrappers 203 /* It does not make sense to print such a warning, given the fact that
smg_comms_c_wrappers 204 * this whole Windows !@#$% and their user base are inherently insecure
smg_comms_c_wrappers 205 */
smg_comms_c_wrappers 206 #else
smg_comms_c_wrappers 207 log_info("Please note that you don't have secure memory on this system\n");
smg_comms_c_wrappers 208 #endif
smg_comms_c_wrappers 209 }
smg_comms_c_wrappers 210
smg_comms_c_wrappers 211
smg_comms_c_wrappers 212 static void
smg_comms_c_wrappers 213 init_pool( size_t n)
smg_comms_c_wrappers 214 {
smg_comms_c_wrappers 215 long int pgsize_val;
smg_comms_c_wrappers 216 size_t pgsize;
smg_comms_c_wrappers 217
smg_comms_c_wrappers 218 poolsize = n;
smg_comms_c_wrappers 219
smg_comms_c_wrappers 220 if( disable_secmem )
smg_comms_c_wrappers 221 log_bug("secure memory is disabled");
smg_comms_c_wrappers 222
smg_comms_c_wrappers 223 #if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
smg_comms_c_wrappers 224 pgsize_val = sysconf (_SC_PAGESIZE);
smg_comms_c_wrappers 225 #elif defined(HAVE_GETPAGESIZE)
smg_comms_c_wrappers 226 pgsize_val = getpagesize ();
smg_comms_c_wrappers 227 #else
smg_comms_c_wrappers 228 pgsize_val = -1;
smg_comms_c_wrappers 229 #endif
smg_comms_c_wrappers 230 pgsize = (pgsize_val != -1 && pgsize_val > 0)? pgsize_val : 4096;
smg_comms_c_wrappers 231
smg_comms_c_wrappers 232
smg_comms_c_wrappers 233 #ifdef HAVE_MMAP
smg_comms_c_wrappers 234 poolsize = (poolsize + pgsize -1 ) & ~(pgsize-1);
smg_comms_c_wrappers 235 #ifdef MAP_ANONYMOUS
smg_comms_c_wrappers 236 pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
smg_comms_c_wrappers 237 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
smg_comms_c_wrappers 238 #else /* map /dev/zero instead */
smg_comms_c_wrappers 239 { int fd;
smg_comms_c_wrappers 240
smg_comms_c_wrappers 241 fd = open("/dev/zero", O_RDWR);
smg_comms_c_wrappers 242 if( fd == -1 ) {
smg_comms_c_wrappers 243 log_error("can't open /dev/zero: %s\n", strerror(errno) );
smg_comms_c_wrappers 244 pool = (void*)-1;
smg_comms_c_wrappers 245 }
smg_comms_c_wrappers 246 else {
smg_comms_c_wrappers 247 pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
smg_comms_c_wrappers 248 MAP_PRIVATE, fd, 0);
smg_comms_c_wrappers 249 close (fd);
smg_comms_c_wrappers 250 }
smg_comms_c_wrappers 251 }
smg_comms_c_wrappers 252 #endif
smg_comms_c_wrappers 253 if( pool == (void*)-1 )
smg_comms_c_wrappers 254 log_info("can't mmap pool of %u bytes: %s - using malloc\n",
smg_comms_c_wrappers 255 (unsigned)poolsize, strerror(errno));
smg_comms_c_wrappers 256 else {
smg_comms_c_wrappers 257 pool_is_mmapped = 1;
smg_comms_c_wrappers 258 pool_okay = 1;
smg_comms_c_wrappers 259 }
smg_comms_c_wrappers 260
smg_comms_c_wrappers 261 #endif
smg_comms_c_wrappers 262 if( !pool_okay ) {
smg_comms_c_wrappers 263 pool = malloc( poolsize );
smg_comms_c_wrappers 264 if( !pool )
smg_comms_c_wrappers 265 log_fatal("can't allocate memory pool of %u bytes\n",
smg_comms_c_wrappers 266 (unsigned)poolsize);
smg_comms_c_wrappers 267 else
smg_comms_c_wrappers 268 pool_okay = 1;
smg_comms_c_wrappers 269 }
smg_comms_c_wrappers 270 lock_pool( pool, poolsize );
smg_comms_c_wrappers 271 poollen = 0;
smg_comms_c_wrappers 272 }
smg_comms_c_wrappers 273
smg_comms_c_wrappers 274
smg_comms_c_wrappers 275 /* concatenate unused blocks */
smg_comms_c_wrappers 276 static void
smg_comms_c_wrappers 277 compress_pool(void)
smg_comms_c_wrappers 278 {
smg_comms_c_wrappers 279 /* fixme: we really should do this */
smg_comms_c_wrappers 280 }
smg_comms_c_wrappers 281
smg_comms_c_wrappers 282 void
smg_comms_c_wrappers 283 secmem_set_flags( unsigned flags )
smg_comms_c_wrappers 284 {
smg_comms_c_wrappers 285 int was_susp = suspend_warning;
smg_comms_c_wrappers 286
smg_comms_c_wrappers 287 no_warning = flags & 1;
smg_comms_c_wrappers 288 suspend_warning = flags & 2;
smg_comms_c_wrappers 289
smg_comms_c_wrappers 290 /* and now issue the warning if it is not longer suspended */
smg_comms_c_wrappers 291 if( was_susp && !suspend_warning && show_warning ) {
smg_comms_c_wrappers 292 show_warning = 0;
smg_comms_c_wrappers 293 print_warn();
smg_comms_c_wrappers 294 }
smg_comms_c_wrappers 295 }
smg_comms_c_wrappers 296
smg_comms_c_wrappers 297 unsigned
smg_comms_c_wrappers 298 secmem_get_flags(void)
smg_comms_c_wrappers 299 {
smg_comms_c_wrappers 300 unsigned flags;
smg_comms_c_wrappers 301
smg_comms_c_wrappers 302 flags = no_warning ? 1:0;
smg_comms_c_wrappers 303 flags |= suspend_warning ? 2:0;
smg_comms_c_wrappers 304 return flags;
smg_comms_c_wrappers 305 }
smg_comms_c_wrappers 306
smg_comms_c_wrappers 307 /* Returns 1 if memory was locked, 0 if not. */
smg_comms_c_wrappers 308 int
smg_comms_c_wrappers 309 secmem_init( size_t n )
smg_comms_c_wrappers 310 {
smg_comms_c_wrappers 311 if( !n ) {
smg_comms_c_wrappers 312 #ifdef USE_CAPABILITIES
smg_comms_c_wrappers 313 /* drop all capabilities */
smg_comms_c_wrappers 314 cap_set_proc( cap_from_text("all-eip") );
smg_comms_c_wrappers 315 #elif !defined(HAVE_DOSISH_SYSTEM)
smg_comms_c_wrappers 316 uid_t uid;
smg_comms_c_wrappers 317 disable_secmem=1;
smg_comms_c_wrappers 318 uid = getuid();
smg_comms_c_wrappers 319 if( uid != geteuid() ) {
smg_comms_c_wrappers 320 if( setuid( uid ) || getuid() != geteuid() || !setuid(0) )
smg_comms_c_wrappers 321 log_fatal("failed to drop setuid\n" );
smg_comms_c_wrappers 322 }
smg_comms_c_wrappers 323 #endif
smg_comms_c_wrappers 324 }
smg_comms_c_wrappers 325 else {
smg_comms_c_wrappers 326 if( n < DEFAULT_POOLSIZE )
smg_comms_c_wrappers 327 n = DEFAULT_POOLSIZE;
smg_comms_c_wrappers 328 if( !pool_okay )
smg_comms_c_wrappers 329 init_pool(n);
smg_comms_c_wrappers 330 else
smg_comms_c_wrappers 331 log_error("Oops, secure memory pool already initialized\n");
smg_comms_c_wrappers 332 }
smg_comms_c_wrappers 333
smg_comms_c_wrappers 334 return !show_warning;
smg_comms_c_wrappers 335 }
smg_comms_c_wrappers 336
smg_comms_c_wrappers 337
smg_comms_c_wrappers 338 void *
smg_comms_c_wrappers 339 secmem_malloc( size_t size )
smg_comms_c_wrappers 340 {
smg_comms_c_wrappers 341 MEMBLOCK *mb, *mb2;
smg_comms_c_wrappers 342 int compressed=0;
smg_comms_c_wrappers 343
smg_comms_c_wrappers 344 if( !pool_okay ) {
smg_comms_c_wrappers 345 log_info(
smg_comms_c_wrappers 346 "operation is not possible without initialized secure memory\n");
smg_comms_c_wrappers 347 log_info("(you may have used the wrong program for this task)\n");
smg_comms_c_wrappers 348 exit(2);
smg_comms_c_wrappers 349 }
smg_comms_c_wrappers 350 if( show_warning && !suspend_warning ) {
smg_comms_c_wrappers 351 show_warning = 0;
smg_comms_c_wrappers 352 print_warn();
smg_comms_c_wrappers 353 }
smg_comms_c_wrappers 354
smg_comms_c_wrappers 355 /* Blocks are always a multiple of 32. Note that we allocate an
smg_comms_c_wrappers 356 extra of the size of an entire MEMBLOCK. This is required
smg_comms_c_wrappers 357 becuase we do not only need the SIZE info but also extra space
smg_comms_c_wrappers 358 to chain up unused memory blocks. */
smg_comms_c_wrappers 359 size += sizeof(MEMBLOCK);
smg_comms_c_wrappers 360 size = ((size + 31) / 32) * 32;
smg_comms_c_wrappers 361
smg_comms_c_wrappers 362 retry:
smg_comms_c_wrappers 363 /* try to get it from the used blocks */
smg_comms_c_wrappers 364 for(mb = unused_blocks,mb2=NULL; mb; mb2=mb, mb = mb->u.next )
smg_comms_c_wrappers 365 if( mb->size >= size ) {
smg_comms_c_wrappers 366 if( mb2 )
smg_comms_c_wrappers 367 mb2->u.next = mb->u.next;
smg_comms_c_wrappers 368 else
smg_comms_c_wrappers 369 unused_blocks = mb->u.next;
smg_comms_c_wrappers 370 goto leave;
smg_comms_c_wrappers 371 }
smg_comms_c_wrappers 372 /* allocate a new block */
smg_comms_c_wrappers 373 if( (poollen + size <= poolsize) ) {
smg_comms_c_wrappers 374 mb = (void*)((char*)pool + poollen);
smg_comms_c_wrappers 375 poollen += size;
smg_comms_c_wrappers 376 mb->size = size;
smg_comms_c_wrappers 377 }
smg_comms_c_wrappers 378 else if( !compressed ) {
smg_comms_c_wrappers 379 compressed=1;
smg_comms_c_wrappers 380 compress_pool();
smg_comms_c_wrappers 381 goto retry;
smg_comms_c_wrappers 382 }
smg_comms_c_wrappers 383 else
smg_comms_c_wrappers 384 return NULL;
smg_comms_c_wrappers 385
smg_comms_c_wrappers 386 leave:
smg_comms_c_wrappers 387 cur_alloced += mb->size;
smg_comms_c_wrappers 388 cur_blocks++;
smg_comms_c_wrappers 389 if( cur_alloced > max_alloced )
smg_comms_c_wrappers 390 max_alloced = cur_alloced;
smg_comms_c_wrappers 391 if( cur_blocks > max_blocks )
smg_comms_c_wrappers 392 max_blocks = cur_blocks;
smg_comms_c_wrappers 393
smg_comms_c_wrappers 394 return &mb->u.aligned.c;
smg_comms_c_wrappers 395 }
smg_comms_c_wrappers 396
smg_comms_c_wrappers 397
smg_comms_c_wrappers 398 void *
smg_comms_c_wrappers 399 secmexrealloc( void *p, size_t newsize )
smg_comms_c_wrappers 400 {
smg_comms_c_wrappers 401 MEMBLOCK *mb;
smg_comms_c_wrappers 402 size_t size;
smg_comms_c_wrappers 403 void *a;
smg_comms_c_wrappers 404
smg_comms_c_wrappers 405 mb = (MEMBLOCK*)((char*)p - ((size_t) &((MEMBLOCK*)0)->u.aligned.c));
smg_comms_c_wrappers 406 size = mb->size;
smg_comms_c_wrappers 407 if (size < sizeof(MEMBLOCK))
smg_comms_c_wrappers 408 log_bug ("secure memory corrupted at block %p\n", (void *)mb);
smg_comms_c_wrappers 409 size -= ((size_t) &((MEMBLOCK*)0)->u.aligned.c);
smg_comms_c_wrappers 410
smg_comms_c_wrappers 411 if( newsize <= size )
smg_comms_c_wrappers 412 return p; /* It is easier not to shrink the memory. */
smg_comms_c_wrappers 413 a = secmem_malloc( newsize );
smg_comms_c_wrappers 414 if ( a ) {
smg_comms_c_wrappers 415 memcpy(a, p, size);
smg_comms_c_wrappers 416 memset((char*)a+size, 0, newsize-size);
smg_comms_c_wrappers 417 secmem_free(p);
smg_comms_c_wrappers 418 }
smg_comms_c_wrappers 419 return a;
smg_comms_c_wrappers 420 }
smg_comms_c_wrappers 421
smg_comms_c_wrappers 422
smg_comms_c_wrappers 423 void
smg_comms_c_wrappers 424 secmem_free( void *a )
smg_comms_c_wrappers 425 {
smg_comms_c_wrappers 426 MEMBLOCK *mb;
smg_comms_c_wrappers 427 size_t size;
smg_comms_c_wrappers 428
smg_comms_c_wrappers 429 if( !a )
smg_comms_c_wrappers 430 return;
smg_comms_c_wrappers 431
smg_comms_c_wrappers 432 mb = (MEMBLOCK*)((char*)a - ((size_t) &((MEMBLOCK*)0)->u.aligned.c));
smg_comms_c_wrappers 433 size = mb->size;
smg_comms_c_wrappers 434 /* This does not make much sense: probably this memory is held in the
smg_comms_c_wrappers 435 * cache. We do it anyway: */
smg_comms_c_wrappers 436 wipememory2(mb, 0xff, size );
smg_comms_c_wrappers 437 wipememory2(mb, 0xaa, size );
smg_comms_c_wrappers 438 wipememory2(mb, 0x55, size );
smg_comms_c_wrappers 439 wipememory2(mb, 0x00, size );
smg_comms_c_wrappers 440 mb->size = size;
smg_comms_c_wrappers 441 mb->u.next = unused_blocks;
smg_comms_c_wrappers 442 unused_blocks = mb;
smg_comms_c_wrappers 443 cur_blocks--;
smg_comms_c_wrappers 444 cur_alloced -= size;
smg_comms_c_wrappers 445 }
smg_comms_c_wrappers 446
smg_comms_c_wrappers 447
smg_comms_c_wrappers 448 /* Check whether P points into the pool. */
smg_comms_c_wrappers 449 static int
smg_comms_c_wrappers 450 ptr_into_pool_p (const void *p)
smg_comms_c_wrappers 451 {
smg_comms_c_wrappers 452 /* We need to convert pointers to addresses. This is required by
smg_comms_c_wrappers 453 C-99 6.5.8 to avoid undefined behaviour. Using size_t is at
smg_comms_c_wrappers 454 least only implementation defined. See also
smg_comms_c_wrappers 455 http://lists.gnupg.org/pipermail/gcrypt-devel/2007-February/001102.html
smg_comms_c_wrappers 456 */
smg_comms_c_wrappers 457 size_t p_addr = (size_t)p;
smg_comms_c_wrappers 458 size_t pool_addr = (size_t)pool;
smg_comms_c_wrappers 459
smg_comms_c_wrappers 460 return p_addr >= pool_addr && p_addr < pool_addr+poolsize;
smg_comms_c_wrappers 461 }
smg_comms_c_wrappers 462
smg_comms_c_wrappers 463
smg_comms_c_wrappers 464 int
smg_comms_c_wrappers 465 m_is_secure( const void *p )
smg_comms_c_wrappers 466 {
smg_comms_c_wrappers 467 return pool_okay && ptr_into_pool_p (p);
smg_comms_c_wrappers 468 }
smg_comms_c_wrappers 469
smg_comms_c_wrappers 470
smg_comms_c_wrappers 471
smg_comms_c_wrappers 472 /****************
smg_comms_c_wrappers 473 * Warning: This code might be called by an interrupt handler
smg_comms_c_wrappers 474 * and frankly, there should really be such a handler,
smg_comms_c_wrappers 475 * to make sure that the memory is wiped out.
smg_comms_c_wrappers 476 * We hope that the OS wipes out mlocked memory after
smg_comms_c_wrappers 477 * receiving a SIGKILL - it really should do so, otherwise
smg_comms_c_wrappers 478 * there is no chance to get the secure memory cleaned.
smg_comms_c_wrappers 479 */
smg_comms_c_wrappers 480 void
smg_comms_c_wrappers 481 secmem_term()
smg_comms_c_wrappers 482 {
smg_comms_c_wrappers 483 if( !pool_okay )
smg_comms_c_wrappers 484 return;
smg_comms_c_wrappers 485
smg_comms_c_wrappers 486 wipememory2( pool, 0xff, poolsize);
smg_comms_c_wrappers 487 wipememory2( pool, 0xaa, poolsize);
smg_comms_c_wrappers 488 wipememory2( pool, 0x55, poolsize);
smg_comms_c_wrappers 489 wipememory2( pool, 0x00, poolsize);
smg_comms_c_wrappers 490 #ifdef HAVE_MMAP
smg_comms_c_wrappers 491 if( pool_is_mmapped )
smg_comms_c_wrappers 492 munmap( pool, poolsize );
smg_comms_c_wrappers 493 #endif
smg_comms_c_wrappers 494 pool = NULL;
smg_comms_c_wrappers 495 pool_okay = 0;
smg_comms_c_wrappers 496 poolsize=0;
smg_comms_c_wrappers 497 poollen=0;
smg_comms_c_wrappers 498 unused_blocks=NULL;
smg_comms_c_wrappers 499 }
smg_comms_c_wrappers 500
smg_comms_c_wrappers 501
smg_comms_c_wrappers 502 void
smg_comms_c_wrappers 503 secmem_dump_stats()
smg_comms_c_wrappers 504 {
smg_comms_c_wrappers 505 if( disable_secmem )
smg_comms_c_wrappers 506 return;
smg_comms_c_wrappers 507 fprintf(stderr,
smg_comms_c_wrappers 508 "secmem usage: %u/%u bytes in %u/%u blocks of pool %lu/%lu\n",
smg_comms_c_wrappers 509 cur_alloced, max_alloced, cur_blocks, max_blocks,
smg_comms_c_wrappers 510 (ulong)poollen, (ulong)poolsize );
smg_comms_c_wrappers 511 }