Set aux group vector for PERM_RUNAS and restore group vector for
PERM_ROOT if we previously changed it. Stash the runas group vector so we don't have to call initgroups more than once. Also add no-op check to check_perms.
This commit is contained in:
@@ -353,9 +353,8 @@ log_error(flags, fmt, va_alist)
|
||||
va_start(ap);
|
||||
#endif
|
||||
|
||||
/* Become root if we are not already to avoid user control */
|
||||
if (geteuid() != 0)
|
||||
set_perms(PERM_ROOT);
|
||||
/* Become root if we are not already to avoid user interference */
|
||||
set_perms(PERM_ROOT);
|
||||
|
||||
/* Expand printf-style format + args. */
|
||||
evasprintf(&message, fmt, ap);
|
||||
|
113
set_perms.c
113
set_perms.c
@@ -65,6 +65,10 @@ __unused static const char rcsid[] = "$Sudo$";
|
||||
* Prototypes
|
||||
*/
|
||||
static void runas_setup __P((void));
|
||||
static void runas_setgroups __P((const char *, gid_t));
|
||||
static void restore_groups __P((void));
|
||||
|
||||
static int current_perm = -1;
|
||||
|
||||
#ifdef HAVE_SETRESUID
|
||||
/*
|
||||
@@ -77,11 +81,16 @@ void
|
||||
set_perms(perm)
|
||||
int perm;
|
||||
{
|
||||
if (perm == current_perm)
|
||||
return;
|
||||
|
||||
switch (perm) {
|
||||
case PERM_ROOT:
|
||||
if (setresuid(ROOT_UID, ROOT_UID, ROOT_UID))
|
||||
errorx(1, "setresuid(ROOT_UID, ROOT_UID, ROOT_UID) failed, your operating system may have a broken setresuid() function\nTry running configure with --disable-setresuid");
|
||||
(void) setresgid(-1, user_gid, -1);
|
||||
if (current_perm == PERM_RUNAS)
|
||||
restore_groups();
|
||||
break;
|
||||
|
||||
case PERM_USER:
|
||||
@@ -98,6 +107,7 @@ set_perms(perm)
|
||||
break;
|
||||
|
||||
case PERM_RUNAS:
|
||||
runas_setgroups(runas_pw->pw_name, runas_pw->pw_gid);
|
||||
(void) setresgid(-1, runas_gr ?
|
||||
runas_gr->gr_gid : runas_pw->pw_gid, -1);
|
||||
if (setresuid(-1,
|
||||
@@ -139,6 +149,8 @@ set_perms(perm)
|
||||
error(1, "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)");
|
||||
break;
|
||||
}
|
||||
|
||||
current_perm = perm;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -154,6 +166,9 @@ void
|
||||
set_perms(perm)
|
||||
int perm;
|
||||
{
|
||||
if (perm == current_perm)
|
||||
return;
|
||||
|
||||
switch (perm) {
|
||||
case PERM_ROOT:
|
||||
if (setreuid(-1, ROOT_UID))
|
||||
@@ -161,6 +176,8 @@ set_perms(perm)
|
||||
if (setuid(ROOT_UID))
|
||||
error(1, "setuid(ROOT_UID)");
|
||||
(void) setregid(-1, user_gid);
|
||||
if (current_perm == PERM_RUNAS)
|
||||
restore_groups();
|
||||
break;
|
||||
|
||||
case PERM_USER:
|
||||
@@ -177,6 +194,7 @@ set_perms(perm)
|
||||
break;
|
||||
|
||||
case PERM_RUNAS:
|
||||
runas_setgroups(runas_pw->pw_name, runas_pw->pw_gid);
|
||||
(void) setregid(-1, runas_gr ?
|
||||
runas_gr->gr_gid : runas_pw->pw_gid);
|
||||
if (setreuid(-1,
|
||||
@@ -217,6 +235,8 @@ set_perms(perm)
|
||||
error(1, "setreuid(ROOT_UID, timestamp_uid)");
|
||||
break;
|
||||
}
|
||||
|
||||
current_perm = perm;
|
||||
}
|
||||
|
||||
# else /* !HAVE_SETRESUID && !HAVE_SETREUID */
|
||||
@@ -230,6 +250,9 @@ void
|
||||
set_perms(perm)
|
||||
int perm;
|
||||
{
|
||||
if (perm == current_perm)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Since we only have setuid() and seteuid() and semantics
|
||||
* for these calls differ on various systems, we set
|
||||
@@ -244,6 +267,8 @@ set_perms(perm)
|
||||
case PERM_ROOT:
|
||||
/* uid set above */
|
||||
(void) setegid(user_gid);
|
||||
if (current_perm == PERM_RUNAS)
|
||||
restore_groups();
|
||||
break;
|
||||
|
||||
case PERM_USER:
|
||||
@@ -260,6 +285,7 @@ set_perms(perm)
|
||||
break;
|
||||
|
||||
case PERM_RUNAS:
|
||||
runas_setgroups(runas_pw->pw_name, runas_pw->pw_gid);
|
||||
(void) setegid(runas_gr ?
|
||||
runas_gr->gr_gid : runas_pw->pw_gid);
|
||||
if (seteuid(runas_pw ? runas_pw->pw_uid : user_uid))
|
||||
@@ -297,6 +323,8 @@ set_perms(perm)
|
||||
error(1, "seteuid(timestamp_uid)");
|
||||
break;
|
||||
}
|
||||
|
||||
current_perm = perm;
|
||||
}
|
||||
|
||||
# else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */
|
||||
@@ -310,11 +338,15 @@ void
|
||||
set_perms(perm)
|
||||
int perm;
|
||||
{
|
||||
if (perm == current_perm)
|
||||
return;
|
||||
|
||||
switch (perm) {
|
||||
case PERM_ROOT:
|
||||
if (setuid(ROOT_UID))
|
||||
error(1, "setuid(ROOT_UID)");
|
||||
if (current_perm == PERM_RUNAS)
|
||||
restore_groups();
|
||||
break;
|
||||
|
||||
case PERM_FULL_USER:
|
||||
@@ -336,11 +368,67 @@ set_perms(perm)
|
||||
/* Unsupported since we can't set euid. */
|
||||
break;
|
||||
}
|
||||
|
||||
current_perm = perm;
|
||||
}
|
||||
# endif /* HAVE_SETEUID */
|
||||
# endif /* HAVE_SETREUID */
|
||||
#endif /* HAVE_SETRESUID */
|
||||
|
||||
#ifdef HAVE_INITGROUPS
|
||||
static void
|
||||
runas_setgroups(name, basegid)
|
||||
const char *name;
|
||||
gid_t basegid;
|
||||
{
|
||||
static int ngroups = -1;
|
||||
static gid_t *groups;
|
||||
|
||||
if (def_preserve_groups)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Use stashed copy of runas groups if available, else initgroups and stash.
|
||||
*/
|
||||
if (ngroups == -1) {
|
||||
if (initgroups(name, basegid) < 0)
|
||||
log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
|
||||
if ((ngroups = getgroups(0, NULL)) < 0)
|
||||
log_error(USE_ERRNO|MSG_ONLY, "can't get runas ngroups");
|
||||
groups = emalloc2(ngroups, MAX(sizeof(gid_t), sizeof(int)));
|
||||
if (getgroups(ngroups, groups) < 0)
|
||||
log_error(USE_ERRNO|MSG_ONLY, "can't get runas group vector");
|
||||
} else {
|
||||
if (setgroups(ngroups, groups) < 0)
|
||||
log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
restore_groups()
|
||||
{
|
||||
if (setgroups(user_ngroups, user_groups) < 0)
|
||||
log_error(USE_ERRNO|MSG_ONLY, "can't reset user group vector");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void
|
||||
runas_setgroups(name, basegid)
|
||||
const char *name;
|
||||
gid_t basegid;
|
||||
{
|
||||
/* STUB */
|
||||
}
|
||||
|
||||
static void
|
||||
restore_groups()
|
||||
{
|
||||
/* STUB */
|
||||
}
|
||||
|
||||
#endif /* HAVE_INITGROUPS */
|
||||
|
||||
static void
|
||||
runas_setup()
|
||||
{
|
||||
@@ -359,10 +447,7 @@ runas_setup()
|
||||
#ifdef HAVE_LOGIN_CAP_H
|
||||
if (def_use_loginclass) {
|
||||
/*
|
||||
* We don't have setusercontext() set the user since we
|
||||
* may only want to set the effective uid. Depending on
|
||||
* sudoers and/or command line arguments we may not want
|
||||
* setusercontext() to call initgroups().
|
||||
* We only use setusercontext() set the nice value and rlimits.
|
||||
*/
|
||||
flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
|
||||
if (!def_preserve_groups)
|
||||
@@ -375,19 +460,13 @@ runas_setup()
|
||||
else
|
||||
warning("unable to set user context");
|
||||
}
|
||||
} else
|
||||
#endif /* HAVE_LOGIN_CAP_H */
|
||||
{
|
||||
if (setgid(gid))
|
||||
warning("cannot set gid to runas gid");
|
||||
#ifdef HAVE_INITGROUPS
|
||||
/*
|
||||
* Initialize group vector unless asked not to.
|
||||
*/
|
||||
if (!def_preserve_groups &&
|
||||
initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0)
|
||||
warning("cannot set group vector");
|
||||
#endif /* HAVE_INITGROUPS */
|
||||
}
|
||||
#endif /* HAVE_LOGIN_CAP_H */
|
||||
if (setgid(gid))
|
||||
warning("cannot set gid to runas gid");
|
||||
/*
|
||||
* Initialize group vector
|
||||
*/
|
||||
runas_setgroups(runas_pw->pw_name, runas_pw->pw_gid);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user