On Fri, Dec 23, 2016 at 09:35:06PM -0700, Theo de Raadt wrote:
> This is why sshd has to be started with an absolute path, to
> avoid this problem. Path games like this worried us.
I doubt that it makes sense to require an absolute path for all our
daemons. It would break commands like 'pkill relayd; relayd'. So
we should keep the p in execvp(3).
sshd can be considered special as it gives shell access and has a
broader attack vector.
> By removing this, you could be adding some subtle risk...
I considered it and concluded that I reduced the risk a bit.
Currently syslogd searches the relative path from "/" with my diff
it starts from "." . The latter is better as we know it will find
the running syslogd binary there.
The current implementation is just wrong. Started with an relative
path it fails silently. Only -d gives the reason.
root@q70:.../sbin# ./syslogd -d
CAfile /etc/ssl/cert.pem
off & running....
syslogd: init
exec priv './syslogd' failed: No such file or directory
But I found another issue. When the parent process receives a
SIGHUP, it does an execvp(3) on itself. This still fails with my
diff. We could remove chdir("/") in the parent completely, but I
think this is too dangerous.
As a compromise between convenience and security I suggest to forbid
relative paths. PATH search and absolute paths are still possible.
ok?
bluhm
Index: usr.sbin/syslogd/syslogd.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.224
diff -u -p -r1.224 syslogd.c
--- usr.sbin/syslogd/syslogd.c 23 Dec 2016 23:01:48 -0000 1.224
+++ usr.sbin/syslogd/syslogd.c 25 Dec 2016 14:31:34 -0000
@@ -361,6 +361,9 @@ main(int argc, char *argv[])
int fd_ctlsock, fd_klog, fd_sendsys, fd_bind, fd_listen;
int *fd_unix;
+ if (argv[0][0] != '/' && strchr(argv[0], '/'))
+ errx(1, "Cannot execute with relative path: %s", argv[0]);
+
if ((path_unix = malloc(sizeof(*path_unix))) == NULL)
err(1, "malloc %s", _PATH_LOG);
path_unix[0] = _PATH_LOG;