2004 privsep caused "tcpdump -r" to became a priviledged operation because
authorderaadt <deraadt@openbsd.org>
Thu, 21 Jul 2016 07:22:38 +0000 (07:22 +0000)
committerderaadt <deraadt@openbsd.org>
Thu, 21 Jul 2016 07:22:38 +0000 (07:22 +0000)
we felt chroot-containment was also necessary for off-line analysis.  Today
use of pledge "stdio" for the packet parser acts as an even better sandbox.
We can therefore silently ignore chroot setup failure, and regain tcpdump -r
support.

Result of a discussion with tedu -- which probably happened because we
became aware of the laughable retarded -Z option in upstream tcpdump.
ok tedu sthen guenther stsp

usr.sbin/tcpdump/privsep.c

index bd23597..8bc37b6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: privsep.c,v 1.40 2015/12/05 19:27:17 mmcc Exp $       */
+/*     $OpenBSD: privsep.c,v 1.41 2016/07/21 07:22:38 deraadt Exp $    */
 
 /*
  * Copyright (c) 2003 Can Erkin Acar
@@ -136,16 +136,11 @@ priv_init(int argc, char **argv)
        int bpfd = -1;
        int i, socks[2], cmd, nflag = 0;
        struct passwd *pw;
-       uid_t uid;
-       gid_t gid;
        char *cmdbuf, *infile = NULL;
        char *RFileName = NULL;
        char *WFileName = NULL;
        sigset_t allsigs, oset;
 
-       if (geteuid() != 0)
-               errx(1, "need root privileges");
-
        closefrom(STDERR_FILENO + 1);
        for (i = 1; i < _NSIG; i++)
                signal(i, SIG_DFL);
@@ -162,31 +157,33 @@ priv_init(int argc, char **argv)
                err(1, "fork() failed");
 
        if (child_pid) {
-               /* Parent, drop privileges to _tcpdump */
+               close(socks[0]);
+               priv_fd = socks[1];
+
+               set_slave_signals();
+               sigprocmask(SIG_SETMASK, &oset, NULL);
+
+               /*
+                * Parent, attempt to drop privs and chroot.  If any of this
+                * fails that is OK, safety is still provided by pledge(2).
+                */
                pw = getpwnam("_tcpdump");
                if (pw == NULL)
-                       errx(1, "unknown user _tcpdump");
+                       return (0);
 
-               /* chroot, drop privs and return */
-               if (chroot(pw->pw_dir) != 0)
-                       err(1, "unable to chroot");
-               if (chdir("/") != 0)
-                       err(1, "unable to chdir");
+               /* Attempt to chroot */
+               if (chroot(pw->pw_dir) == -1)
+                       return (0);
+               if (chdir("/") == -1)
+                       return (0);
 
                /* drop to _tcpdump */
                if (setgroups(1, &pw->pw_gid) == -1)
-                       err(1, "setgroups() failed");
+                       return (0);
                if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
-                       err(1, "setresgid() failed");
+                       return (0);
                if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
-                       err(1, "setresuid() failed");
-               endpwent();
-
-               close(socks[0]);
-               priv_fd = socks[1];
-
-               set_slave_signals();
-               sigprocmask(SIG_SETMASK, &oset, NULL);
+                       return (0);
 
                return (0);
        }
@@ -194,15 +191,6 @@ priv_init(int argc, char **argv)
        sigprocmask(SIG_SETMASK, &oset, NULL);
        signal(SIGINT, SIG_IGN);
 
-       /* Child - drop suid privileges */
-       gid = getgid();
-       uid = getuid();
-
-       if (setresgid(gid, gid, gid) == -1)
-               err(1, "setresgid() failed");
-       if (setresuid(uid, uid, uid) == -1)
-               err(1, "setresuid() failed");
-
        /* parse the arguments for required options */
        opterr = 0;
        while ((i = getopt(argc, argv,