From: Todd C. Miller Date: Sat, 10 Apr 2010 14:34:37 +0000 (-0400) Subject: Primitive set/restore permissions. Will be replaced by a push/pop X-Git-Tag: SUDO_1_8_0~734 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=744eae82e7153063cc4dac313115b1b60a4e9ae3;p=sudo Primitive set/restore permissions. Will be replaced by a push/pop model. --- diff --git a/plugins/sudoers/check.c b/plugins/sudoers/check.c index 161d86e5d..8aafa28aa 100644 --- a/plugins/sudoers/check.c +++ b/plugins/sudoers/check.c @@ -215,7 +215,7 @@ update_timestamp(timestampdir, timestampfile) } } if (timestamp_uid != 0) - set_perms(PERM_ROOT); + restore_perms(); } /* @@ -464,11 +464,8 @@ timestamp_status(timestampdir, timestampfile, user, flags) status = TS_MISSING; } } - if (status == TS_ERROR) { - if (timestamp_uid != 0) - set_perms(PERM_ROOT); - return(status); - } + if (status == TS_ERROR) + goto done; /* * Sanity check the user's ticket dir. We start by downgrading @@ -592,7 +589,7 @@ timestamp_status(timestampdir, timestampfile, user, flags) done: if (timestamp_uid != 0) - set_perms(PERM_ROOT); + restore_perms(); return(status); } diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index 6caf0cd6e..eb8d1f829 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -406,7 +406,7 @@ log_error(flags, fmt, va_alist) efree(logline); - set_perms(PERM_USER); + restore_perms(); if (!ISSET(flags, NO_EXIT)) { cleanup(0); diff --git a/plugins/sudoers/parse.c b/plugins/sudoers/parse.c index f7ea49e4c..0278cd76e 100644 --- a/plugins/sudoers/parse.c +++ b/plugins/sudoers/parse.c @@ -257,7 +257,7 @@ sudo_file_lookup(nss, validated, pwflag) SET(validated, VALIDATE_NOT_OK); CLR(validated, VALIDATE_OK); } - set_perms(PERM_ROOT); + restore_perms(); return(validated); } diff --git a/plugins/sudoers/set_perms.c b/plugins/sudoers/set_perms.c index d3b2c2b87..6956237b2 100644 --- a/plugins/sudoers/set_perms.c +++ b/plugins/sudoers/set_perms.c @@ -66,7 +66,38 @@ static void runas_setup(void); static void runas_setgroups(void); static void restore_groups(void); -static int current_perm = -1; +/* + * We keep track of the current permisstions and use a stack to restore + * the old permissions. A depth of 16 is overkill. + */ +#define PERM_STACK_MAX 16 +static int perm_stack[PERM_STACK_MAX]; +static int perm_stack_depth = 0; +static int perm_current = PERM_INITIAL; + +/* + * XXX - better to push what we've changed: + * ruid, euid, suid, gids group vector. + */ + +int +restore_perms(void) +{ + int old_perm; + + if (!perm_stack_depth) { + /* nothing to do */ + return TRUE; + } + old_perm = perm_stack[--perm_stack_depth]; + return set_perms2(old_perm, FALSE); +} + +int +set_perms(int perm) +{ + return set_perms2(perm, TRUE); +} #ifdef HAVE_SETRESUID /* @@ -76,8 +107,7 @@ static int current_perm = -1; * This version of set_perms() works fine with the "stay_setuid" option. */ int -set_perms(perm) - int perm; +set_perms2(int perm, int push_it) { const char *errstr; int noexit; @@ -85,17 +115,32 @@ set_perms(perm) noexit = ISSET(perm, PERM_NOEXIT); CLR(perm, PERM_MASK); - if (perm == current_perm) - return(1); + if (perm_stack_depth == PERM_STACK_MAX) { + errno = EINVAL; + goto bad; + } + if (perm == perm_current) + goto done; switch (perm) { + case PERM_INITIAL: + /* Setuid root */ + if (setuid(ROOT_UID)) { + errstr = "setuid(ROOT_UID)"; + goto bad; + } + (void) setresgid(-1, user_gid, -1); + if (perm_current == PERM_RUNAS) + restore_groups(); + (void) setresuid(user_uid, -1, -1); + break; case PERM_ROOT: if (setresuid(ROOT_UID, ROOT_UID, ROOT_UID)) { errstr = "setresuid(ROOT_UID, ROOT_UID, ROOT_UID)"; goto bad; } (void) setresgid(-1, user_gid, -1); - if (current_perm == PERM_RUNAS) + if (perm_current == PERM_RUNAS) restore_groups(); break; @@ -172,7 +217,10 @@ set_perms(perm) break; } - current_perm = perm; +done: + if (push_it) + perm_stack[perm_stack_depth++] = perm_current; + perm_current = perm; return(1); bad: warningx("%s: %s", errstr, @@ -201,7 +249,7 @@ set_perms(perm) noexit = ISSET(perm, PERM_NOEXIT); CLR(perm, PERM_MASK); - if (perm == current_perm) + if (perm == perm_current) return(1); switch (perm) { @@ -215,7 +263,7 @@ set_perms(perm) goto bad; } (void) setregid(-1, user_gid); - if (current_perm == PERM_RUNAS) + if (perm_current == PERM_RUNAS) restore_groups(); break; @@ -291,7 +339,7 @@ set_perms(perm) break; } - current_perm = perm; + perm_current = perm; return(1); bad: warningx("%s: %s", errstr, @@ -318,7 +366,7 @@ set_perms(perm) noexit = ISSET(perm, PERM_NOEXIT); CLR(perm, PERM_MASK); - if (perm == current_perm) + if (perm == perm_current) return(1); /* @@ -339,7 +387,7 @@ set_perms(perm) case PERM_ROOT: /* uid set above */ (void) setegid(user_gid); - if (current_perm == PERM_RUNAS) + if (perm_current == PERM_RUNAS) restore_groups(); break; @@ -412,7 +460,7 @@ set_perms(perm) break; } - current_perm = perm; + perm_current = perm; return(1); bad: warningx("%s: %s", errstr, @@ -439,7 +487,7 @@ set_perms(perm) noexit = ISSET(perm, PERM_NOEXIT); CLR(perm, PERM_MASK); - if (perm == current_perm) + if (perm == perm_current) return(1); switch (perm) { @@ -448,7 +496,7 @@ set_perms(perm) errstr = "setuid(ROOT_UID)"; goto bad; } - if (current_perm == PERM_RUNAS) + if (perm_current == PERM_RUNAS) restore_groups(); break; @@ -478,7 +526,7 @@ set_perms(perm) break; } - current_perm = perm; + perm_current = perm; return(1); bad: warningx("%s: %s", errstr, diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index f04439b89..232080d02 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -737,12 +737,12 @@ set_cmnd(sudo_mode) if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) { set_perms(PERM_RUNAS); rval = find_path(NewArgv[0], &user_cmnd, user_stat, user_path); - set_perms(PERM_ROOT); + restore_perms(); if (rval != FOUND) { /* Failed as root, try as invoking user. */ set_perms(PERM_USER); rval = find_path(NewArgv[0], &user_cmnd, user_stat, user_path); - set_perms(PERM_ROOT); + restore_perms(); } } @@ -855,7 +855,7 @@ open_sudoers(sudoers, doedit, keepopen) (void) fcntl(fileno(fp), F_SETFD, 1); } - set_perms(PERM_ROOT); /* change back to root */ + restore_perms(); /* change back to root */ return(fp); } diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index 5a7fc10b9..77b121a38 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -136,13 +136,14 @@ struct sudo_user { /* * Used with set_perms() */ -#define PERM_ROOT 0x00 -#define PERM_USER 0x01 -#define PERM_FULL_USER 0x02 -#define PERM_SUDOERS 0x03 -#define PERM_RUNAS 0x04 -#define PERM_FULL_RUNAS 0x05 -#define PERM_TIMESTAMP 0x06 +#define PERM_INITIAL 0x00 +#define PERM_ROOT 0x01 +#define PERM_USER 0x02 +#define PERM_FULL_USER 0x03 +#define PERM_SUDOERS 0x04 +#define PERM_RUNAS 0x05 +#define PERM_FULL_RUNAS 0x06 +#define PERM_TIMESTAMP 0x07 #define PERM_NOEXIT 0x10 /* flag */ #define PERM_MASK 0xf0 @@ -236,6 +237,7 @@ int sudo_file_display_defaults(struct sudo_nss *, struct passwd *, struct lbuf * int sudo_file_display_bound_defaults(struct sudo_nss *, struct passwd *, struct lbuf *); int sudo_file_display_privs(struct sudo_nss *, struct passwd *, struct lbuf *); int set_perms(int); +int restore_perms(void); void remove_timestamp(int); int check_secureware(char *); void sia_attempt_auth(void);