I have a coming change which will need to access both the calling user and
target users' passwd entries. In order to accomplish this, we need to switch
to the reentrant flavor of getpwuid. No behaviorial change, but I think this
is clearer and less error prone as well, versus reusing a pointer to static
storage.

Index: doas.c
===================================================================
RCS file: /home/cvs/src/usr.bin/doas/doas.c,v
retrieving revision 1.74
diff -u -p -r1.74 doas.c
--- doas.c      17 Jan 2019 05:35:35 -0000      1.74
+++ doas.c      21 May 2019 17:04:04 -0000
@@ -289,13 +289,15 @@ main(int argc, char **argv)
        const char *cmd;
        char cmdline[LINE_MAX];
        char myname[_PW_NAME_LEN + 1];
-       struct passwd *pw;
+       char mypwbuf[_PW_BUF_LEN], targpwbuf[_PW_BUF_LEN];
+       struct passwd mypwstore, targpwstore;
+       struct passwd *mypw, *targpw;
        const struct rule *rule;
        uid_t uid;
        uid_t target = 0;
        gid_t groups[NGROUPS_MAX + 1];
        int ngroups;
-       int i, ch;
+       int i, ch, rv;
        int sflag = 0;
        int nflag = 0;
        char cwdpath[PATH_MAX];
@@ -346,10 +348,10 @@ main(int argc, char **argv)
        } else if ((!sflag && !argc) || (sflag && argc))
                usage();
 
-       pw = getpwuid(uid);
-       if (!pw)
-               err(1, "getpwuid failed");
-       if (strlcpy(myname, pw->pw_name, sizeof(myname)) >= sizeof(myname))
+       rv = getpwuid_r(uid, &mypwstore, mypwbuf, sizeof(mypwbuf), &mypw);
+       if (rv != 0 || mypw == NULL)
+               err(1, "getpwuid_r failed");
+       if (strlcpy(myname, mypw->pw_name, sizeof(myname)) >= sizeof(myname))
                errx(1, "pw_name too long");
        ngroups = getgroups(NGROUPS_MAX, groups);
        if (ngroups == -1)
@@ -359,7 +361,7 @@ main(int argc, char **argv)
        if (sflag) {
                sh = getenv("SHELL");
                if (sh == NULL || *sh == '\0') {
-                       shargv[0] = strdup(pw->pw_shell);
+                       shargv[0] = strdup(mypw->pw_shell);
                        if (shargv[0] == NULL)
                                err(1, NULL);
                } else
@@ -415,11 +417,11 @@ main(int argc, char **argv)
        if (pledge("stdio rpath getpw exec id", NULL) == -1)
                err(1, "pledge");
 
-       pw = getpwuid(target);
-       if (!pw)
+       rv = getpwuid_r(target, &targpwstore, targpwbuf, sizeof(targpwbuf), 
&targpw);
+       if (rv != 0 || targpw == NULL)
                errx(1, "no passwd entry for target");
 
-       if (setusercontext(NULL, pw, target, LOGIN_SETGROUP |
+       if (setusercontext(NULL, targpw, target, LOGIN_SETGROUP |
            LOGIN_SETPRIORITY | LOGIN_SETRESOURCES | LOGIN_SETUMASK |
            LOGIN_SETUSER) != 0)
                errx(1, "failed to set user context for target");
@@ -436,7 +438,7 @@ main(int argc, char **argv)
                err(1, "pledge");
 
        syslog(LOG_AUTHPRIV | LOG_INFO, "%s ran command %s as %s from %s",
-           myname, cmdline, pw->pw_name, cwd);
+           myname, cmdline, targpw->pw_name, cwd);
 
        envp = prepenv(rule);
 

Reply via email to