Mercurial > hg > octave-nkf > gnulib-hg
view lib/idpriv-drop.c @ 12028:a65ac3b41872
openat: simplify use of at-func.c
* lib/at-func.c (includes): Include prerequisites here, to
simplify requirements on client files.
* lib/openat-priv.h: Add double-inclusion guard.
* lib/faccessat.c (includes): Simplify.
* lib/fchmodat.c (includes): Likewise.
* lib/fchownat.c (includes): Likewise.
* lib/mkdirat.c (includes): Likewise.
* lib/mkfifoat.c (includes): Likewise.
* lib/symlinkat.c (includes): Likewise.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Sat, 19 Sep 2009 08:03:45 -0600 |
parents | 1d540dc13d74 |
children | e8d2c6fc33ad |
line wrap: on
line source
/* Dropping uid/gid privileges of the current process permanently. Copyright (C) 2009 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; }