Imported Upstream version 1.8.7
[debian/sudo] / plugins / sudoers / set_perms.c
index 97d6ee9e755ea952cb5197915d1c8bb18d4213f9..a887a512455182a0cb0591910742c980e74c498d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994-1996,1998-2011 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1994-1996,1998-2013 Todd C. Miller <Todd.Miller@courtesan.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -21,7 +21,6 @@
 #include <config.h>
 
 #include <sys/types.h>
-#include <sys/param.h>
 #include <sys/stat.h>
 #include <stdio.h>
 #ifdef STDC_HEADERS
@@ -91,7 +90,7 @@ rewind_perms(void)
 
     while (perm_stack_depth > 1)
        restore_perms();
-    grlist_delref(perm_stack[0].grlist);
+    sudo_grlist_delref(perm_stack[0].grlist);
 
     debug_return;
 }
@@ -112,6 +111,7 @@ set_perms(int perm)
 {
     struct perm_state *state, *ostate = NULL;
     char errbuf[1024];
+    const char *errstr = errbuf;
     int noexit;
     debug_decl(set_perms, SUDO_DEBUG_PERMS)
 
@@ -119,7 +119,7 @@ set_perms(int perm)
     CLR(perm, PERM_MASK);
 
     if (perm_stack_depth == PERM_STACK_MAX) {
-       strlcpy(errbuf, _("perm stack overflow"), sizeof(errbuf));
+       errstr = N_("perm stack overflow");
        errno = EINVAL;
        goto bad;
     }
@@ -127,7 +127,7 @@ set_perms(int perm)
     state = &perm_stack[perm_stack_depth];
     if (perm != PERM_INITIAL) {
        if (perm_stack_depth == 0) {
-           strlcpy(errbuf, _("perm stack underflow"), sizeof(errbuf));
+           errstr = N_("perm stack underflow");
            errno = EINVAL;
            goto bad;
        }
@@ -139,12 +139,12 @@ set_perms(int perm)
        /* Stash initial state */
 #ifdef HAVE_GETRESUID
        if (getresuid(&state->ruid, &state->euid, &state->suid)) {
-           strlcpy(errbuf, "PERM_INITIAL: getresuid", sizeof(errbuf));
+           errstr = "PERM_INITIAL: getresuid";
            goto bad;
 
        }
        if (getresgid(&state->rgid, &state->egid, &state->sgid)) {
-           strlcpy(errbuf, "PERM_INITIAL: getresgid", sizeof(errbuf));
+           errstr = "PERM_INITIAL: getresgid";
            goto bad;
        }
 #else
@@ -157,7 +157,7 @@ set_perms(int perm)
        state->sgid = state->egid; /* in case we are setgid */
 #endif
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_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,
@@ -179,10 +179,18 @@ set_perms(int perm)
            goto bad;
        }
        state->rgid = ostate->rgid;
-       state->egid = ostate->egid;
+       state->egid = ROOT_GID;
        state->sgid = ostate->sgid;
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: 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))) {
+           errstr = N_("unable to change to root gid");
+           goto bad;
+       }
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        break;
 
     case PERM_USER:
@@ -199,10 +207,10 @@ set_perms(int perm)
            goto bad;
        }
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        if (state->grlist != ostate->grlist) {
            if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
-               strlcpy(errbuf, "PERM_USER: setgroups", sizeof(errbuf));
+               errstr = "PERM_USER: setgroups";
                goto bad;
            }
        }
@@ -236,10 +244,10 @@ set_perms(int perm)
            goto bad;
        }
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        if (state->grlist != ostate->grlist) {
            if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
-               strlcpy(errbuf, "PERM_FULL_USER: setgroups", sizeof(errbuf));
+               errstr = "PERM_FULL_USER: setgroups";
                goto bad;
            }
        }
@@ -267,7 +275,7 @@ set_perms(int perm)
            (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));
+           errstr = N_("unable to change to runas gid");
            goto bad;
        }
        state->grlist = runas_setgroups();
@@ -279,14 +287,14 @@ set_perms(int perm)
            (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));
+           errstr = N_("unable to change to runas uid");
            goto bad;
        }
        break;
 
     case PERM_SUDOERS:
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
 
        /* assumes euid == ROOT_UID, ruid == user */
        state->rgid = ostate->rgid;
@@ -297,7 +305,7 @@ set_perms(int perm)
            (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 sudoers gid"), sizeof(errbuf));
+           errstr = N_("unable to change to sudoers gid");
            goto bad;
        }
 
