[monitoring-plugins] Add Gnulib module "idpriv-droptemp"

Holger Weiss git at monitoring-plugins.org
Wed Jun 18 23:20:08 CEST 2014


 Module: monitoring-plugins
 Branch: master
 Commit: 91d04ad62d5272dd0e0e76af80e86ef912a3f643
 Author: Holger Weiss <holger at zedat.fu-berlin.de>
   Date: Wed Jun 18 21:47:10 2014 +0200
    URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=91d04ad

Add Gnulib module "idpriv-droptemp"

---

 gl/Makefile.am        |  10 ++-
 gl/idpriv-droptemp.c  | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++
 gl/idpriv.h           | 116 ++++++++++++++++++++++++++++
 gl/m4/gnulib-cache.m4 |   3 +-
 gl/m4/gnulib-comp.m4  |   9 ++-
 gl/m4/idpriv.m4       |  14 ++++
 6 files changed, 352 insertions(+), 4 deletions(-)

diff --git a/gl/Makefile.am b/gl/Makefile.am
index 4339b2c..54abb4c 100644
--- a/gl/Makefile.am
+++ b/gl/Makefile.am
@@ -21,7 +21,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=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname environ floorf fsusage getaddrinfo gethostname getloadavg getopt-gnu gettext mountlist regex setenv strcase strsep timegm unsetenv vasprintf vsnprintf
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname environ floorf fsusage getaddrinfo gethostname getloadavg getopt-gnu gettext idpriv-droptemp mountlist regex setenv strcase strsep timegm unsetenv vasprintf vsnprintf
 
 AUTOMAKE_OPTIONS = 1.9.6 gnits subdir-objects
 
@@ -402,6 +402,14 @@ EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath
 
 ## end   gnulib module havelib
 
+## begin gnulib module idpriv-droptemp
+
+libgnu_a_SOURCES += idpriv-droptemp.c
+
+EXTRA_DIST += idpriv.h
+
+## end   gnulib module idpriv-droptemp
+
 ## begin gnulib module inet_ntop
 
 
diff --git a/gl/idpriv-droptemp.c b/gl/idpriv-droptemp.c
new file mode 100644
index 0000000..13d1064
--- /dev/null
+++ b/gl/idpriv-droptemp.c
@@ -0,0 +1,204 @@
+/* Dropping uid/gid privileges of the current process temporarily.
+   Copyright (C) 2009-2013 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 /* Mac OS 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 /* Mac OS 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 /* Mac OS 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 /* Mac OS 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/gl/idpriv.h b/gl/idpriv.h
new file mode 100644
index 0000000..f454a2c
--- /dev/null
+++ b/gl/idpriv.h
@@ -0,0 +1,116 @@
+/* Dropping uid/gid privileges of the current process.
+   Copyright (C) 2009-2013 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 */
diff --git a/gl/m4/gnulib-cache.m4 b/gl/m4/gnulib-cache.m4
index e61a536..d6fca2a 100644
--- a/gl/m4/gnulib-cache.m4
+++ b/gl/m4/gnulib-cache.m4
@@ -27,7 +27,7 @@
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname environ floorf fsusage getaddrinfo gethostname getloadavg getopt-gnu gettext mountlist regex setenv strcase strsep timegm unsetenv vasprintf vsnprintf
+#   gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname environ floorf fsusage getaddrinfo gethostname getloadavg getopt-gnu gettext idpriv-droptemp mountlist regex setenv strcase strsep timegm unsetenv vasprintf vsnprintf
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([])
@@ -43,6 +43,7 @@ gl_MODULES([
   getloadavg
   getopt-gnu
   gettext
+  idpriv-droptemp
   mountlist
   regex
   setenv
diff --git a/gl/m4/gnulib-comp.m4 b/gl/m4/gnulib-comp.m4
index b3cb4c1..67a8156 100644
--- a/gl/m4/gnulib-comp.m4
+++ b/gl/m4/gnulib-comp.m4
@@ -28,7 +28,7 @@
 # other built files.
 
 
-# This macro should be invoked from ./configure.in, in the section
+# This macro should be invoked from ./configure.ac, in the section
 # "Checks for programs", right after AC_PROG_CC, and certainly before
 # any checks for libraries, header files, types and library functions.
 AC_DEFUN([gl_EARLY],
@@ -70,6 +70,7 @@ AC_DEFUN([gl_EARLY],
   # Code from module gettext-h:
   # Code from module havelib:
   # Code from module hostent:
+  # Code from module idpriv-droptemp:
   # Code from module include_next:
   # Code from module inet_ntop:
   # Code from module intprops:
@@ -153,7 +154,7 @@ AC_DEFUN([gl_EARLY],
   # Code from module xstrndup:
 ])
 
-# This macro should be invoked from ./configure.in, in the section
+# This macro should be invoked from ./configure.ac, in the section
 # "Check for header files, types and library functions".
 AC_DEFUN([gl_INIT],
 [
@@ -258,6 +259,7 @@ AC_DEFUN([gl_INIT],
   AC_SUBST([LIBINTL])
   AC_SUBST([LTLIBINTL])
   gl_HOSTENT
+  gl_IDPRIV
   gl_FUNC_INET_NTOP
   if test $HAVE_INET_NTOP = 0 || test $REPLACE_INET_NTOP = 1; then
     AC_LIBOBJ([inet_ntop])
@@ -658,6 +660,8 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/glthread/lock.c
   lib/glthread/lock.h
   lib/glthread/threadlib.c
+  lib/idpriv-droptemp.c
+  lib/idpriv.h
   lib/inet_ntop.c
   lib/intprops.h
   lib/itold.c
@@ -790,6 +794,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/gnulib-common.m4
   m4/hostent.m4
   m4/iconv.m4
+  m4/idpriv.m4
   m4/include_next.m4
   m4/inet_ntop.m4
   m4/intdiv0.m4
diff --git a/gl/m4/idpriv.m4 b/gl/m4/idpriv.m4
new file mode 100644
index 0000000..167f523
--- /dev/null
+++ b/gl/m4/idpriv.m4
@@ -0,0 +1,14 @@
+# idpriv.m4 serial 1
+dnl Copyright (C) 2009-2013 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_IDPRIV],
+[
+  dnl Persuade glibc <unistd.h> to declare {get,set}res{uid,gid}.
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+  AC_CHECK_FUNCS_ONCE([getuid geteuid getresuid getgid getegid getresgid])
+  AC_CHECK_FUNCS_ONCE([setresuid setreuid seteuid setresgid setregid setegid])
+])



More information about the Commits mailing list