Revamp set_perms. We now use a version based on setresuid() or setreuid()

when possible since that allows us to support the stay_setuid option and
we always know exactly what the semantics will be (various Linux kernels
have broken POSIX saved uid support).
This commit is contained in:
Todd C. Miller
2002-11-22 19:09:49 +00:00
parent 2de61320b3
commit b152da4cdb
3 changed files with 114 additions and 29 deletions

View File

@@ -153,14 +153,15 @@ set_perms_posix(perm)
}
#endif /* !NO_SAVED_IDS && _SC_SAVED_IDS && _SC_VERSION */
#ifdef HAVE_SETREUID
#ifdef HAVE_SETRESUID
/*
* Set real and effective uids and gids based on perm.
* We always retain a real or effective uid of 0 unless
* we are headed for an exec().
* Set real and effective and saved uids and gids based on perm.
* We always retain a saved uid of 0 unless we are headed for an exec().
* We only flip the effective gid since it only changes for PERM_SUDOERS.
* This version of set_perms() works fine with the "stay_setuid" option.
*/
void
set_perms_fallback(perm)
set_perms_suid(perm)
int perm;
{
int error;
@@ -168,12 +169,84 @@ set_perms_fallback(perm)
switch (perm) {
case PERM_FULL_ROOT:
case PERM_ROOT:
if (setuid(0))
fatal("setuid(0) failed, your operating system may have broken POSIX saved ID support\nTry running configure with --disable-setreuid", 0);
if (setresuid(0, 0, 0))
fatal("setresuid(0, 0, 0) failed, your operating system may have a broken setresuid() function\nTry running configure with --disable-setresuid", 0);
break;
case PERM_USER:
(void) setegid(user_gid);
(void) setresgid(user_gid, -1, -1);
if (setresuid(user_uid, user_uid, 0))
fatal("setresuid(user_uid, user_uid, 0)", 1);
break;
case PERM_FULL_USER:
/* headed for exec() */
(void) setgid(user_gid);
if (setresuid(user_uid, user_uid, user_uid))
fatal("setresuid(user_uid, user_uid, user_uid)", 1);
break;
case PERM_RUNAS:
/* headed for exec(), assume euid == 0 */
runas_setup();
error = setresuid(def_flag(I_STAY_SETUID) ?
user_uid : runas_pw->pw_uid,
runas_pw->pw_uid, runas_pw->pw_uid);
if (error)
fatal("unable to change to runas uid", 1);
break;
case PERM_SUDOERS:
/* assume euid == 0, ruid == user */
if (setresgid(SUDOERS_GID, -1, -1))
fatal("unable to change to sudoers gid", 1);
/*
* If SUDOERS_UID == 0 and SUDOERS_MODE
* is group readable we use a non-zero
* uid in order to avoid NFS lossage.
* Using uid 1 is a bit bogus but should
* work on all OS's.
*/
if (SUDOERS_UID == 0) {
if ((SUDOERS_MODE & 040) && setresuid(0, 1, 0))
fatal("setresuid(0, 1, 0)", 1);
} else {
if (setresuid(0, SUDOERS_UID, 0))
fatal("setresuid(0, SUDOERS_UID, 0)", 1);
}
break;
case PERM_TIMESTAMP:
if (setresuid(0, timestamp_uid, 0))
fatal("setresuid(0, timestamp_uid, 0)", 1);
break;
}
}
#else
# ifdef HAVE_SETREUID
/*
* Set real and effective uids and gids based on perm.
* We always retain a real or effective uid of 0 unless
* we are headed for an exec().
* This version of set_perms() works fine with the "stay_setuid" option.
*/
void
set_perms_suid(perm)
int perm;
{
int error;
switch (perm) {
case PERM_FULL_ROOT:
case PERM_ROOT:
if (setreuid(0, 0))
fatal("setreuid(0, 0) failed, your operating system may have a broken setreuid() function\nTry running configure with --disable-setreuid", 0);
break;
case PERM_USER:
(void) setregid(user_gid, -1);
if (setreuid(0, user_uid))
fatal("setreuid(0, user_uid)", 1);
break;
@@ -181,24 +254,23 @@ set_perms_fallback(perm)
case PERM_FULL_USER:
/* headed for exec() */
(void) setgid(user_gid);
if (setuid(user_uid))
fatal("setuid(user_uid)", 1);
if (setreuid(user_uid, user_uid))
fatal("setreuid(user_uid, user_uid)", 1);
break;
case PERM_RUNAS:
/* headed for exec(), assume euid == 0 */
runas_setup();
if (def_flag(I_STAY_SETUID))
error = setreuid(user_uid, runas_pw->pw_uid);
else
error = setuid(runas_pw->pw_uid);
error = setreuid(def_flag(I_STAY_SETUID) ?
user_uid : runas_pw->pw_uid,
runas_pw->pw_uid);
if (error)
fatal("unable to change to runas uid", 1);
break;
case PERM_SUDOERS:
/* assume euid == 0, ruid == user */
if (setegid(SUDOERS_GID))
if (setregid(SUDOERS_GID, -1))
fatal("unable to change to sudoers gid", 1);
/*
@@ -223,20 +295,20 @@ set_perms_fallback(perm)
}
}
#else
# else
/*
* Set real and effective uids and gids based on perm.
* NOTE: does not support the "stay_setuid" option.
*/
void
set_perms_fallback(perm)
set_perms_nosuid(perm)
int perm;
{
/*
* Since we only have setuid() and seteuid() we have to set
* real and effective uidss to 0 initially.
* real and effective uids to 0 initially.
*/
if (setuid(0))
fatal("setuid(0)", 1);
@@ -288,7 +360,8 @@ set_perms_fallback(perm)
break;
}
}
#endif /* HAVE_SETREUID */
# endif /* HAVE_SETREUID */
#endif /* HAVE_SETRESUID */
static void
runas_setup()

27
sudo.c
View File

@@ -260,17 +260,18 @@ main(argc, argv, envp)
validated = sudoers_lookup(pwflag);
/*
* If we have POSIX saved uids and the stay_setuid flag was not set,
* set the real, effective and saved uids to 0 and use set_perms_fallback()
* If we are using set_perms_posix() and the stay_setuid flag was not set,
* set the real, effective and saved uids to 0 and use set_perms_nosuid()
* instead of set_perms_posix().
*/
#if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
#if !defined(HAVE_SETRESUID) && !defined(HAVE_SETREUID) && \
!defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
if (!def_flag(I_STAY_SETUID) && set_perms == set_perms_posix) {
if (setuid(0)) {
perror("setuid(0)");
exit(1);
}
set_perms = set_perms_fallback;
set_perms = set_perms_nosuid;
}
#endif
@@ -901,13 +902,23 @@ initial_setup()
for (fd = maxfd; fd > STDERR_FILENO; fd--)
(void) close(fd);
/* Set set_perms pointer to the correct function */
#if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
/*
* Make set_perms point to the correct function.
* If we are using setresuid() or setreuid() we only need to set this
* once. If we are using POSIX saved uids we will switch to
* set_perms_nosuid after sudoers has been parsed if the "stay_suid"
* option is not set.
*/
#if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID)
set_perms = set_perms_suid;
#else
# if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
if (sysconf(_SC_SAVED_IDS) == 1 && sysconf(_SC_VERSION) >= 199009)
set_perms = set_perms_posix;
else
#endif
set_perms = set_perms_fallback;
# endif
set_perms = set_perms_nosuid;
#endif /* HAVE_SETRESUID || HAVE_SETREUID */
}
#ifdef HAVE_LOGIN_CAP_H

5
sudo.h
View File

@@ -202,8 +202,9 @@ int find_path __P((char *, char **, char *));
void check_user __P((void));
void verify_user __P((struct passwd *, char *));
int sudoers_lookup __P((int));
void set_perms_nosuid __P((int));
void set_perms_posix __P((int));
void set_perms_fallback __P((int));
void set_perms_suid __P((int));
void remove_timestamp __P((int));
int check_secureware __P((char *));
void sia_attempt_auth __P((void));
@@ -235,7 +236,7 @@ extern int Argc;
extern char **Argv;
extern FILE *sudoers_fp;
extern int tgetpass_flags;
extern int timestamp_uid;
extern uid_t timestamp_uid;
extern void (*set_perms) __P((int));
#endif