Finally, the last part..

Drop root privileges in the monitor process before we service any DNS
lookups for the parser process, and if we know beforehand that we never
will, chroot(2).

-Bryan.

diff -Nru tcpdump_orig/privsep.c tcpdump/privsep.c
--- usr.sbin/tcpdump/privsep.c  Tue Sep 19 13:31:52 2017
+++ usr.sbin/tcpdump/privsep.c  Tue Sep 19 13:34:07 2017
@@ -102,6 +102,8 @@
 
 extern void    set_slave_signals(void);
 
+static void    drop_privs(int);
+
 static void    impl_open_bpf(int, int *);
 static void    impl_open_dump(int, const char *);
 static void    impl_open_pfosfp(int);
@@ -119,11 +121,42 @@
 static void    test_state(int, int);
 static void    logmsg(int, const char *, ...);
 
+static void
+drop_privs(int nochroot)
+{
+       struct passwd *pw;
+
+       /*
+        * If run as regular user, then tcpdump will rely on
+        * pledge(2). If we are root, we want to chroot also..
+        */
+       if (getuid() != 0)
+               return;
+
+       pw = getpwnam("_tcpdump");
+       if (pw == NULL)
+               errx(1, "unknown user _tcpdump");
+
+       if (!nochroot) {
+               if (chroot(pw->pw_dir) == -1)
+                       err(1, "unable to chroot");
+               if (chdir("/") == -1)
+                       err(1, "unable to chdir");
+       }
+
+       /* drop to _tcpdump */
+       if (setgroups(1, &pw->pw_gid) == -1)
+               err(1, "setgroups() failed");
+       if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
+               err(1, "setresgid() failed");
+       if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
+               err(1, "setresuid() failed");
+}
+
 int
 priv_init(int argc, char **argv)
 {
        int i, nargc, socks[2];
-       struct passwd *pw;
        sigset_t allsigs, oset;
        char **privargv;
 
@@ -149,30 +182,8 @@
                set_slave_signals();
                sigprocmask(SIG_SETMASK, &oset, NULL);
 
-               /*
-                * If run as regular user, packet parser will rely on
-                * pledge(2). If we are root, we want to chroot also..
-                */
-               if (getuid() != 0)
-                       return (0);
+               drop_privs(0);
 
-               pw = getpwnam("_tcpdump");
-               if (pw == NULL)
-                       errx(1, "unknown user _tcpdump");
-
-               if (chroot(pw->pw_dir) == -1)
-                       err(1, "unable to chroot");
-               if (chdir("/") == -1)
-                       err(1, "unable to chdir");
-
-               /* drop to _tcpdump */
-               if (setgroups(1, &pw->pw_gid) == -1)
-                       err(1, "setgroups() failed");
-               if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
-                       err(1, "setresgid() failed");
-               if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
-                       err(1, "setresuid() failed");
-
                return (0);
        }
        close(socks[1]);
@@ -306,10 +317,12 @@
                        impl_init_done(sock, &bpfd);
 
                        if (!nflag && WFileName == NULL) {
+                               drop_privs(1);
                                /* XXX rpath for /etc/{ethers,rpc} */
                                if (pledge("stdio rpath dns bpf", NULL) == -1)
                                        err(1, "pledge");
                        } else {
+                               drop_privs(0);
                                if (pledge("stdio bpf", NULL) == -1)
                                        err(1, "pledge");
                        }

Reply via email to