On Tue, May 21, 2019 at 01:07:10PM -0400, Ted Unangst wrote:
> 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.
ok lteo@
> 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);
>
>