summaryrefslogtreecommitdiff
path: root/gnulib/lib
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2010-12-19 16:11:13 +0000
committerColin Watson <cjwatson@debian.org>2010-12-19 16:11:13 +0000
commitf7658f51c254ce16a564d670880d828a00f3a3fc (patch)
tree5927055ee2e7b194923fa3efef638a6cca670aad /gnulib/lib
parent2e6a28c3f67527a4a1eb87a26a011bb62d95ee09 (diff)
* gnulib: Import idpriv-drop and idpriv-droptemp modules.
* configure.ac: Stop checking for seteuid, setreuid, and setresuid. * lib/security.c (POSIX_SAVED_IDS, SET_EUID, SWAP_UIDS): Remove in favour of idpriv.h. (drop_effective_privs): Use idpriv_temp_drop. (regain_effective_privs): Use idpriv_temp_restore. (do_system_drop_privs): Use idpriv_drop. Drop saved-IDs case; avoiding a fork doesn't justify having two code paths.
Diffstat (limited to 'gnulib/lib')
-rw-r--r--gnulib/lib/Makefile.am18
-rw-r--r--gnulib/lib/Makefile.in70
-rw-r--r--gnulib/lib/idpriv-drop.c129
-rw-r--r--gnulib/lib/idpriv-droptemp.c204
-rw-r--r--gnulib/lib/idpriv.h116
5 files changed, 504 insertions, 33 deletions
diff --git a/gnulib/lib/Makefile.am b/gnulib/lib/Makefile.am
index 7e792638..4bd09024 100644
--- a/gnulib/lib/Makefile.am
+++ b/gnulib/lib/Makefile.am
@@ -9,7 +9,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gnulib/lib --m4-base=gnulib/m4 --po-base=gnulib/po --doc-base=doc --tests-base=tests --aux-dir=tools --libtool --macro-prefix=gl --po-domain=man-db argp canonicalize dirname error fnmatch-gnu getopt-gnu gettext glob lib-ignore localcharset lock minmax mkdtemp mkstemp regex rename setenv sigaction signal sigprocmask strerror strsep unsetenv xalloc xgetcwd xstrndup xvasprintf
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gnulib/lib --m4-base=gnulib/m4 --po-base=gnulib/po --doc-base=doc --tests-base=tests --aux-dir=tools --libtool --macro-prefix=gl --po-domain=man-db argp canonicalize dirname error fnmatch-gnu getopt-gnu gettext glob idpriv-drop idpriv-droptemp lib-ignore localcharset lock minmax mkdtemp mkstemp regex rename setenv sigaction signal sigprocmask strerror strsep unsetenv xalloc xgetcwd xstrndup xvasprintf
AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects
@@ -642,6 +642,22 @@ EXTRA_DIST += $(top_srcdir)/tools/config.rpath
## end gnulib module havelib
+## begin gnulib module idpriv-drop
+
+libgnu_la_SOURCES += idpriv-drop.c
+
+EXTRA_DIST += idpriv.h
+
+## end gnulib module idpriv-drop
+
+## begin gnulib module idpriv-droptemp
+
+libgnu_la_SOURCES += idpriv-droptemp.c
+
+EXTRA_DIST += idpriv.h
+
+## end gnulib module idpriv-droptemp
+
## begin gnulib module intprops
diff --git a/gnulib/lib/Makefile.in b/gnulib/lib/Makefile.in
index bf012ce1..a1f8eb86 100644
--- a/gnulib/lib/Makefile.in
+++ b/gnulib/lib/Makefile.in
@@ -24,7 +24,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gnulib/lib --m4-base=gnulib/m4 --po-base=gnulib/po --doc-base=doc --tests-base=tests --aux-dir=tools --libtool --macro-prefix=gl --po-domain=man-db argp canonicalize dirname error fnmatch-gnu getopt-gnu gettext glob lib-ignore localcharset lock minmax mkdtemp mkstemp regex rename setenv sigaction signal sigprocmask strerror strsep unsetenv xalloc xgetcwd xstrndup xvasprintf
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gnulib/lib --m4-base=gnulib/m4 --po-base=gnulib/po --doc-base=doc --tests-base=tests --aux-dir=tools --libtool --macro-prefix=gl --po-domain=man-db argp canonicalize dirname error fnmatch-gnu getopt-gnu gettext glob idpriv-drop idpriv-droptemp lib-ignore localcharset lock minmax mkdtemp mkstemp regex rename setenv sigaction signal sigprocmask strerror strsep unsetenv xalloc xgetcwd xstrndup xvasprintf
@@ -104,6 +104,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/man-bdb.m4 \
$(top_srcdir)/gnulib/m4/gnulib-comp.m4 \
$(top_srcdir)/gnulib/m4/hash.m4 \
$(top_srcdir)/gnulib/m4/iconv.m4 \
+ $(top_srcdir)/gnulib/m4/idpriv.m4 \
$(top_srcdir)/gnulib/m4/include_next.m4 \
$(top_srcdir)/gnulib/m4/inline.m4 \
$(top_srcdir)/gnulib/m4/intlmacosx.m4 \
@@ -222,9 +223,10 @@ am_libgnu_la_OBJECTS = areadlink-with-size.lo argp-ba.lo argp-eexst.lo \
argp-fmtstream.lo argp-fs-xinl.lo argp-help.lo argp-parse.lo \
argp-pin.lo argp-pv.lo argp-pvh.lo argp-xinl.lo close-hook.lo \
exitfail.lo file-set.lo hash-pjw.lo hash-triple.lo \
- localcharset.lo glthread/lock.lo malloca.lo openat-die.lo \
- strnlen1.lo glthread/threadlib.lo xalloc-die.lo xstrndup.lo \
- xvasprintf.lo xasprintf.lo
+ idpriv-drop.lo idpriv-droptemp.lo localcharset.lo \
+ glthread/lock.lo malloca.lo openat-die.lo strnlen1.lo \
+ glthread/threadlib.lo xalloc-die.lo xstrndup.lo xvasprintf.lo \
+ xasprintf.lo
libgnu_la_OBJECTS = $(am_libgnu_la_OBJECTS)
AM_V_lt = $(am__v_lt_$(V))
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
@@ -1066,30 +1068,31 @@ EXTRA_DIST = alloca.c alloca.in.h areadlink.h \
getcwd.c getdtablesize.c getlogin_r.c getopt.c getopt.in.h \
getopt1.c getopt_int.h $(top_srcdir)/tools/config.rpath \
gettimeofday.c glob-libc.h glob.c glob.in.h hash.c hash.h \
- hash-triple.h $(top_srcdir)/tools/config.rpath intprops.h \
- langinfo.in.h lchown.c config.charset ref-add.sin ref-del.sin \
- lstat.c malloc.c malloc.c malloca.h malloca.valgrind mbrtowc.c \
- mbsinit.c mbsrtowcs-state.c mbsrtowcs.c memchr.c \
- memchr.valgrind mempcpy.c memrchr.c mkdir.c mkdtemp.c \
- mkstemp.c nl_langinfo.c open.c at-func.c fchmodat.c fchownat.c \
- fstatat.c mkdirat.c openat-priv.h openat-proc.c openat.c \
- openat.h unlinkat.c pathmax.h rawmemchr.c rawmemchr.valgrind \
- readlink.c realloc.c regcomp.c regex.c regex.h \
- regex_internal.c regex_internal.h regexec.c rename.c rmdir.c \
- same.c same.h same-inode.h save-cwd.c save-cwd.h setenv.c \
- sig-handler.h sigaction.c signal.in.h sigprocmask.c sleep.c \
- stat.c stdarg.in.h stdbool.in.h stddef.in.h stdint.in.h \
- stdio-write.c stdio.in.h stdlib.in.h strcasecmp.c \
- strncasecmp.c strchrnul.c strchrnul.valgrind strdup.c streq.h \
- strerror.c string.in.h strings.in.h strndup.c strnlen.c \
- strsep.c sys_stat.in.h sys_time.in.h sysexits.in.h tempname.c \
- tempname.h $(top_srcdir)/tools/config.rpath time.in.h \
- unistd.in.h dup-safer.c fd-safer.c pipe-safer.c unistd--.h \
- unistd-safer.h unlink.c unsetenv.c asnprintf.c float+.h \
- printf-args.c printf-args.h printf-parse.c printf-parse.h \
- vasnprintf.c vasnprintf.h asprintf.c vasprintf.c vsnprintf.c \
- $(top_srcdir)/tools/warn-on-use.h wchar.in.h wcrtomb.c \
- wctype.in.h xalloc.h xmalloc.c xgetcwd.c xgetcwd.h xalloc.h
+ hash-triple.h $(top_srcdir)/tools/config.rpath idpriv.h \
+ idpriv.h intprops.h langinfo.in.h lchown.c config.charset \
+ ref-add.sin ref-del.sin lstat.c malloc.c malloc.c malloca.h \
+ malloca.valgrind mbrtowc.c mbsinit.c mbsrtowcs-state.c \
+ mbsrtowcs.c memchr.c memchr.valgrind mempcpy.c memrchr.c \
+ mkdir.c mkdtemp.c mkstemp.c nl_langinfo.c open.c at-func.c \
+ fchmodat.c fchownat.c fstatat.c mkdirat.c openat-priv.h \
+ openat-proc.c openat.c openat.h unlinkat.c pathmax.h \
+ rawmemchr.c rawmemchr.valgrind readlink.c realloc.c regcomp.c \
+ regex.c regex.h regex_internal.c regex_internal.h regexec.c \
+ rename.c rmdir.c same.c same.h same-inode.h save-cwd.c \
+ save-cwd.h setenv.c sig-handler.h sigaction.c signal.in.h \
+ sigprocmask.c sleep.c stat.c stdarg.in.h stdbool.in.h \
+ stddef.in.h stdint.in.h stdio-write.c stdio.in.h stdlib.in.h \
+ strcasecmp.c strncasecmp.c strchrnul.c strchrnul.valgrind \
+ strdup.c streq.h strerror.c string.in.h strings.in.h strndup.c \
+ strnlen.c strsep.c sys_stat.in.h sys_time.in.h sysexits.in.h \
+ tempname.c tempname.h $(top_srcdir)/tools/config.rpath \
+ time.in.h unistd.in.h dup-safer.c fd-safer.c pipe-safer.c \
+ unistd--.h unistd-safer.h unlink.c unsetenv.c asnprintf.c \
+ float+.h printf-args.c printf-args.h printf-parse.c \
+ printf-parse.h vasnprintf.c vasnprintf.h asprintf.c \
+ vasprintf.c vsnprintf.c $(top_srcdir)/tools/warn-on-use.h \
+ wchar.in.h wcrtomb.c wctype.in.h xalloc.h xmalloc.c xgetcwd.c \
+ xgetcwd.h xalloc.h
# The BUILT_SOURCES created by this Makefile snippet are not used via #include
# statements but through direct file reference. Therefore this snippet must be
@@ -1140,10 +1143,11 @@ libgnu_la_SOURCES = areadlink-with-size.c argp.h argp-ba.c \
argp-help.c argp-namefrob.h argp-parse.c argp-pin.c argp-pv.c \
argp-pvh.c argp-xinl.c bitrotate.h close-hook.c exitfail.c \
file-set.c gettext.h hash-pjw.h hash-pjw.c hash-triple.c \
- localcharset.h localcharset.c glthread/lock.h glthread/lock.c \
- malloca.c minmax.h openat-die.c size_max.h strnlen1.h \
- strnlen1.c glthread/threadlib.c verify.h xalloc-die.c xsize.h \
- xstrndup.h xstrndup.c xvasprintf.h xvasprintf.c xasprintf.c
+ idpriv-drop.c idpriv-droptemp.c localcharset.h localcharset.c \
+ glthread/lock.h glthread/lock.c malloca.c minmax.h \
+ openat-die.c size_max.h strnlen1.h strnlen1.c \
+ glthread/threadlib.c verify.h xalloc-die.c xsize.h xstrndup.h \
+ xstrndup.c xvasprintf.h xvasprintf.c xasprintf.c
libgnu_la_LIBADD = $(gl_LTLIBOBJS) @LTALLOCA@
libgnu_la_DEPENDENCIES = $(gl_LTLIBOBJS) @LTALLOCA@
EXTRA_libgnu_la_SOURCES = alloca.c btowc.c canonicalize.c \
@@ -1296,6 +1300,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash-pjw.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash-triple.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idpriv-drop.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idpriv-droptemp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lchown.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localcharset.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lstat.Plo@am__quote@
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;
+}
diff --git a/gnulib/lib/idpriv-droptemp.c b/gnulib/lib/idpriv-droptemp.c
new file mode 100644
index 00000000..1c19c13d
--- /dev/null
+++ b/gnulib/lib/idpriv-droptemp.c
@@ -0,0 +1,204 @@
+/* Dropping uid/gid privileges of the current process temporarily.
+ 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 <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* The privileged uid and gid that the process had earlier. */
+#if HAVE_GETUID
+static int saved_uid = -1;
+#endif
+#if HAVE_GETGID
+static int saved_gid = -1;
+#endif
+
+int
+idpriv_temp_drop (void)
+{
+#if HAVE_GETEUID && HAVE_GETEGID && (HAVE_SETRESUID || HAVE_SETREUID) && (HAVE_SETRESGID || HAVE_SETREGID)
+ int uid = getuid ();
+ int gid = getgid ();
+
+ /* Find out about the privileged uid and gid at the first call. */
+ if (saved_uid == -1)
+ saved_uid = geteuid ();
+ if (saved_gid == -1)
+ saved_gid = getegid ();
+
+ /* 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 */
+ if (setresgid (-1, gid, saved_gid) < 0)
+ return -1;
+# else /* MacOS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
+ if (setregid (-1, gid) < 0)
+ return -1;
+# endif
+
+ /* This is for executables that have the setuid bit set. */
+# if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
+ /* See <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
+ figure 14. */
+ if (setresuid (-1, uid, saved_uid) < 0)
+ return -1;
+# else /* MacOS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
+ if (setreuid (-1, 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.
+ 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 != saved_uid)
+ abort ();
+ }
+# else
+# if HAVE_GETEUID
+ if (geteuid () != uid)
+ abort ();
+# endif
+ if (getuid () != uid)
+ abort ();
+# endif
+# if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
+ {
+ uid_t real;
+ uid_t effective;
+ uid_t saved;
+ if (getresgid (&real, &effective, &saved) < 0
+ || real != gid
+ || effective != gid
+ || saved != saved_gid)
+ abort ();
+ }
+# else
+# if HAVE_GETEGID
+ if (getegid () != gid)
+ abort ();
+# endif
+ if (getgid () != gid)
+ abort ();
+# endif
+
+ return 0;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+int
+idpriv_temp_restore (void)
+{
+#if HAVE_GETEUID && HAVE_GETEGID && (HAVE_SETRESUID || HAVE_SETREUID) && (HAVE_SETRESGID || HAVE_SETREGID)
+ int uid = getuid ();
+ int gid = getgid ();
+
+ if (saved_uid == -1 || saved_gid == -1)
+ /* Caller error: idpriv_temp_drop was never invoked. */
+ abort ();
+
+ /* Acquire the gid privilege last, because in some cases the gid privilege
+ cannot be acquired before the uid privilege has been acquired. */
+
+ /* This is for executables that have the setuid bit set. */
+# if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
+ /* See <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
+ figure 14. */
+ if (setresuid (-1, saved_uid, -1) < 0)
+ return -1;
+# else /* MacOS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
+ if (setreuid (-1, saved_uid) < 0)
+ return -1;
+# endif
+
+ /* This is for executables that have the setgid bit set. */
+# if HAVE_SETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
+ if (setresgid (-1, saved_gid, -1) < 0)
+ return -1;
+# else /* MacOS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
+ if (setregid (-1, saved_gid) < 0)
+ return -1;
+# endif
+
+ /* Verify that the privileges have really been acquired.
+ This verification is here for security reasons. Doesn't matter if it
+ takes a couple of system calls.
+ 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 != saved_uid
+ || saved != saved_uid)
+ abort ();
+ }
+# else
+# if HAVE_GETEUID
+ if (geteuid () != saved_uid)
+ abort ();
+# endif
+ if (getuid () != uid)
+ abort ();
+# endif
+# if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
+ {
+ uid_t real;
+ uid_t effective;
+ uid_t saved;
+ if (getresgid (&real, &effective, &saved) < 0
+ || real != gid
+ || effective != saved_gid
+ || saved != saved_gid)
+ abort ();
+ }
+# else
+# if HAVE_GETEGID
+ if (getegid () != saved_gid)
+ abort ();
+# endif
+ if (getgid () != gid)
+ abort ();
+# endif
+
+ return 0;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
diff --git a/gnulib/lib/idpriv.h b/gnulib/lib/idpriv.h
new file mode 100644
index 00000000..eb4d0517
--- /dev/null
+++ b/gnulib/lib/idpriv.h
@@ -0,0 +1,116 @@
+/* Dropping uid/gid privileges of the current process.
+ 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/>. */
+
+#ifndef _IDPRIV_H
+#define _IDPRIV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This module allows programs which are installed with setuid or setgid bit
+ (and which therefore initially run with an effective user id or group id
+ different from the one of the current user) to drop their uid or gid
+ privilege, either permanently or temporarily.
+
+ It is absolutely necessary to minimize the amount of code that is running
+ with escalated privileges (e.g. with effective uid = root). The reason is
+ that any bug or exploit in a part of a program that is running with
+ escalated privileges is a security vulnerability that - upon discovery -
+ puts the users in danger and requires immediate fixing. Then consider that
+ there's a bug every 10 or 20 lines of code on average...
+
+ For programs that temporarily drop privileges but have the ability to
+ restore them later, there are additionally the dangers that
+ - Any bug in the non-privileged part of the program may be used to
+ create invalid data structures that will trigger security
+ vulnerabilities in the privileged part of the program.
+ - Code execution exploits in the non-privileged part of the program may
+ be used to invoke the function that restores high privileges and then
+ execute additional arbitrary code.
+
+ 1) The usual, and reasonably safe, way to minimize the amount of code
+ running with privileges is to create a separate executable, with setuid
+ or setgid bit, that contains only code for the tasks that require
+ privileges (and,of course, strict checking of the arguments, so that the
+ program cannot be abused). The main program is installed without setuid
+ or setgid bit.
+
+ 2) A less safe way is to do some privileged tasks at the beginning of the
+ program's run, and drop privileges permanently as soon as possible.
+
+ Note: There may still be security issues if the privileged task puts
+ sensitive data into the process memory or opens communication channels
+ to restricted facilities.
+
+ 3) The most unsafe way is to drop privileges temporarily for most of the
+ main program but to re-enable them for the duration of privileged tasks.
+
+ As explained above, this approach has uncontrollable dangers for
+ security.
+
+ This approach is normally not usable in multithreaded programs, because
+ you cannot know what kind of system calls the other threads could be
+ doing during the time the privileges are enabled.
+
+ With approach 1, you don't need gnulib modules.
+ With approach 2, you need the gnulib module 'idpriv-drop'.
+ With approach 3, you need the gnulib module 'idpriv-droptemp'. But really,
+ you should better stay away from this approach.
+ */
+
+/* For more in-depth discussion of these topics, see the papers/articles
+ * Hao Chen, David Wagner, Drew Dean: Setuid Demystified
+ <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
+ * Dan Tsafrir, Dilma da Silva, David Wagner: The Murky Issue of Changing
+ Process Identity: Revising "Setuid Demystified"
+ <http://www.eecs.berkeley.edu/~daw/papers/setuid-login08b.pdf>
+ <http://code.google.com/p/change-process-identity/>
+ * Dhruv Mohindra: Observe correct revocation order while relinquishing
+ privileges
+ <https://www.securecoding.cert.org/confluence/display/seccode/POS36-C.+Observe+correct+revocation+order+while+relinquishing+privileges>
+ */
+
+
+/* For approach 2. */
+
+/* Drop the uid and gid privileges of the current process.
+ Return 0 if successful, or -1 with errno set upon failure. The recommended
+ handling of failure is to terminate the process. */
+extern int idpriv_drop (void);
+
+
+/* For approach 3. */
+
+/* Drop the uid and gid privileges of the current process in a way that allows
+ them to be restored later.
+ Return 0 if successful, or -1 with errno set upon failure. The recommended
+ handling of failure is to terminate the process. */
+extern int idpriv_temp_drop (void);
+
+/* Restore the uid and gid privileges of the current process.
+ Return 0 if successful, or -1 with errno set upon failure. The recommended
+ handling of failure is to not perform the actions that require the escalated
+ privileges. */
+extern int idpriv_temp_restore (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _IDPRIV_H */