From 0d5eb34f5e1374a4462dd25360b842b054aa1966 Mon Sep 17 00:00:00 2001 From: deraadt Date: Wed, 8 Aug 2018 18:32:51 +0000 Subject: [PATCH] After authentication is complete, unveil login.conf "r" (to discover login tweaks), and walk the path (would could be $PATH, or not) adding an unveil "x" to each possible executable which execvpe() could later be tried by execvpe. It would be great if we could do some unveil before authentication, but I failed to determine all the possibilities. Some problem reports by bluhm, tb, florian, and others during development In snaps for about 3 weeks. ok florian --- usr.bin/doas/doas.c | 54 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/usr.bin/doas/doas.c b/usr.bin/doas/doas.c index 9ec4257dffd..f20f5d35b69 100644 --- a/usr.bin/doas/doas.c +++ b/usr.bin/doas/doas.c @@ -1,4 +1,4 @@ -/* $OpenBSD: doas.c,v 1.72 2017/05/27 09:51:07 tedu Exp $ */ +/* $OpenBSD: doas.c,v 1.73 2018/08/08 18:32:51 deraadt Exp $ */ /* * Copyright (c) 2015 Ted Unangst * @@ -239,6 +239,44 @@ good: } } +int +unveilcommands(const char *ipath, const char *cmd) +{ + char *path = NULL, *p; + int unveils = 0; + + if (strchr(cmd, '/') != NULL) { + if (unveil(cmd, "x") != -1) + unveils++; + goto done; + } + + if (!ipath) { + errno = ENOENT; + goto done; + } + path = strdup(ipath); + if (!path) { + errno = ENOENT; + goto done; + } + for (p = path; p && *p; ) { + char buf[PATH_MAX]; + char *cp = strsep(&p, ":"); + + if (cp) { + int r = snprintf(buf, sizeof buf, "%s/%s", cp, cmd); + if (r != -1 && r < sizeof buf) { + if (unveil(buf, "x") != -1) + unveils++; + } + } + } +done: + free(path); + return (unveils); +} + int main(int argc, char **argv) { @@ -364,6 +402,15 @@ main(int argc, char **argv) authuser(myname, login_style, rule->options & PERSIST); } + if (unveil(_PATH_LOGIN_CONF, "r") == -1) + err(1, "unveil"); + if (rule->cmd) { + if (setenv("PATH", safepath, 1) == -1) + err(1, "failed to set PATH '%s'", safepath); + } + if (unveilcommands(getenv("PATH"), cmd) == 0) + goto fail; + if (pledge("stdio rpath getpw exec id", NULL) == -1) err(1, "pledge"); @@ -392,11 +439,8 @@ main(int argc, char **argv) envp = prepenv(rule); - if (rule->cmd) { - if (setenv("PATH", safepath, 1) == -1) - err(1, "failed to set PATH '%s'", safepath); - } execvpe(cmd, argv, envp); +fail: if (errno == ENOENT) errx(1, "%s: command not found", cmd); err(1, "%s", cmd); -- 2.20.1