1 /* Dropping uid/gid privileges of the current process temporarily.
2 Copyright (C) 2009-2017 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include <sys/types.h>
26 /* The privileged uid and gid that the process had earlier. */
28 static int saved_uid
= -1;
31 static int saved_gid
= -1;
35 idpriv_temp_drop (void)
37 #if HAVE_GETEUID && HAVE_GETEGID && (HAVE_SETRESUID || HAVE_SETREUID) && (HAVE_SETRESGID || HAVE_SETREGID)
41 /* Find out about the privileged uid and gid at the first call. */
43 saved_uid
= geteuid ();
45 saved_gid
= getegid ();
47 /* Drop the gid privilege first, because in some cases the gid privilege
48 cannot be dropped after the uid privilege has been dropped. */
50 /* This is for executables that have the setgid bit set. */
51 # if HAVE_SETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
52 if (setresgid (-1, gid
, saved_gid
) < 0)
54 # else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
55 if (setregid (-1, gid
) < 0)
59 /* This is for executables that have the setuid bit set. */
60 # if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
61 /* See <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
63 if (setresuid (-1, uid
, saved_uid
) < 0)
65 # else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
66 if (setreuid (-1, uid
) < 0)
70 /* Verify that the privileges have really been dropped.
71 This verification is here for security reasons. Doesn't matter if it
72 takes a couple of system calls.
73 When the verification fails, it indicates that we need to use different
74 API in the code above. Therefore 'abort ()', not 'return -1'. */
75 # if HAVE_GETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
80 if (getresuid (&real
, &effective
, &saved
) < 0
83 || saved
!= saved_uid
)
88 if (geteuid () != uid
)
94 # if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
99 if (getresgid (&real
, &effective
, &saved
) < 0
102 || saved
!= saved_gid
)
107 if (getegid () != gid
)
110 if (getgid () != gid
)
122 idpriv_temp_restore (void)
124 #if HAVE_GETEUID && HAVE_GETEGID && (HAVE_SETRESUID || HAVE_SETREUID) && (HAVE_SETRESGID || HAVE_SETREGID)
128 if (saved_uid
== -1 || saved_gid
== -1)
129 /* Caller error: idpriv_temp_drop was never invoked. */
132 /* Acquire the gid privilege last, because in some cases the gid privilege
133 cannot be acquired before the uid privilege has been acquired. */
135 /* This is for executables that have the setuid bit set. */
136 # if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
137 /* See <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
139 if (setresuid (-1, saved_uid
, -1) < 0)
141 # else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
142 if (setreuid (-1, saved_uid
) < 0)
146 /* This is for executables that have the setgid bit set. */
147 # if HAVE_SETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
148 if (setresgid (-1, saved_gid
, -1) < 0)
150 # else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
151 if (setregid (-1, saved_gid
) < 0)
155 /* Verify that the privileges have really been acquired.
156 This verification is here for security reasons. Doesn't matter if it
157 takes a couple of system calls.
158 When the verification fails, it indicates that we need to use different
159 API in the code above. Therefore 'abort ()', not 'return -1'. */
160 # if HAVE_GETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
165 if (getresuid (&real
, &effective
, &saved
) < 0
167 || effective
!= saved_uid
168 || saved
!= saved_uid
)
173 if (geteuid () != saved_uid
)
176 if (getuid () != uid
)
179 # if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
184 if (getresgid (&real
, &effective
, &saved
) < 0
186 || effective
!= saved_gid
187 || saved
!= saved_gid
)
192 if (getegid () != saved_gid
)
195 if (getgid () != gid
)