root/maint/gnulib/lib/idpriv-droptemp.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. idpriv_temp_drop
  2. idpriv_temp_restore

   1 /* Dropping uid/gid privileges of the current process temporarily.
   2    Copyright (C) 2009-2021 Free Software Foundation, Inc.
   3 
   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.
   8 
   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.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 #include <config.h>
  18 
  19 #include "idpriv.h"
  20 
  21 #include <errno.h>
  22 #include <stdlib.h>
  23 #include <sys/types.h>
  24 #include <unistd.h>
  25 
  26 /* The privileged uid and gid that the process had earlier.  */
  27 #if HAVE_GETUID
  28 static int saved_uid = -1;
  29 #endif
  30 #if HAVE_GETGID
  31 static int saved_gid = -1;
  32 #endif
  33 
  34 int
  35 idpriv_temp_drop (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  36 {
  37 #if HAVE_GETEUID && HAVE_GETEGID && (HAVE_SETRESUID || HAVE_SETREUID) && (HAVE_SETRESGID || HAVE_SETREGID)
  38   int uid = getuid ();
  39   int gid = getgid ();
  40 
  41   /* Find out about the privileged uid and gid at the first call.  */
  42   if (saved_uid == -1)
  43     saved_uid = geteuid ();
  44   if (saved_gid == -1)
  45     saved_gid = getegid ();
  46 
  47   /* Drop the gid privilege first, because in some cases the gid privilege
  48      cannot be dropped after the uid privilege has been dropped.  */
  49 
  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)
  53     return -1;
  54 # else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
  55   if (setregid (-1, gid) < 0)
  56     return -1;
  57 # endif
  58 
  59   /* This is for executables that have the setuid bit set.  */
  60 # if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
  61   /* See
  62        Hao Chen, David Wagner, Drew Dean: Setuid Demystified
  63        <https://www.usenix.org/legacy/publications/library/proceedings/sec02/full_papers/chen/chen.pdf>
  64      figure 14.  */
  65   if (setresuid (-1, uid, saved_uid) < 0)
  66     return -1;
  67 # else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
  68   if (setreuid (-1, uid) < 0)
  69     return -1;
  70 # endif
  71 
  72   /* Verify that the privileges have really been dropped.
  73      This verification is here for security reasons.  Doesn't matter if it
  74      takes a couple of system calls.
  75      When the verification fails, it indicates that we need to use different
  76      API in the code above. Therefore 'abort ()', not 'return -1'.  */
  77 # if HAVE_GETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
  78   {
  79     uid_t real;
  80     uid_t effective;
  81     uid_t saved;
  82     if (getresuid (&real, &effective, &saved) < 0
  83         || real != uid
  84         || effective != uid
  85         || saved != saved_uid)
  86       abort ();
  87   }
  88 # else
  89 #  if HAVE_GETEUID
  90   if (geteuid () != uid)
  91     abort ();
  92 #  endif
  93   if (getuid () != uid)
  94     abort ();
  95 # endif
  96 # if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
  97   {
  98     uid_t real;
  99     uid_t effective;
 100     uid_t saved;
 101     if (getresgid (&real, &effective, &saved) < 0
 102         || real != gid
 103         || effective != gid
 104         || saved != saved_gid)
 105       abort ();
 106   }
 107 # else
 108 #  if HAVE_GETEGID
 109   if (getegid () != gid)
 110     abort ();
 111 #  endif
 112   if (getgid () != gid)
 113     abort ();
 114 # endif
 115 
 116   return 0;
 117 #else
 118   errno = ENOSYS;
 119   return -1;
 120 #endif
 121 }
 122 
 123 int
 124 idpriv_temp_restore (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126 #if HAVE_GETEUID && HAVE_GETEGID && (HAVE_SETRESUID || HAVE_SETREUID) && (HAVE_SETRESGID || HAVE_SETREGID)
 127   int uid = getuid ();
 128   int gid = getgid ();
 129 
 130   if (saved_uid == -1 || saved_gid == -1)
 131     /* Caller error: idpriv_temp_drop was never invoked.  */
 132     abort ();
 133 
 134   /* Acquire the gid privilege last, because in some cases the gid privilege
 135      cannot be acquired before the uid privilege has been acquired.  */
 136 
 137   /* This is for executables that have the setuid bit set.  */
 138 # if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
 139   /* See
 140        Hao Chen, David Wagner, Drew Dean: Setuid Demystified
 141        <https://www.usenix.org/legacy/publications/library/proceedings/sec02/full_papers/chen/chen.pdf>
 142      figure 14.  */
 143   if (setresuid (-1, saved_uid, -1) < 0)
 144     return -1;
 145 # else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
 146   if (setreuid (-1, saved_uid) < 0)
 147     return -1;
 148 # endif
 149 
 150   /* This is for executables that have the setgid bit set.  */
 151 # if HAVE_SETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
 152   if (setresgid (-1, saved_gid, -1) < 0)
 153     return -1;
 154 # else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
 155   if (setregid (-1, saved_gid) < 0)
 156     return -1;
 157 # endif
 158 
 159   /* Verify that the privileges have really been acquired.
 160      This verification is here for security reasons.  Doesn't matter if it
 161      takes a couple of system calls.
 162      When the verification fails, it indicates that we need to use different
 163      API in the code above. Therefore 'abort ()', not 'return -1'.  */
 164 # if HAVE_GETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
 165   {
 166     uid_t real;
 167     uid_t effective;
 168     uid_t saved;
 169     if (getresuid (&real, &effective, &saved) < 0
 170         || real != uid
 171         || effective != saved_uid
 172         || saved != saved_uid)
 173       abort ();
 174   }
 175 # else
 176 #  if HAVE_GETEUID
 177   if (geteuid () != saved_uid)
 178     abort ();
 179 #  endif
 180   if (getuid () != uid)
 181     abort ();
 182 # endif
 183 # if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
 184   {
 185     uid_t real;
 186     uid_t effective;
 187     uid_t saved;
 188     if (getresgid (&real, &effective, &saved) < 0
 189         || real != gid
 190         || effective != saved_gid
 191         || saved != saved_gid)
 192       abort ();
 193   }
 194 # else
 195 #  if HAVE_GETEGID
 196   if (getegid () != saved_gid)
 197     abort ();
 198 #  endif
 199   if (getgid () != gid)
 200     abort ();
 201 # endif
 202 
 203   return 0;
 204 #else
 205   errno = ENOSYS;
 206   return -1;
 207 #endif
 208 }

/* [previous][next][first][last][top][bottom][index][help] */