--- gnupg-1.4.7/g10/gpg.c.orig 2007-03-05 02:02:57.000000000 -0700 +++ gnupg-1.4.7/g10/gpg.c 2007-03-07 13:59:40.000000000 -0700 @@ -72,6 +72,11 @@ #endif +#ifdef USE_CAPABILITIES +#include <sys/capability.h> +#include <sys/prctl.h> +#endif + enum cmd_and_opt_values { aNull = 0, @@ -1768,6 +1773,10 @@ main (int argc, char **argv ) #ifdef USE_SHM_COPROCESSING ulong requested_shm_size=0; #endif +#ifdef USE_CAPABILITIES + uid_t curr_uid; + cap_t caps; +#endif #ifdef __riscos__ opt.lock_once = 1; @@ -1780,6 +1789,33 @@ main (int argc, char **argv ) * when adding any stuff between here and the call to * secmem_init() somewhere after the option parsing */ + + /* if we use capabilities and run as root, we can immediately setuid back + * to the normal user and only keep CAP_IPC_LOCK until the shared memory is + * set up. + */ +#ifdef USE_CAPABILITIES + curr_uid = getuid(); + if( curr_uid && !geteuid() ) { /* we are setuid root */ + if( prctl( PR_SET_KEEPCAPS, 1, 0, 0, 0 ) ) { + perror( "main(): could not keep capabilities" ); + return -100; + } + + if( setuid( curr_uid ) ) { + perror( "main(): could not set user id" ); + return -100; + } + + caps = cap_from_text( "cap_ipc_lock=p" ); + if( cap_set_proc( caps ) ) { + perror( "main(): could not install capabilities" ); + return -100; + } + cap_free( caps ); + } +#endif + log_set_name("gpg"); secure_randoxmalloc(); /* put random number into secure memory */ may_coredump = disable_core_dumps(); @@ -1906,7 +1942,7 @@ main (int argc, char **argv ) } #endif /* initialize the secure memory. */ - got_secmem=secmem_init( 32768 ); + got_secmem=secmem_init( 32768 ); /* this will drop all remaining privileges */ maybe_setuid = 0; /* Okay, we are now working under our real uid */