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 */ #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. * Set real and effective and saved uids and gids based on perm.
* We always retain a real or effective uid of 0 unless * We always retain a saved uid of 0 unless we are headed for an exec().
* 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 void
set_perms_fallback(perm) set_perms_suid(perm)
int perm; int perm;
{ {
int error; int error;
@@ -168,12 +169,84 @@ set_perms_fallback(perm)
switch (perm) { switch (perm) {
case PERM_FULL_ROOT: case PERM_FULL_ROOT:
case PERM_ROOT: case PERM_ROOT:
if (setuid(0)) if (setresuid(0, 0, 0))
fatal("setuid(0) failed, your operating system may have broken POSIX saved ID support\nTry running configure with --disable-setreuid", 0); fatal("setresuid(0, 0, 0) failed, your operating system may have a broken setresuid() function\nTry running configure with --disable-setresuid", 0);
break; break;
case PERM_USER: 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)) if (setreuid(0, user_uid))
fatal("setreuid(0, user_uid)", 1); fatal("setreuid(0, user_uid)", 1);
break; break;
@@ -181,24 +254,23 @@ set_perms_fallback(perm)
case PERM_FULL_USER: case PERM_FULL_USER:
/* headed for exec() */ /* headed for exec() */
(void) setgid(user_gid); (void) setgid(user_gid);
if (setuid(user_uid)) if (setreuid(user_uid, user_uid))
fatal("setuid(user_uid)", 1); fatal("setreuid(user_uid, user_uid)", 1);
break; break;
case PERM_RUNAS: case PERM_RUNAS:
/* headed for exec(), assume euid == 0 */ /* headed for exec(), assume euid == 0 */
runas_setup(); runas_setup();
if (def_flag(I_STAY_SETUID)) error = setreuid(def_flag(I_STAY_SETUID) ?
error = setreuid(user_uid, runas_pw->pw_uid); user_uid : runas_pw->pw_uid,
else runas_pw->pw_uid);
error = setuid(runas_pw->pw_uid);
if (error) if (error)
fatal("unable to change to runas uid", 1); fatal("unable to change to runas uid", 1);
break; break;
case PERM_SUDOERS: case PERM_SUDOERS:
/* assume euid == 0, ruid == user */ /* assume euid == 0, ruid == user */
if (setegid(SUDOERS_GID)) if (setregid(SUDOERS_GID, -1))
fatal("unable to change to sudoers gid", 1); fatal("unable to change to sudoers gid", 1);
/* /*
@@ -230,13 +302,13 @@ set_perms_fallback(perm)
* NOTE: does not support the "stay_setuid" option. * NOTE: does not support the "stay_setuid" option.
*/ */
void void
set_perms_fallback(perm) set_perms_nosuid(perm)
int perm; int perm;
{ {
/* /*
* Since we only have setuid() and seteuid() we have to set * 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)) if (setuid(0))
fatal("setuid(0)", 1); fatal("setuid(0)", 1);
@@ -289,6 +361,7 @@ set_perms_fallback(perm)
} }
} }
# endif /* HAVE_SETREUID */ # endif /* HAVE_SETREUID */
#endif /* HAVE_SETRESUID */
static void static void
runas_setup() runas_setup()

23
sudo.c
View File

@@ -260,17 +260,18 @@ main(argc, argv, envp)
validated = sudoers_lookup(pwflag); validated = sudoers_lookup(pwflag);
/* /*
* If we have POSIX saved uids and the stay_setuid flag was not set, * 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_fallback() * set the real, effective and saved uids to 0 and use set_perms_nosuid()
* instead of set_perms_posix(). * 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 (!def_flag(I_STAY_SETUID) && set_perms == set_perms_posix) {
if (setuid(0)) { if (setuid(0)) {
perror("setuid(0)"); perror("setuid(0)");
exit(1); exit(1);
} }
set_perms = set_perms_fallback; set_perms = set_perms_nosuid;
} }
#endif #endif
@@ -901,13 +902,23 @@ initial_setup()
for (fd = maxfd; fd > STDERR_FILENO; fd--) for (fd = maxfd; fd > STDERR_FILENO; fd--)
(void) close(fd); (void) close(fd);
/* Set set_perms pointer to the correct function */ /*
* 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 !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
if (sysconf(_SC_SAVED_IDS) == 1 && sysconf(_SC_VERSION) >= 199009) if (sysconf(_SC_SAVED_IDS) == 1 && sysconf(_SC_VERSION) >= 199009)
set_perms = set_perms_posix; set_perms = set_perms_posix;
else else
# endif # endif
set_perms = set_perms_fallback; set_perms = set_perms_nosuid;
#endif /* HAVE_SETRESUID || HAVE_SETREUID */
} }
#ifdef HAVE_LOGIN_CAP_H #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 check_user __P((void));
void verify_user __P((struct passwd *, char *)); void verify_user __P((struct passwd *, char *));
int sudoers_lookup __P((int)); int sudoers_lookup __P((int));
void set_perms_nosuid __P((int));
void set_perms_posix __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)); void remove_timestamp __P((int));
int check_secureware __P((char *)); int check_secureware __P((char *));
void sia_attempt_auth __P((void)); void sia_attempt_auth __P((void));
@@ -235,7 +236,7 @@ extern int Argc;
extern char **Argv; extern char **Argv;
extern FILE *sudoers_fp; extern FILE *sudoers_fp;
extern int tgetpass_flags; extern int tgetpass_flags;
extern int timestamp_uid; extern uid_t timestamp_uid;
extern void (*set_perms) __P((int)); extern void (*set_perms) __P((int));
#endif #endif