1 --- libgamin/gam_fork.c.orig 2007-07-04 06:36:48.000000000 -0700 2 +++ libgamin/gam_fork.c 2013-02-16 20:37:31.298176973 -0800 3 @@ -42,6 +42,78 @@ 4 return NULL; 5 } 6 7 +#ifdef RUN_AS_EUID 8 +/** 9 + * gamin_drop_privileges 10 + * 11 + * Attempt to drop privileges to another user and group before forking 12 + * a copy of the gam server 13 + * 14 + * Return 0 in case of success or -1 in case of detected error. 15 + */ 16 +int 17 +gamin_drop_privileges(int to_uid, int to_gid) 18 +{ 19 + GAM_DEBUG(DEBUG_INFO, "Dropping privileges to %d:%d before forking server\n", to_uid, to_gid); 20 + 21 + /* Get the current real user and group */ 22 + int from_uid = getuid(); 23 + int from_gid = getgid(); 24 + 25 + /* Make sure we were able to get the user and group values */ 26 + if ( from_uid == -1 || to_uid == -1 || from_gid == -1 || to_gid == -1 ) { 27 + gam_error(DEBUG_INFO, "failed to get user or group info, unable to drop privileges\n"); 28 + return(-1); 29 + } 30 + 31 + /* Refuse to run setuid if it would escalate privileges */ 32 + if ( from_uid != 0 && to_uid == 0 ) 33 + { 34 + gam_error(DEBUG_INFO, "refusing to escalate user privileges from=%d to=%d\n", from_uid, to_uid); 35 + return(-1); 36 + } 37 + 38 + /* Refuse to run setgid if it would escalate privileges */ 39 + if ( from_gid != 0 && to_gid == 0 ) 40 + { 41 + gam_error(DEBUG_INFO, "refusing to escalate group privileges from=%d to=%d\n", from_gid, to_gid); 42 + return(-1); 43 + } 44 + 45 + /* Run setuid to drop privileges to the effective user */ 46 + if ( from_uid != to_uid ) { 47 + GAM_DEBUG(DEBUG_INFO, "Attempting setuid from=%d to=%d\n", from_uid, to_uid); 48 + 49 + /* run setuid and check for errors */ 50 + if (setuid(to_uid) == -1) { 51 + gam_error(DEBUG_INFO, "failed to run setuid from=%d to=%d\n", from_uid, to_uid); 52 + return(-1); 53 + } 54 + } 55 + else { 56 + GAM_DEBUG(DEBUG_INFO, "Already running as effective user, skipping setuid\n"); 57 + } 58 + 59 + /* Run setgid to drop privileges to the effective group */ 60 + if ( from_gid != to_gid ) { 61 + GAM_DEBUG(DEBUG_INFO, "Attempting setgid from=%d to=%d\n", from_gid, to_gid); 62 + 63 + /* run setuid and check for errors */ 64 + if (setgid(to_gid) == -1) { 65 + gam_error(DEBUG_INFO, "failed to run setgid from=%d to=%d\n", from_gid, to_gid); 66 + return(-1); 67 + } 68 + } 69 + else { 70 + GAM_DEBUG(DEBUG_INFO, "Already running as effective group, skipping setgid\n"); 71 + } 72 + 73 + GAM_DEBUG(DEBUG_INFO, "Succeeded in dropping privileges from %d:%d to %d:%d\n", from_uid, from_gid, to_uid, to_gid); 74 + 75 + return(0); 76 +} 77 +#endif 78 + 79 /** 80 * gamin_fork_server: 81 * @fam_client_id: the client ID string to use 82 @@ -71,6 +143,13 @@ 83 long open_max; 84 long i; 85 86 +#ifdef RUN_AS_EUID 87 + /* Drop privileges to the current effective uid/gid and return on failure */ 88 + if(gamin_drop_privileges( geteuid(), getegid() ) == -1) { 89 + return(-1); 90 + } 91 +#endif 92 + 93 /* don't hold open fd opened from the client of the library */ 94 open_max = sysconf (_SC_OPEN_MAX); 95 for (i = 0; i < open_max; i++) 96