@@ -307,7 +315,7 @@ set_perms(int perm)
         * 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 == ROOT_UID && (sudoers_mode & 040))
+       if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
            state->euid = 1;
        else
            state->euid = sudoers_uid;
@@ -326,7 +334,7 @@ set_perms(int perm)
 
     case PERM_TIMESTAMP:
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        state->rgid = ostate->rgid;
        state->egid = ostate->egid;
        state->sgid = ostate->sgid;
@@ -349,7 +357,7 @@ set_perms(int perm)
     perm_stack_depth++;
     debug_return_bool(1);
 bad:
-    warningx("%s: %s", errbuf,
+    warningx("%s: %s", _(errstr),
        errno == EAGAIN ? _("too many processes") : strerror(errno));
     if (noexit)
        debug_return_bool(0);
@@ -403,7 +411,7 @@ restore_perms(void)
            goto bad;
        }
     }
-    grlist_delref(state->grlist);
+    sudo_grlist_delref(state->grlist);
     debug_return;
 
 bad:
@@ -426,6 +434,7 @@ set_perms(int perm)
 {
     struct perm_state *state, *ostate = NULL;
     char errbuf[1024];
+    const char *errstr = errbuf;
     int noexit;
     debug_decl(set_perms, SUDO_DEBUG_PERMS)
 
@@ -433,7 +442,7 @@ set_perms(int perm)
     CLR(perm, PERM_MASK);
 
     if (perm_stack_depth == PERM_STACK_MAX) {
-       strlcpy(errbuf, _("perm stack overflow"), sizeof(errbuf));
+       errstr = N_("perm stack overflow");
        errno = EINVAL;
        goto bad;
     }
@@ -441,7 +450,7 @@ set_perms(int perm)
     state = &perm_stack[perm_stack_depth];
     if (perm != PERM_INITIAL) {
        if (perm_stack_depth == 0) {
-           strlcpy(errbuf, _("perm stack underflow"), sizeof(errbuf));
+           errstr = N_("perm stack underflow");
            errno = EINVAL;
            goto bad;
        }
@@ -458,7 +467,7 @@ set_perms(int perm)
        state->egid = getgidx(ID_EFFECTIVE);
        state->sgid = getgidx(ID_SAVED);
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_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,
@@ -481,10 +490,18 @@ set_perms(int perm)
            goto bad;
        }
        state->rgid = ostate->rgid;
-       state->egid = ostate->egid;
+       state->egid = ROOT_GID;
        state->sgid = ostate->sgid;
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: 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, ROOT_GID)) {
+           errstr = N_("unable to change to root gid");
+           goto bad;
+       }
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        break;
 
     case PERM_USER:
@@ -501,10 +518,10 @@ set_perms(int perm)
            goto bad;
        }
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        if (state->grlist != ostate->grlist) {
            if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
-               strlcpy(errbuf, "PERM_USER: setgroups", sizeof(errbuf));
+               errstr = "PERM_USER: setgroups";
                goto bad;
            }
        }
@@ -546,10 +563,10 @@ set_perms(int perm)
            goto bad;
        }
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        if (state->grlist != ostate->grlist) {
            if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
-               strlcpy(errbuf, "PERM_FULL_USER: setgroups", sizeof(errbuf));
+               errstr = "PERM_FULL_USER: setgroups";
                goto bad;
            }
        }
@@ -577,7 +594,7 @@ set_perms(int perm)
            (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));
+           errstr = N_("unable to change to runas gid");
            goto bad;
        }
        state->grlist = runas_setgroups();
@@ -589,14 +606,14 @@ set_perms(int perm)
            (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));
+           errstr = N_("unable to change to runas uid");
            goto bad;
        }
        break;
 
     case PERM_SUDOERS:
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
 
        /* assume euid == ROOT_UID, ruid == user */
        state->rgid = ostate->rgid;
@@ -607,7 +624,7 @@ set_perms(int perm)
            (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)) {
-           strlcpy(errbuf, _("unable to change to sudoers gid"), sizeof(errbuf));
+           errstr = N_("unable to change to sudoers gid");
            goto bad;
        }
 
@@ -617,7 +634,7 @@ set_perms(int perm)
         * 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 == ROOT_UID && (sudoers_mode & 040))
+       if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
            state->euid = 1;
        else
            state->euid = sudoers_uid;
@@ -645,7 +662,7 @@ set_perms(int perm)
 
     case PERM_TIMESTAMP:
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        state->rgid = ostate->rgid;
        state->egid = ostate->egid;
        state->sgid = ostate->sgid;
