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");
}