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:
111
set_perms.c
111
set_perms.c
@@ -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
27
sudo.c
@@ -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
5
sudo.h
@@ -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
|
||||
|
Reference in New Issue
Block a user