@@ -677,7 +694,7 @@ set_perms(int perm)
     perm_stack_depth++;
     debug_return_bool(1);
 bad:
-    warningx("%s: %s", errbuf,
+    warningx("%s: %s", _(errstr),
        errno == EAGAIN ? _("too many processes") : strerror(errno));
     if (noexit)
        debug_return_bool(0);
@@ -795,7 +812,7 @@ restore_perms(void)
            goto bad;
        }
     }
-    grlist_delref(state->grlist);
+    sudo_grlist_delref(state->grlist);
     debug_return;
 
 bad:
@@ -818,6 +835,7 @@ set_perms(int perm)
 {
     struct perm_state *state, *ostate = NULL;
     char errbuf[1024];
+    const char *errstr = errbuf;
     int noexit;
     debug_decl(set_perms, SUDO_DEBUG_PERMS)
 
@@ -825,7 +843,7 @@ set_perms(int perm)
     CLR(perm, PERM_MASK);
 
     if (perm_stack_depth == PERM_STACK_MAX) {
-       strlcpy(errbuf, _("perm stack overflow"), sizeof(errbuf));
+       errstr = N_("perm stack overflow");
        errno = EINVAL;
        goto bad;
     }
@@ -833,7 +851,7 @@ set_perms(int perm)
     state = &perm_stack[perm_stack_depth];
     if (perm != PERM_INITIAL) {
        if (perm_stack_depth == 0) {
-           strlcpy(errbuf, _("perm stack underflow"), sizeof(errbuf));
+           errstr = N_("perm stack underflow");
            errno = EINVAL;
            goto bad;
        }
@@ -848,7 +866,7 @@ set_perms(int perm)
        state->rgid = getgid();
        state->egid = getegid();
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_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,
@@ -879,9 +897,17 @@ set_perms(int perm)
            }
        }
        state->rgid = ostate->rgid;
-       state->egid = ostate->rgid;
+       state->egid = ROOT_GID;
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: 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_ROOT: setregid(%d, %d)", ID(rgid), ID(egid));
+           goto bad;
+       }
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        break;
 
     case PERM_USER:
@@ -896,10 +922,10 @@ set_perms(int perm)
            goto bad;
        }
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        if (state->grlist != ostate->grlist) {
            if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
-               strlcpy(errbuf, "PERM_USER: setgroups", sizeof(errbuf));
+               errstr = "PERM_USER: setgroups";
                goto bad;
            }
        }
@@ -928,10 +954,10 @@ set_perms(int perm)
            goto bad;
        }
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        if (state->grlist != ostate->grlist) {
            if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
-               strlcpy(errbuf, "PERM_FULL_USER: setgroups", sizeof(errbuf));
+               errstr = "PERM_FULL_USER: setgroups";
                goto bad;
            }
        }
@@ -954,7 +980,7 @@ set_perms(int perm)
            "[%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));
+           errstr = N_("unable to change to runas gid");
            goto bad;
        }
        state->grlist = runas_setgroups();
@@ -964,14 +990,14 @@ set_perms(int perm)
            "[%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));
+           errstr = N_("unable to change to runas uid");
            goto bad;
        }
        break;
 
     case PERM_SUDOERS:
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
 
        /* assume euid == ROOT_UID, ruid == user */
        state->rgid = ostate->rgid;
@@ -980,7 +1006,7 @@ set_perms(int perm)
            "[%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 sudoers gid"), sizeof(errbuf));
+           errstr = N_("unable to change to sudoers gid");
            goto bad;
        }
 
@@ -990,7 +1016,7 @@ set_perms(int perm)
         * 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 == ROOT_UID && (sudoers_mode & 040))
+       if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
            state->euid = 1;
        else
            state->euid = sudoers_uid;
@@ -1006,7 +1032,7 @@ set_perms(int perm)
 
     case PERM_TIMESTAMP:
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        state->rgid = ostate->rgid;
        state->egid = ostate->egid;
        state->ruid = ROOT_UID;
@@ -1025,7 +1051,7 @@ set_perms(int perm)
     perm_stack_depth++;
     debug_return_bool(1);
 bad:
