From: Todd C. Miller Date: Fri, 9 Mar 2012 22:07:41 +0000 (-0500) Subject: Better error messages, and added debugging throughout. X-Git-Tag: SUDO_1_8_5~1^2~164 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b49bb17c3e480fdcbeb46c1dc9f896df52fab798;p=sudo Better error messages, and added debugging throughout. Fixed seteuid() version of set_perms()/restore_perms(). Fixed logic bug in AIX version of restore_perms(). Added checks to avoid changing uid/gid when we don't have to. Never set gid/uid state to -1, use the old value instead. --- diff --git a/plugins/sudoers/set_perms.c b/plugins/sudoers/set_perms.c index 1f0a2ac69..4c5570edf 100644 --- a/plugins/sudoers/set_perms.c +++ b/plugins/sudoers/set_perms.c @@ -96,6 +96,9 @@ rewind_perms(void) #if defined(HAVE_SETRESUID) +#define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid || state->suid != ostate->suid) +#define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid || state->sgid != ostate->sgid) + /* * 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(). @@ -106,7 +109,7 @@ int set_perms(int perm) { struct perm_state *state, *ostate = NULL; - const char *errstr; + char errbuf[1024]; int noexit; debug_decl(set_perms, SUDO_DEBUG_PERMS) @@ -114,7 +117,7 @@ set_perms(int perm) CLR(perm, PERM_MASK); if (perm_stack_depth == PERM_STACK_MAX) { - errstr = _("perm stack overflow"); + strlcpy(errbuf, _("perm stack overflow"), sizeof(errbuf)); errno = EINVAL; goto bad; } @@ -122,7 +125,7 @@ set_perms(int perm) state = &perm_stack[perm_stack_depth]; if (perm != PERM_INITIAL) { if (perm_stack_depth == 0) { - errstr = _("perm stack underflow"); + strlcpy(errbuf, _("perm stack underflow"), sizeof(errbuf)); errno = EINVAL; goto bad; } @@ -136,12 +139,12 @@ set_perms(int perm) /* Stash initial state */ #ifdef HAVE_GETRESUID if (getresuid(&state->ruid, &state->euid, &state->suid)) { - errstr = "getresuid"; + strlcpy(errbuf, "PERM_INITIAL: getresuid", sizeof(errbuf)); goto bad; } if (getresgid(&state->rgid, &state->egid, &state->sgid)) { - errstr = "getresgid"; + strlcpy(errbuf, "PERM_INITIAL: getresgid", sizeof(errbuf)); goto bad; } #else @@ -155,44 +158,64 @@ set_perms(int perm) #endif state->grlist = user_group_list; grlist_addref(state->grlist); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " + "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d", + __func__, (int)state->ruid, (int)state->euid, (int)state->suid, + (int)state->rgid, (int)state->egid, (int)state->sgid); break; case PERM_ROOT: state->ruid = ROOT_UID; state->euid = ROOT_UID; state->suid = ROOT_UID; - if (setresuid(ID(ruid), ID(euid), ID(suid))) { - errstr = "setresuid(ROOT_UID, ROOT_UID, ROOT_UID)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) { + snprintf(errbuf, sizeof(errbuf), + "PERM_ROOT: setresuid(%d, %d, %d)", + ID(ruid), ID(euid), ID(suid)); goto bad; } - state->rgid = -1; - state->egid = -1; - state->sgid = -1; + state->rgid = ostate->rgid; + state->egid = ostate->egid; + state->sgid = ostate->sgid; state->grlist = ostate->grlist; grlist_addref(state->grlist); break; case PERM_USER: - state->rgid = -1; + state->rgid = ostate->rgid; state->egid = user_gid; - state->sgid = -1; - if (setresgid(-1, ID(egid), -1)) { - errstr = "setresgid(-1, user_gid, -1)"; + state->sgid = ostate->sgid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid, + (int)state->rgid, (int)state->egid, (int)state->sgid); + if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) { + snprintf(errbuf, sizeof(errbuf), "PERM_USER: setresgid(%d, %d, %d)", + ID(rgid), ID(egid), ID(sgid)); goto bad; } state->grlist = user_group_list; grlist_addref(state->grlist); if (state->grlist != ostate->grlist) { if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { - errstr = "setgroups()"; + strlcpy(errbuf, "PERM_USER: setgroups", sizeof(errbuf)); goto bad; } } state->ruid = user_uid; state->euid = user_uid; state->suid = ROOT_UID; - if (setresuid(ID(ruid), ID(euid), ID(suid))) { - errstr = "setresuid(user_uid, user_uid, ROOT_UID)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) { + snprintf(errbuf, sizeof(errbuf), "PERM_USER: setresuid(%d, %d, %d)", + ID(ruid), ID(euid), ID(suid)); goto bad; } break; @@ -202,41 +225,61 @@ set_perms(int perm) state->rgid = user_gid; state->egid = user_gid; state->sgid = user_gid; - if (setresgid(ID(rgid), ID(egid), ID(sgid))) { - errstr = "setresgid(user_gid, user_gid, user_gid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid, + (int)state->rgid, (int)state->egid, (int)state->sgid); + if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) { + snprintf(errbuf, sizeof(errbuf), + "PERM_FULL_USER: setresgid(%d, %d, %d)", + ID(rgid), ID(egid), ID(sgid)); goto bad; } state->grlist = user_group_list; grlist_addref(state->grlist); if (state->grlist != ostate->grlist) { if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { - errstr = "setgroups()"; + strlcpy(errbuf, "PERM_FULL_USER: setgroups", sizeof(errbuf)); goto bad; } } state->ruid = user_uid; state->euid = user_uid; state->suid = user_uid; - if (setresuid(ID(ruid), ID(euid), ID(suid))) { - errstr = "setresuid(user_uid, user_uid, user_uid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) { + snprintf(errbuf, sizeof(errbuf), + "PERM_FULL_USER: setresuid(%d, %d, %d)", + ID(ruid), ID(euid), ID(suid)); goto bad; } break; case PERM_RUNAS: - state->rgid = -1; + state->rgid = ostate->rgid; state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid; - state->sgid = -1; - if (setresgid(-1, ID(egid), -1)) { - errstr = _("unable to change to runas gid"); + state->sgid = ostate->sgid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid, + (int)state->rgid, (int)state->egid, (int)state->sgid); + if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) { + strlcpy(errbuf, _("unable to change to runas gid"), sizeof(errbuf)); goto bad; } state->grlist = runas_setgroups(); - state->ruid = -1; + state->ruid = ostate->ruid; state->euid = runas_pw ? runas_pw->pw_uid : user_uid; - state->suid = -1; - if (setresuid(-1, ID(euid), -1)) { - errstr = _("unable to change to runas uid"); + state->suid = ostate->suid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) { + strlcpy(errbuf, _("unable to change to runas uid"), sizeof(errbuf)); goto bad; } break; @@ -246,10 +289,14 @@ set_perms(int perm) grlist_addref(state->grlist); /* assumes euid == ROOT_UID, ruid == user */ - state->rgid = -1; + state->rgid = ostate->rgid; state->egid = sudoers_gid; - state->sgid = -1; - if (setresgid(-1, ID(egid), -1)) + state->sgid = ostate->sgid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid, + (int)state->rgid, (int)state->egid, (int)state->sgid); + if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) error(1, _("unable to change to sudoers gid")); state->ruid = ROOT_UID; @@ -263,8 +310,14 @@ set_perms(int perm) else state->euid = sudoers_uid; state->suid = ROOT_UID; - if (setresuid(ID(ruid), ID(euid), ID(suid))) { - errstr = "setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) { + snprintf(errbuf, sizeof(errbuf), + "PERM_SUDOERS: setresuid(%d, %d, %d)", + ID(ruid), ID(euid), ID(suid)); goto bad; } break; @@ -272,14 +325,20 @@ set_perms(int perm) case PERM_TIMESTAMP: state->grlist = ostate->grlist; grlist_addref(state->grlist); - state->rgid = -1; - state->egid = -1; - state->sgid = -1; + state->rgid = ostate->rgid; + state->egid = ostate->egid; + state->sgid = ostate->sgid; state->ruid = ROOT_UID; state->euid = timestamp_uid; state->suid = ROOT_UID; - if (setresuid(ID(ruid), ID(euid), ID(suid))) { - errstr = "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) { + snprintf(errbuf, sizeof(errbuf), + "PERM_TIMESTAMP: setresuid(%d, %d, %d)", + ID(ruid), ID(euid), ID(suid)); goto bad; } break; @@ -289,8 +348,7 @@ done: perm_stack_depth++; debug_return_bool(1); bad: - /* XXX - better warnings inline */ - warningx("%s: %s", errstr, + warningx("%s: %s", errbuf, errno == EAGAIN ? _("too many processes") : strerror(errno)); if (noexit) debug_return_bool(0); @@ -310,6 +368,13 @@ restore_perms(void) ostate = &perm_stack[perm_stack_depth - 2]; perm_stack_depth--; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d, %d] -> [%d, %d, %d]", + __func__, (int)state->ruid, (int)state->euid, (int)state->suid, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d, %d] -> [%d, %d, %d]", + __func__, (int)state->rgid, (int)state->egid, (int)state->sgid, + (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid); + /* XXX - more cases here where euid != ruid */ if (OID(euid) == ROOT_UID && state->euid != ROOT_UID) { if (setresuid(-1, ROOT_UID, -1)) { @@ -346,6 +411,9 @@ bad: #elif defined(_AIX) && defined(ID_SAVED) +#define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid || state->suid != ostate->suid) +#define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid || state->sgid != ostate->sgid) + /* * 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(). @@ -356,7 +424,7 @@ int set_perms(int perm) { struct perm_state *state, *ostate = NULL; - const char *errstr; + char errbuf[1024]; int noexit; debug_decl(set_perms, SUDO_DEBUG_PERMS) @@ -364,7 +432,7 @@ set_perms(int perm) CLR(perm, PERM_MASK); if (perm_stack_depth == PERM_STACK_MAX) { - errstr = _("perm stack overflow"); + strlcpy(errbuf, _("perm stack overflow"), sizeof(errbuf)); errno = EINVAL; goto bad; } @@ -372,7 +440,7 @@ set_perms(int perm) state = &perm_stack[perm_stack_depth]; if (perm != PERM_INITIAL) { if (perm_stack_depth == 0) { - errstr = _("perm stack underflow"); + strlcpy(errbuf, _("perm stack underflow"), sizeof(errbuf)); errno = EINVAL; goto bad; } @@ -392,50 +460,73 @@ set_perms(int perm) state->sgid = getgidx(ID_SAVED); state->grlist = user_group_list; grlist_addref(state->grlist); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " + "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d", + __func__, (unsigned int)state->ruid, (unsigned int)state->euid, + (unsigned int)state->suid, (unsigned int)state->rgid, + (unsigned int)state->egid, (unsigned int)state->sgid); break; case PERM_ROOT: - if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) { - errstr = "setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)"; - goto bad; - } state->ruid = ROOT_UID; state->euid = ROOT_UID; state->suid = ROOT_UID; - state->rgid = -1; - state->egid = -1; - state->sgid = -1; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (UID_CHANGED && setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_ROOT: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)", + ROOT_UID); + goto bad; + } + state->rgid = ostate->rgid; + state->egid = ostate->egid; + state->sgid = ostate->sgid; state->grlist = ostate->grlist; grlist_addref(state->grlist); break; case PERM_USER: - state->rgid = -1; + state->rgid = ostate->rgid; state->egid = user_gid; - state->sgid = -1; - if (setgidx(ID_EFFECTIVE, user_gid)) { - errstr = "setgidx(ID_EFFECTIVE, user_gid)"; + state->sgid = ostate->sgid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid, + (int)state->rgid, (int)state->egid, (int)state->sgid); + if (GID_CHANGED && setgidx(ID_EFFECTIVE, user_gid)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_USER: setgidx(ID_EFFECTIVE, %d)", user_gid); goto bad; } state->grlist = user_group_list; grlist_addref(state->grlist); if (state->grlist != ostate->grlist) { if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { - errstr = "setgroups()"; + strlcpy(errbuf, "PERM_USER: setgroups", sizeof(errbuf)); goto bad; } } - if (ID(ruid) != ROOT_UID || ID(euid) != ROOT_UID || ID(suid) != ROOT_UID) { + state->ruid = user_uid; + state->euid = user_uid; + state->suid = ROOT_UID; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (ostate->euid != ROOT_UID || ostate->suid != ROOT_UID) { if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) { - errstr = "setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)"; + snprintf(errbuf, sizeof(errbuf), + "PERM_USER: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)", + ROOT_UID); goto bad; } } - state->ruid = user_uid; - state->euid = user_uid; - state->suid = ROOT_UID; if (setuidx(ID_EFFECTIVE|ID_REAL, user_uid)) { - errstr = "setuidx(ID_EFFECTIVE|ID_REAL, user_uid)"; + snprintf(errbuf, sizeof(errbuf), + "PERM_USER: setuidx(ID_EFFECTIVE|ID_REAL, %d)", user_uid); goto bad; } break; @@ -445,41 +536,61 @@ set_perms(int perm) state->rgid = user_gid; state->egid = user_gid; state->sgid = user_gid; - if (setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, user_gid)) { - errstr = "setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, user_gid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid, + (int)state->rgid, (int)state->egid, (int)state->sgid); + if (GID_CHANGED && setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, user_gid)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_FULL_USER: setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)", + user_gid); goto bad; } state->grlist = user_group_list; grlist_addref(state->grlist); if (state->grlist != ostate->grlist) { if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { - errstr = "setgroups()"; + strlcpy(errbuf, "PERM_FULL_USER: setgroups", sizeof(errbuf)); goto bad; } } state->ruid = user_uid; state->euid = user_uid; state->suid = user_uid; - if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, user_uid)) { - errstr = "setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, user_uid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (UID_CHANGED && setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, user_uid)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_FULL_USER: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)", + user_uid); goto bad; } break; case PERM_RUNAS: - state->rgid = -1; + state->rgid = ostate->rgid; state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid; - state->sgid = -1; - if (setgidx(ID_EFFECTIVE, state->egid)) { - errstr = _("unable to change to runas gid"); + state->sgid = ostate->sgid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid, + (int)state->rgid, (int)state->egid, (int)state->sgid); + if (GID_CHANGED && setgidx(ID_EFFECTIVE, state->egid)) { + strlcpy(errbuf, _("unable to change to runas gid"), sizeof(errbuf)); goto bad; } state->grlist = runas_setgroups(); - state->ruid = -1; + state->ruid = ostate->ruid; state->euid = runas_pw ? runas_pw->pw_uid : user_uid; - state->suid = -1; - if (setuidx(ID_EFFECTIVE, state->euid)) { - errstr = _("unable to change to runas uid"); + state->suid = ostate->suid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (UID_CHANGED && setuidx(ID_EFFECTIVE, state->euid)) { + strlcpy(errbuf, _("unable to change to runas uid"), sizeof(errbuf)); goto bad; } break; @@ -489,10 +600,14 @@ set_perms(int perm) grlist_addref(state->grlist); /* assume euid == ROOT_UID, ruid == user */ - state->rgid = -1; + state->rgid = ostate->rgid; state->egid = sudoers_gid; - state->sgid = -1; - if (setgidx(ID_EFFECTIVE, sudoers_gid)) + state->sgid = ostate->sgid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid, + (int)state->rgid, (int)state->egid, (int)state->sgid); + if (GID_CHANGED && setgidx(ID_EFFECTIVE, sudoers_gid)) error(1, _("unable to change to sudoers gid")); state->ruid = ROOT_UID; @@ -506,37 +621,55 @@ set_perms(int perm) else state->euid = sudoers_uid; state->suid = ROOT_UID; - if (ID(ruid) != ROOT_UID || ID(suid) != ROOT_UID) { - if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) { - errstr = "setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (UID_CHANGED) { + if (ostate->ruid != ROOT_UID || ostate->suid != ROOT_UID) { + if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_SUDOERS: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)", + ROOT_UID); + goto bad; + } + } + if (setuidx(ID_EFFECTIVE, state->euid)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_SUDOERS: setuidx(ID_EFFECTIVE, %d)", sudoers_uid); goto bad; } } - if (setuidx(ID_EFFECTIVE, state->euid)) { - errstr = "setuidx(ID_EFFECTIVE, SUDOERS_UID)"; - goto bad; - } break; case PERM_TIMESTAMP: state->grlist = ostate->grlist; grlist_addref(state->grlist); - state->rgid = -1; - state->egid = -1; - state->sgid = -1; + state->rgid = ostate->rgid; + state->egid = ostate->egid; + state->sgid = ostate->sgid; state->ruid = ROOT_UID; state->euid = timestamp_uid; state->suid = ROOT_UID; - if (ID(ruid) != ROOT_UID || ID(suid) != ROOT_UID) { - if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) { - errstr = "setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: " + "[%d, %d, %d] -> [%d, %d, %d]", __func__, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid, + (int)state->ruid, (int)state->euid, (int)state->suid); + if (UID_CHANGED) { + if (ostate->ruid != ROOT_UID || ostate->suid != ROOT_UID) { + if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_TIMESTAMP: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)", + ROOT_UID); + goto bad; + } + } + if (setuidx(ID_EFFECTIVE, timestamp_uid)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_TIMESTAMP: setuidx(ID_EFFECTIVE, %d)", timestamp_uid); goto bad; } } - if (setuidx(ID_EFFECTIVE, timestamp_uid)) { - errstr = "setuidx(ID_EFFECTIVE, timestamp_uid)"; - goto bad; - } break; } @@ -544,8 +677,7 @@ done: perm_stack_depth++; debug_return_bool(1); bad: - /* XXX - better warnings inline */ - warningx("%s: %s", errstr, + warningx("%s: %s", errbuf, errno == EAGAIN ? _("too many processes") : strerror(errno)); if (noexit) debug_return_bool(0); @@ -565,6 +697,13 @@ restore_perms(void) ostate = &perm_stack[perm_stack_depth - 2]; perm_stack_depth--; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d, %d] -> [%d, %d, %d]", + __func__, (int)state->ruid, (int)state->euid, (int)state->suid, + (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d, %d] -> [%d, %d, %d]", + __func__, (int)state->rgid, (int)state->egid, (int)state->sgid, + (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid); + if (OID(ruid) != -1 && OID(euid) != -1 && OID(suid) != -1) { /* XXX - more cases here where euid != ruid */ if (OID(euid) == ROOT_UID && state->euid != ROOT_UID) { @@ -575,7 +714,7 @@ restore_perms(void) goto bad; } } - if (OID(ruid) == OID(euid) == OID(suid)) { + if (OID(ruid) == OID(euid) && OID(euid) == OID(suid)) { if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, OID(ruid))) { warning("setuidx() [%d, %d, %d] -> [%d, %d, %d]", (int)state->ruid, (int)state->euid, (int)state->suid, @@ -599,7 +738,7 @@ restore_perms(void) } } if (OID(rgid) != -1 && OID(egid) != -1 && OID(sgid) != -1) { - if (OID(rgid) == OID(egid) == OID(sgid)) { + if (OID(rgid) == OID(egid) && OID(egid) == OID(sgid)) { if (setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, OID(rgid))) { warning("setgidx() [%d, %d, %d] -> [%d, %d, %d]", (int)state->rgid, (int)state->egid, (int)state->sgid, @@ -637,6 +776,9 @@ bad: #elif defined(HAVE_SETREUID) +#define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid) +#define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid) + /* * 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(). @@ -647,7 +789,7 @@ int set_perms(int perm) { struct perm_state *state, *ostate = NULL; - const char *errstr; + char errbuf[1024]; int noexit; debug_decl(set_perms, SUDO_DEBUG_PERMS) @@ -655,7 +797,7 @@ set_perms(int perm) CLR(perm, PERM_MASK); if (perm_stack_depth == PERM_STACK_MAX) { - errstr = _("perm stack overflow"); + strlcpy(errbuf, _("perm stack overflow"), sizeof(errbuf)); errno = EINVAL; goto bad; } @@ -663,7 +805,7 @@ set_perms(int perm) state = &perm_stack[perm_stack_depth]; if (perm != PERM_INITIAL) { if (perm_stack_depth == 0) { - errstr = _("perm stack underflow"); + strlcpy(errbuf, _("perm stack underflow"), sizeof(errbuf)); errno = EINVAL; goto bad; } @@ -681,49 +823,68 @@ set_perms(int perm) state->egid = getegid(); state->grlist = user_group_list; grlist_addref(state->grlist); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " + "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__, + (int)state->ruid, (int)state->euid, + (int)state->rgid, (int)state->egid); break; case PERM_ROOT: + state->ruid = ROOT_UID; + state->euid = ROOT_UID; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, (int)state->ruid, (int)state->euid); /* * setreuid(0, 0) may fail on some systems if euid is not already 0. */ if (ostate->euid != ROOT_UID) { if (setreuid(-1, ROOT_UID)) { - errstr = "setreuid(-1, ROOT_UID)"; + snprintf(errbuf, sizeof(errbuf), + "PERM_ROOT: setreuid(-1, %d)", PERM_ROOT); goto bad; } } - state->euid = ROOT_UID; - if (setreuid(ID(ruid), -1)) { - errstr = "setreuid(ROOT_UID, -1)"; - goto bad; + if (ostate->ruid != ROOT_UID) { + if (setreuid(ROOT_UID, -1)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_ROOT: setreuid(%d, -1)", ROOT_UID); + goto bad; + } } - state->ruid = ROOT_UID; - state->rgid = -1; - state->egid = -1; + state->rgid = ostate->rgid; + state->egid = ostate->rgid; state->grlist = ostate->grlist; grlist_addref(state->grlist); break; case PERM_USER: - state->rgid = -1; + state->rgid = ostate->rgid; state->egid = user_gid; - if (setregid(-1, ID(egid))) { - errstr = "setregid(-1, user_gid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid, + (int)ostate->egid, (int)state->rgid, (int)state->egid); + if (GID_CHANGED && setregid(ID(rgid), ID(egid))) { + snprintf(errbuf, sizeof(errbuf), + "PERM_USER: setregid(%d, %d)", ID(rgid), ID(egid)); goto bad; } state->grlist = user_group_list; grlist_addref(state->grlist); if (state->grlist != ostate->grlist) { if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { - errstr = "setgroups()"; + strlcpy(errbuf, "PERM_USER: setgroups", sizeof(errbuf)); goto bad; } } state->ruid = ROOT_UID; state->euid = user_uid; - if (setreuid(ID(ruid), ID(euid))) { - errstr = "setreuid(ROOT_UID, user_uid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, (int)state->ruid, (int)state->euid); + if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) { + snprintf(errbuf, sizeof(errbuf), + "PERM_USER: setreuid(%d, %d)", ID(ruid), ID(euid)); goto bad; } break; @@ -732,38 +893,52 @@ set_perms(int perm) /* headed for exec() */ state->rgid = user_gid; state->egid = user_gid; - if (setregid(ID(rgid), ID(egid))) { - errstr = "setregid(user_gid, user_gid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid, + (int)ostate->egid, (int)state->rgid, (int)state->egid); + if (GID_CHANGED && setregid(ID(rgid), ID(egid))) { + snprintf(errbuf, sizeof(errbuf), + "PERM_FULL_USER: setregid(%d, %d)", ID(rgid), ID(egid)); goto bad; } state->grlist = user_group_list; grlist_addref(state->grlist); if (state->grlist != ostate->grlist) { if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { - errstr = "setgroups()"; + strlcpy(errbuf, "PERM_FULL_USER: setgroups", sizeof(errbuf)); goto bad; } } state->ruid = user_uid; state->euid = user_uid; - if (setreuid(ID(ruid), ID(euid))) { - errstr = "setreuid(user_uid, user_uid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, (int)state->ruid, (int)state->euid); + if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) { + snprintf(errbuf, sizeof(errbuf), + "PERM_FULL_USER: setreuid(%d, %d)", ID(ruid), ID(euid)); goto bad; } break; case PERM_RUNAS: - state->rgid = -1; + state->rgid = ostate->rgid; state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid; - if (setregid(ID(rgid), ID(egid))) { - errstr = _("unable to change to runas gid"); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid, + (int)ostate->egid, (int)state->rgid, (int)state->egid); + if (GID_CHANGED && setregid(ID(rgid), ID(egid))) { + strlcpy(errbuf, _("unable to change to runas gid"), sizeof(errbuf)); goto bad; } state->grlist = runas_setgroups(); state->ruid = ROOT_UID; state->euid = runas_pw ? runas_pw->pw_uid : user_uid; - if (setreuid(ID(ruid), ID(euid))) { - errstr = _("unable to change to runas uid"); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, (int)state->ruid, (int)state->euid); + if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) { + strlcpy(errbuf, _("unable to change to runas uid"), sizeof(errbuf)); goto bad; } break; @@ -773,9 +948,12 @@ set_perms(int perm) grlist_addref(state->grlist); /* assume euid == ROOT_UID, ruid == user */ - state->rgid = -1; + state->rgid = ostate->rgid; state->egid = sudoers_gid; - if (setregid(-1, ID(egid))) + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid, + (int)ostate->egid, (int)state->rgid, (int)state->egid); + if (GID_CHANGED && setregid(ID(rgid), ID(egid))) error(1, _("unable to change to sudoers gid")); state->ruid = ROOT_UID; @@ -788,8 +966,12 @@ set_perms(int perm) state->euid = 1; else state->euid = sudoers_uid; - if (setreuid(ID(ruid), ID(euid))) { - errstr = "setreuid(ROOT_UID, SUDOERS_UID)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, (int)state->ruid, (int)state->euid); + if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) { + snprintf(errbuf, sizeof(errbuf), + "PERM_SUDOERS: setreuid(%d, %d)", ID(ruid), ID(euid)); goto bad; } break; @@ -797,12 +979,16 @@ set_perms(int perm) case PERM_TIMESTAMP: state->grlist = ostate->grlist; grlist_addref(state->grlist); - state->rgid = -1; - state->egid = -1; + state->rgid = ostate->rgid; + state->egid = ostate->egid; state->ruid = ROOT_UID; state->euid = timestamp_uid; - if (setreuid(ID(ruid), ID(euid))) { - errstr = "setreuid(ROOT_UID, timestamp_uid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, (int)state->ruid, (int)state->euid); + if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) { + snprintf(errbuf, sizeof(errbuf), + "PERM_TIMESTAMP: setreuid(%d, %d)", ID(ruid), ID(euid)); goto bad; } break; @@ -812,8 +998,7 @@ done: perm_stack_depth++; debug_return_bool(1); bad: - /* XXX - better warnings inline */ - warningx("%s: %s", errstr, + warningx("%s: %s", errbuf, errno == EAGAIN ? _("too many processes") : strerror(errno)); if (noexit) debug_return_bool(0); @@ -833,6 +1018,13 @@ restore_perms(void) ostate = &perm_stack[perm_stack_depth - 2]; perm_stack_depth--; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d] -> [%d, %d]", + __func__, (int)state->ruid, (int)state->euid, + (int)ostate->ruid, (int)ostate->euid); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d] -> [%d, %d]", + __func__, (int)state->rgid, (int)state->egid, + (int)ostate->rgid, (int)ostate->egid); + /* * When changing euid to ROOT_UID, setreuid() may fail even if * the ruid is ROOT_UID so call setuid() first. @@ -872,6 +1064,8 @@ bad: #elif defined(HAVE_SETEUID) +#define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid) + /* * Set real and effective uids and gids based on perm. * We always retain a real or effective uid of ROOT_UID unless @@ -882,7 +1076,7 @@ int set_perms(int perm) { struct perm_state *state, *ostate = NULL; - const char *errstr; + char errbuf[1024]; int noexit; debug_decl(set_perms, SUDO_DEBUG_PERMS) @@ -890,7 +1084,7 @@ set_perms(int perm) CLR(perm, PERM_MASK); if (perm_stack_depth == PERM_STACK_MAX) { - errstr = _("perm stack overflow"); + strlcpy(errbuf, _("perm stack overflow"), sizeof(errbuf)); errno = EINVAL; goto bad; } @@ -898,7 +1092,7 @@ set_perms(int perm) state = &perm_stack[perm_stack_depth]; if (perm != PERM_INITIAL) { if (perm_stack_depth == 0) { - errstr = _("perm stack underflow"); + strlcpy(errbuf, _("perm stack underflow"), sizeof(errbuf)); errno = EINVAL; goto bad; } @@ -913,12 +1107,12 @@ set_perms(int perm) * real and effective uids to ROOT_UID initially to be safe. */ if (perm != PERM_INITIAL) { - if (seteuid(ROOT_UID)) { - errstr = "seteuid(ROOT_UID)"; + if (ostate->euid != ROOT_UID && seteuid(ROOT_UID)) { + snprintf(errbuf, sizeof(errbuf), "set_perms: seteuid(%d)", ROOT_UID); goto bad; } - if (setuid(ROOT_UID)) { - errstr = "setuid(ROOT_UID)"; + if (ostate->ruid != ROOT_UID && setuid(ROOT_UID)) { + snprintf(errbuf, sizeof(errbuf), "set_perms: setuid(%d)", ROOT_UID); goto bad; } } @@ -932,37 +1126,52 @@ set_perms(int perm) state->egid = getegid(); state->grlist = user_group_list; grlist_addref(state->grlist); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " + "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__, + (int)state->ruid, (int)state->euid, + (int)state->rgid, (int)state->egid); break; case PERM_ROOT: /* We already set ruid/euid above. */ + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, ROOT_UID, ROOT_UID); state->ruid = ROOT_UID; state->euid = ROOT_UID; - state->rgid = -1; - state->egid = -1; + state->rgid = ostate->rgid; + state->egid = ostate->egid; state->grlist = ostate->grlist; grlist_addref(state->grlist); break; case PERM_USER: state->egid = user_gid; - if (setegid(ID(egid))) { - errstr = "setegid(user_gid)"; + state->rgid = ostate->rgid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid, + (int)ostate->egid, (int)state->rgid, (int)state->egid); + if (GID_CHANGED && setegid(user_gid)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_USER: setegid(%d)", user_gid); goto bad; } state->grlist = user_group_list; grlist_addref(state->grlist); if (state->grlist != ostate->grlist) { if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { - errstr = "setgroups()"; + strlcpy(errbuf, "PERM_USER: setgroups", sizeof(errbuf)); goto bad; } } - state->rgid = -1; state->ruid = ROOT_UID; state->euid = user_uid; - if (seteuid(ID(euid))) { - errstr = "seteuid(user_uid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, (int)state->ruid, (int)state->euid); + if (seteuid(user_uid)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_USER: seteuid(%d)", user_uid); goto bad; } break; @@ -971,38 +1180,52 @@ set_perms(int perm) /* headed for exec() */ state->rgid = user_gid; state->egid = user_gid; - if (setgid(user_gid)) { - errstr = "setgid(user_gid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid, + (int)ostate->egid, (int)state->rgid, (int)state->egid); + if (GID_CHANGED && setgid(user_gid)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_FULL_USER: setgid(%d)", user_gid); goto bad; } state->grlist = user_group_list; grlist_addref(state->grlist); if (state->grlist != ostate->grlist) { if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { - errstr = "setgroups()"; + strlcpy(errbuf, "PERM_FULL_USER: setgroups", sizeof(errbuf)); goto bad; } } state->ruid = user_uid; state->euid = user_uid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, (int)state->ruid, (int)state->euid); if (setuid(user_uid)) { - errstr = "setuid(user_uid)"; + snprintf(errbuf, sizeof(errbuf), + "PERM_FULL_USER: setuid(%d)", user_uid); goto bad; } break; case PERM_RUNAS: - state->rgid = -1; + state->rgid = ostate->rgid; state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid; - if (setegid(ID(egid))) { - errstr = _("unable to change to runas gid"); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid, + (int)ostate->egid, (int)state->rgid, (int)state->egid); + if (GID_CHANGED && setegid(state->egid)) { + strlcpy(errbuf, _("unable to change to runas gid"), sizeof(errbuf)); goto bad; } state->grlist = runas_setgroups(); - state->ruid = -1; + state->ruid = ostate->ruid; state->euid = runas_pw ? runas_pw->pw_uid : user_uid; - if (seteuid(ID(euid))) { - errstr = _("unable to change to runas uid"); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, (int)state->ruid, (int)state->euid); + if (seteuid(state->euid)) { + strlcpy(errbuf, _("unable to change to runas uid"), sizeof(errbuf)); goto bad; } break; @@ -1012,9 +1235,12 @@ set_perms(int perm) grlist_addref(state->grlist); /* assume euid == ROOT_UID, ruid == user */ - state->rgid = -1; + state->rgid = ostate->rgid; state->egid = sudoers_gid; - if (setegid(ID(egid))) + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid, + (int)ostate->egid, (int)state->rgid, (int)state->egid); + if (GID_CHANGED && setegid(sudoers_gid)) error(1, _("unable to change to sudoers gid")); state->ruid = ROOT_UID; @@ -1027,8 +1253,12 @@ set_perms(int perm) state->euid = 1; else state->euid = sudoers_uid; - if (seteuid(ID(euid))) { - errstr = "seteuid(SUDOERS_UID)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, (int)state->ruid, (int)state->euid); + if (seteuid(state->euid)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_SUDOERS: seteuid(%d)", state->euid); goto bad; } break; @@ -1036,12 +1266,16 @@ set_perms(int perm) case PERM_TIMESTAMP: state->grlist = ostate->grlist; grlist_addref(state->grlist); - state->rgid = -1; - state->egid = -1; + state->rgid = ostate->rgid; + state->egid = ostate->egid; state->ruid = ROOT_UID; state->euid = timestamp_uid; - if (seteuid(ID(euid))) { - errstr = "seteuid(timestamp_uid)"; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: " + "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid, + (int)ostate->euid, (int)state->ruid, (int)state->euid); + if (seteuid(timestamp_uid)) { + snprintf(errbuf, sizeof(errbuf), + "PERM_TIMESTAMP: seteuid(%d)", timestamp_uid); goto bad; } break; @@ -1051,8 +1285,7 @@ done: perm_stack_depth++; debug_return_bool(1); bad: - /* XXX - better warnings inline */ - warningx("%s: %s", errstr, + warningx("%s: %s", errbuf, errno == EAGAIN ? _("too many processes") : strerror(errno)); if (noexit) debug_return_bool(0); @@ -1072,22 +1305,30 @@ restore_perms(void) ostate = &perm_stack[perm_stack_depth - 2]; perm_stack_depth--; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d] -> [%d, %d]", + __func__, (int)state->ruid, (int)state->euid, + (int)ostate->ruid, (int)ostate->euid); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d] -> [%d, %d]", + __func__, (int)state->rgid, (int)state->egid, + (int)ostate->rgid, (int)ostate->egid); + /* * Since we only have setuid() and seteuid() and semantics * for these calls differ on various systems, we set * real and effective uids to ROOT_UID initially to be safe. */ if (seteuid(ROOT_UID)) { - errstr = "seteuid(ROOT_UID)"; + warningx("seteuid() [%d] -> [%d]", (int)state->euid, ROOT_UID); goto bad; } if (setuid(ROOT_UID)) { - errstr = "setuid(ROOT_UID)"; + warningx("setuid() [%d, %d] -> [%d, %d]", (int)state->ruid, ROOT_UID, + ROOT_UID, ROOT_UID); goto bad; } - if (setegid(OID(egid))) { - warning("setegid(%d)", (int)OID(egid)); + if (OID(egid) != -1 && setegid(ostate->egid)) { + warning("setegid(%d)", (int)ostate->egid); goto bad; } if (state->grlist != ostate->grlist) { @@ -1096,8 +1337,8 @@ restore_perms(void) goto bad; } } - if (seteuid(OID(euid))) { - warning("seteuid(%d)", (int)OID(euid)); + if (OID(euid) != -1 && seteuid(ostate->euid)) { + warning("seteuid(%d)", ostate->euid); goto bad; } grlist_delref(state->grlist); @@ -1118,7 +1359,7 @@ int set_perms(int perm) { struct perm_state *state, *ostate = NULL; - const char *errstr; + char errbuf[1024]; int noexit; debug_decl(set_perms, SUDO_DEBUG_PERMS) @@ -1126,7 +1367,7 @@ set_perms(int perm) CLR(perm, PERM_MASK); if (perm_stack_depth == PERM_STACK_MAX) { - errstr = _("perm stack overflow"); + strlcpy(errbuf, _("perm stack overflow"), sizeof(errbuf)); errno = EINVAL; goto bad; } @@ -1134,7 +1375,7 @@ set_perms(int perm) state = &perm_stack[perm_stack_depth]; if (perm != PERM_INITIAL) { if (perm_stack_depth == 0) { - errstr = _("perm stack underflow"); + strlcpy(errbuf, _("perm stack underflow"), sizeof(errbuf)); errno = EINVAL; goto bad; } @@ -1150,33 +1391,42 @@ set_perms(int perm) state->rgid = getgid(); state->grlist = user_group_list; grlist_addref(state->grlist); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " + "ruid: %d, rgid: %d", __func__, (int)state->ruid, (int)state->rgid); break; case PERM_ROOT: state->ruid = ROOT_UID; - state->rgid = -1; + state->rgid = ostate->rgid; state->grlist = ostate->grlist; grlist_addref(state->grlist); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: " + "[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid); if (setuid(ROOT_UID)) { - errstr = "setuid(ROOT_UID)"; + snprintf(errbuf, sizeof(errbuf), "PERM_ROOT: setuid(%d)", ROOT_UID); goto bad; } break; case PERM_FULL_USER: state->rgid = user_gid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: " + "[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid); (void) setgid(user_gid); state->grlist = user_group_list; grlist_addref(state->grlist); if (state->grlist != ostate->grlist) { if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { - errstr = "setgroups()"; + strlcpy(errbuf, "PERM_FULL_USER: setgroups", sizeof(errbuf)) goto bad; } } state->ruid = user_uid; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: " + "[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid); if (setuid(user_uid)) { - errstr = "setuid(user_uid)"; + snprintf(errbuf, sizeof(errbuf), + "PERM_FULL_USER: setuid(%d)", user_uid); goto bad; } break; @@ -1193,8 +1443,7 @@ done: perm_stack_depth++; debug_return_bool(1); bad: - /* XXX - better warnings inline */ - warningx("%s: %s", errstr, + warningx("%s: %s", errbuf, errno == EAGAIN ? _("too many processes") : strerror(errno)); if (noexit) debug_return_bool(0); @@ -1214,6 +1463,11 @@ restore_perms(void) ostate = &perm_stack[perm_stack_depth - 2]; perm_stack_depth--; + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d] -> [%d]", + __func__, (int)state->ruid, (int)ostate->ruid) + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d] -> [%d]", + __func__, (int)state->rgid, (int)ostate->rgid); + if (OID(rgid) != -1 && setgid(ostate->rgid)) { warning("setgid(%d)", (int)ostate->rgid); goto bad;