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