On Mon, Dec 26, 2016 at 09:08:22PM +0100, Jeremie Courreges-Anglas wrote:
> Alexander Bluhm <[email protected]> writes:
> Your last diff has a drawback: you can't simply start the daemon like
> this:
> 
> # syslogd
> 
> realpath will resolve "syslogd" to "/path/to/current/directory/syslogd".
> 
> Maybe call realpath only if argv[0] contains a slash?

better?

bluhm

Index: usr.sbin/syslogd/privsep.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/privsep.c,v
retrieving revision 1.64
diff -u -p -r1.64 privsep.c
--- usr.sbin/syslogd/privsep.c  16 Oct 2016 22:12:50 -0000      1.64
+++ usr.sbin/syslogd/privsep.c  26 Dec 2016 22:24:44 -0000
@@ -97,7 +97,7 @@ priv_init(int lockfd, int nullfd, int ar
 {
        int i, socks[2];
        struct passwd *pw;
-       char childnum[11], **privargv;
+       char *execpath, childnum[11], **privargv;
 
        /* Create sockets */
        if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, socks) == -1)
@@ -114,9 +114,9 @@ priv_init(int lockfd, int nullfd, int ar
        if (!child_pid) {
                /* Child - drop privileges and return */
                if (chroot(pw->pw_dir) != 0)
-                       err(1, "unable to chroot");
+                       err(1, "chroot %s", pw->pw_dir);
                if (chdir("/") != 0)
-                       err(1, "unable to chdir");
+                       err(1, "chdir %s", pw->pw_dir);
 
                if (setgroups(1, &pw->pw_gid) == -1)
                        err(1, "setgroups() failed");
@@ -130,6 +130,13 @@ priv_init(int lockfd, int nullfd, int ar
        }
        close(socks[1]);
 
+       if (strchr(argv[0], '/') == NULL)
+               execpath = argv[0];
+       else if ((execpath = realpath(argv[0], NULL)) == NULL)
+               err(1, "realpath %s", argv[0]);
+       if (chdir("/") != 0)
+               err(1, "chdir /");
+
        if (!Debug) {
                close(lockfd);
                dup2(nullfd, STDIN_FILENO);
@@ -147,7 +154,8 @@ priv_init(int lockfd, int nullfd, int ar
        snprintf(childnum, sizeof(childnum), "%d", child_pid);
        if ((privargv = reallocarray(NULL, argc + 3, sizeof(char *))) == NULL)
                err(1, "alloc priv argv failed");
-       for (i = 0; i < argc; i++)
+       privargv[0] = execpath;
+       for (i = 1; i < argc; i++)
                privargv[i] = argv[i];
        privargv[i++] = "-P";
        privargv[i++] = childnum;
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  26 Dec 2016 16:46:32 -0000
@@ -685,8 +685,6 @@ main(int argc, char *argv[])
 
        logdebug("off & running....\n");
 
-       chdir("/");
-
        tzset();
 
        if (!Debug && !Foreground) {

Reply via email to