diff options
Diffstat (limited to 'gnulib/lib/idpriv-drop.c')
m--------- | gnulib | 0 | ||||
-rw-r--r-- | gnulib/lib/idpriv-drop.c | 129 |
2 files changed, 129 insertions, 0 deletions
diff --git a/gnulib b/gnulib deleted file mode 160000 -Subproject 4fc10daa05477586fea99b6b3ca02a87d1102fa diff --git a/gnulib/lib/idpriv-drop.c b/gnulib/lib/idpriv-drop.c new file mode 100644 index 00000000..30ce5a4f --- /dev/null +++ b/gnulib/lib/idpriv-drop.c @@ -0,0 +1,129 @@ +/* Dropping uid/gid privileges of the current process permanently. + Copyright (C) 2009, 2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "idpriv.h" + +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> + +int +idpriv_drop (void) +{ +#if HAVE_GETUID + int uid = getuid (); +#endif +#if HAVE_GETGID + int gid = getgid (); +#endif + + /* Drop the gid privilege first, because in some cases the gid privilege + cannot be dropped after the uid privilege has been dropped. */ + + /* This is for executables that have the setgid bit set. */ +#if HAVE_SETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */ + /* This code is needed: In particular, on HP-UX 11.11, setregid (gid, gid) + may leave the saved gid as 0. See also the comment below regarding + setresuid. */ + if (setresgid (gid, gid, gid) < 0) + return -1; +#elif HAVE_SETREGID /* MacOS X, NetBSD, AIX, IRIX, Solaris, OSF/1, Cygwin */ + if (setregid (gid, gid) < 0) + return -1; +#elif HAVE_SETEGID /* Solaris 2.4 */ + if (setegid (gid) < 0) + return -1; +#endif + + /* This is for executables that have the setuid bit set. */ +#if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */ + /* On systems which have setresuid(), we use it instead of setreuid(), + because + <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf> + says about setreuid(): "The rule by which the saved uid id is modified + is complicated." Similarly, <http://unixpapa.com/incnote/setuid.html> + says about setreuid(): "What exactly happens to the saved UID when this + is used seems to vary a lot." */ + if (setresuid (uid, uid, uid) < 0) + return -1; +#elif HAVE_SETREUID /* MacOS X, NetBSD, AIX, IRIX, Solaris, OSF/1, Cygwin */ + if (setreuid (uid, uid) < 0) + return -1; +#elif HAVE_SETEUID /* Solaris 2.4 */ + if (seteuid (uid) < 0) + return -1; +#endif + + /* Verify that the privileges have really been dropped. + This verification is here for security reasons. Doesn't matter if it + takes a couple of system calls. + On Solaris (which has saved uids and gids but no getresuid, getresgid + functions), we could read /proc/<pid>/cred and verify the saved uid and + gid found there. But it's not clear to me when to interpret the file as a + 'prcred_t' and when as a 'prcred32_t'. + <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf> + section 8.1.3 also recommends to use a setreuid call as a probe, but + this call would unexpectedly succeed (and the verification thus fail) + on Linux if the process has the CAP_SETUID capability. + When the verification fails, it indicates that we need to use different + API in the code above. Therefore 'abort ()', not 'return -1'. */ +#if HAVE_GETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */ + { + uid_t real; + uid_t effective; + uid_t saved; + if (getresuid (&real, &effective, &saved) < 0 + || real != uid + || effective != uid + || saved != uid) + abort (); + } +#else +# if HAVE_GETEUID + if (geteuid () != uid) + abort (); +# endif +# if HAVE_GETUID + if (getuid () != uid) + abort (); +# endif +#endif +#if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */ + { + gid_t real; + gid_t effective; + gid_t saved; + if (getresgid (&real, &effective, &saved) < 0 + || real != gid + || effective != gid + || saved != gid) + abort (); + } +#else +# if HAVE_GETEGID + if (getegid () != gid) + abort (); +# endif +# if HAVE_GETGID + if (getgid () != gid) + abort (); +# endif +#endif + + return 0; +} |