-    warningx("%s: %s", errbuf,
+    warningx("%s: %s", _(errstr),
        errno == EAGAIN ? _("too many processes") : strerror(errno));
     if (noexit)
        debug_return_bool(0);
@@ -1059,7 +1085,7 @@ restore_perms(void)
     if (OID(euid) == ROOT_UID) {
        /* setuid() may not set the saved ID unless the euid is ROOT_UID */
        if (ID(euid) != ROOT_UID)
-           (void)setreuid(-1, ROOT_UID);
+           ignore_result(setreuid(-1, ROOT_UID));
        if (setuid(ROOT_UID)) {
            warning("setuid() [%d, %d] -> %d)", (int)state->ruid,
                (int)state->euid, ROOT_UID);
@@ -1082,7 +1108,7 @@ restore_perms(void)
            goto bad;
        }
     }
-    grlist_delref(state->grlist);
+    sudo_grlist_delref(state->grlist);
     debug_return;
 
 bad:
@@ -1104,6 +1130,7 @@ set_perms(int perm)
 {
     struct perm_state *state, *ostate = NULL;
     char errbuf[1024];
+    const char *errstr = errbuf;
     int noexit;
     debug_decl(set_perms, SUDO_DEBUG_PERMS)
 
@@ -1111,7 +1138,7 @@ set_perms(int perm)
     CLR(perm, PERM_MASK);
 
     if (perm_stack_depth == PERM_STACK_MAX) {
-       strlcpy(errbuf, _("perm stack overflow"), sizeof(errbuf));
+       errstr = N_("perm stack overflow");
        errno = EINVAL;
        goto bad;
     }
@@ -1119,7 +1146,7 @@ set_perms(int perm)
     state = &perm_stack[perm_stack_depth];
     if (perm != PERM_INITIAL) {
        if (perm_stack_depth == 0) {
-           strlcpy(errbuf, _("perm stack underflow"), sizeof(errbuf));
+           errstr = N_("perm stack underflow");
            errno = EINVAL;
            goto bad;
        }
@@ -1150,7 +1177,7 @@ set_perms(int perm)
        state->rgid = getgid();
        state->egid = getegid();
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_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,
@@ -1165,9 +1192,16 @@ set_perms(int perm)
        state->ruid = ROOT_UID;
        state->euid = ROOT_UID;
        state->rgid = ostate->rgid;
-       state->egid = ostate->egid;
+       state->egid = ROOT_GID;
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
+           "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+           (int)ostate->egid, ROOT_GID, ROOT_GID);
+       if (GID_CHANGED && setegid(ROOT_GID)) {
+           errstr = N_("unable to change to root gid");
+           goto bad;
+       }
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        break;
 
     case PERM_USER:
@@ -1182,10 +1216,10 @@ set_perms(int perm)
            goto bad;
        }
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        if (state->grlist != ostate->grlist) {
            if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
-               strlcpy(errbuf, "PERM_USER: setgroups", sizeof(errbuf));
+               errstr = "PERM_USER: setgroups";
                goto bad;
            }
        }
@@ -1214,10 +1248,10 @@ set_perms(int perm)
            goto bad;
        }
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        if (state->grlist != ostate->grlist) {
            if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
-               strlcpy(errbuf, "PERM_FULL_USER: setgroups", sizeof(errbuf));
+               errstr = "PERM_FULL_USER: setgroups";
                goto bad;
            }
        }
@@ -1240,7 +1274,7 @@ set_perms(int perm)
            "[%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));
+           errstr = N_("unable to change to runas gid");
            goto bad;
        }
        state->grlist = runas_setgroups();
@@ -1250,14 +1284,14 @@ set_perms(int perm)
            "[%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));
+           errstr = N_("unable to change to runas uid");
            goto bad;
        }
        break;
 
     case PERM_SUDOERS:
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
 
        /* assume euid == ROOT_UID, ruid == user */
        state->rgid = ostate->rgid;
@@ -1266,7 +1300,7 @@ set_perms(int perm)
            "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
            (int)ostate->egid, (int)state->rgid, (int)state->egid);
        if (GID_CHANGED && setegid(sudoers_gid)) {
-           strlcpy(errbuf, _("unable to change to sudoers gid"), sizeof(errbuf));
+           errstr = N_("unable to change to sudoers gid");
            goto bad;
        }
 
@@ -1276,7 +1310,7 @@ set_perms(int perm)
         * 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 == ROOT_UID && (sudoers_mode & 040))
+       if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
            state->euid = 1;
        else
            state->euid = sudoers_uid;
@@ -1292,7 +1326,7 @@ set_perms(int perm)
 
     case PERM_TIMESTAMP:
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        state->rgid = ostate->rgid;
        state->egid = ostate->egid;
        state->ruid = ROOT_UID;
@@ -1311,7 +1345,7 @@ set_perms(int perm)
     perm_stack_depth++;
     debug_return_bool(1);
 bad:
