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