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