-    warningx("%s: %s", errbuf,
+    warningx("%s: %s", _(errstr),
        errno == EAGAIN ? _("too many processes") : strerror(errno));
     if (noexit)
        debug_return_bool(0);
@@ -1367,7 +1401,7 @@ restore_perms(void)
        warning("seteuid(%d)", ostate->euid);
        goto bad;
     }
-    grlist_delref(state->grlist);
+    sudo_grlist_delref(state->grlist);
     debug_return;
 
 bad:
@@ -1386,6 +1420,7 @@ set_perms(int perm)
 {
     struct perm_state *state, *ostate = NULL;
     char errbuf[1024];
+    const char *errstr = errbuf;
     int noexit;
     debug_decl(set_perms, SUDO_DEBUG_PERMS)
 
@@ -1393,7 +1428,7 @@ set_perms(int perm)
     CLR(perm, PERM_MASK);
 
     if (perm_stack_depth == PERM_STACK_MAX) {
-       strlcpy(errbuf, _("perm stack overflow"), sizeof(errbuf));
+       errstr = N_("perm stack overflow");
        errno = EINVAL;
        goto bad;
     }
@@ -1401,7 +1436,7 @@ set_perms(int perm)
     state = &perm_stack[perm_stack_depth];
     if (perm != PERM_INITIAL) {
        if (perm_stack_depth == 0) {
-           strlcpy(errbuf, _("perm stack underflow"), sizeof(errbuf));
+           errstr = N_("perm stack underflow");
            errno = EINVAL;
            goto bad;
        }
@@ -1414,39 +1449,45 @@ set_perms(int perm)
        state->ruid = geteuid() == ROOT_UID ? ROOT_UID : getuid();
        state->rgid = getgid();
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_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 = ostate->rgid;
+       state->rgid = ROOT_GID;
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_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)) {
            snprintf(errbuf, sizeof(errbuf), "PERM_ROOT: setuid(%d)", ROOT_UID);
            goto bad;
        }
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
+           "[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid);
+       if (setgid(ROOT_GID)) {
+           errstr = N_("unable to change to root gid");
+           goto bad;
+       }
        break;
 
     case PERM_FULL_USER:
        state->rgid = user_gid;
-       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
            "[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid);
        (void) setgid(user_gid);
        state->grlist = user_group_list;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        if (state->grlist != ostate->grlist) {
            if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
-               strlcpy(errbuf, "PERM_FULL_USER: setgroups", sizeof(errbuf));
+               errstr = "PERM_FULL_USER: setgroups";
                goto bad;
            }
        }
        state->ruid = user_uid;
-       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
            "[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid);
        if (setuid(user_uid)) {
            snprintf(errbuf, sizeof(errbuf),
@@ -1463,14 +1504,14 @@ set_perms(int perm)
        state->ruid = ostate->ruid;
        state->rgid = ostate->rgid;
        state->grlist = ostate->grlist;
-       grlist_addref(state->grlist);
+       sudo_grlist_addref(state->grlist);
        break;
     }
 
     perm_stack_depth++;
     debug_return_bool(1);
 bad:
-    warningx("%s: %s", errbuf,
+    warningx("%s: %s", _(errstr),
        errno == EAGAIN ? _("too many processes") : strerror(errno));
     if (noexit)
        debug_return_bool(0);
@@ -1505,7 +1546,7 @@ restore_perms(void)
            goto bad;
        }
     }
-    grlist_delref(state->grlist);
+    sudo_grlist_delref(state->grlist);
     if (OID(ruid) != -1 && setuid(ostate->ruid)) {
        warning("setuid(%d)", (int)ostate->ruid);
        goto bad;
@@ -1526,7 +1567,7 @@ runas_setgroups(void)
     debug_decl(runas_setgroups, SUDO_DEBUG_PERMS)
 
     if (def_preserve_groups) {
-       grlist_addref(user_group_list);
+       sudo_grlist_addref(user_group_list);
        debug_return_ptr(user_group_list);
     }
 
@@ -1534,12 +1575,12 @@ runas_setgroups(void)
 #ifdef HAVE_SETAUTHDB
     aix_setauthdb(pw->pw_name);
 #endif
-    grlist = get_group_list(pw);
+    grlist = sudo_get_grlist(pw);
 #ifdef HAVE_SETAUTHDB
     aix_restoreauthdb();
 #endif
     if (sudo_setgroups(grlist->ngids, grlist->gids) < 0)
-       log_fatal(USE_ERRNO|MSG_ONLY, _("unable to set runas group vector"));
+       log_fatal(USE_ERRNO|MSG_ONLY, N_("unable to set runas group vector"));
     debug_return_ptr(grlist);
 }
 #endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */