pflogd contained the same "privsep error" as tcpdump -- assuming that
authorderaadt <deraadt@openbsd.org>
Sat, 10 Oct 2015 22:36:06 +0000 (22:36 +0000)
committerderaadt <deraadt@openbsd.org>
Sat, 10 Oct 2015 22:36:06 +0000 (22:36 +0000)
it can ioctl()'s against a bpf device node.  Privsep that operation
via a message to the parent process.  Unfortunately "rpath wpath cpath"
is still needed due to SIGHUP handling, but I have asked canacar the
expert to look into this.

sbin/pflogd/pflogd.c
sbin/pflogd/pflogd.h
sbin/pflogd/privsep.c

index be06312..1b6354b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pflogd.c,v 1.51 2015/02/07 02:09:13 deraadt Exp $     */
+/*     $OpenBSD: pflogd.c,v 1.52 2015/10/10 22:36:06 deraadt Exp $     */
 
 /*
  * Copyright (c) 2001 Theo de Raadt
@@ -561,8 +561,9 @@ void
 log_pcap_stats(void)
 {
        struct pcap_stat pstat;
-       if (pcap_stats(hpcap, &pstat) < 0)
-               logmsg(LOG_WARNING, "Reading stats: %s", pcap_geterr(hpcap));
+
+       if (priv_pcap_stats(&pstat) < 0)
+               logmsg(LOG_WARNING, "Reading stats: error");
        else
                logmsg(LOG_NOTICE,
                        "%u packets received, %u/%u dropped (kernel/pflogd)",
@@ -655,6 +656,12 @@ main(int argc, char **argv)
                exit(1);
        }
 
+       /*
+        * XXX needs wpath cpath rpath, for try_reset_dump() ?
+        */
+       if (pledge("stdio rpath wpath cpath unix recvfd", NULL) == -1)
+               err(1, "pledge");
+
        setproctitle("[initializing]");
        /* Process is now unprivileged and inside a chroot */
        signal(SIGTERM, sig_close);
index c7ef80e..7bab611 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pflogd.h,v 1.4 2010/09/21 05:56:58 henning Exp $ */
+/*     $OpenBSD: pflogd.h,v 1.5 2015/10/10 22:36:06 deraadt Exp $ */
 
 /*
  * Copyright (c) 2003 Can Erkin Acar
@@ -38,6 +38,7 @@ int   priv_init(void);
 int    priv_set_snaplen(int snaplen);
 int    priv_open_log(void);
 int    priv_move_log(void);
+int    priv_pcap_stats(struct pcap_stat *);
 pcap_t *pcap_open_live_fd(int fd, int snaplen, char *ebuf);
 
 void set_pcap_filter(void);
index bb05106..03f86fa 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: privsep.c,v 1.20 2015/04/28 05:54:31 mlarkin Exp $    */
+/*     $OpenBSD: privsep.c,v 1.21 2015/10/10 22:36:06 deraadt Exp $    */
 
 /*
  * Copyright (c) 2003 Can Erkin Acar
@@ -42,7 +42,8 @@
 enum cmd_types {
        PRIV_SET_SNAPLEN,       /* set the snaplength */
        PRIV_MOVE_LOG,          /* move logfile away */
-       PRIV_OPEN_LOG           /* open logfile for appending */
+       PRIV_OPEN_LOG,          /* open logfile for appending */
+       PRIV_PCAP_STATS         /* get pcap statistics */
 };
 
 static int priv_fd = -1;
@@ -65,8 +66,9 @@ extern pcap_t *hpcap;
 int
 priv_init(void)
 {
-       int i, fd, socks[2], cmd;
+       int i, bpfd = -1, socks[2], cmd;
        int snaplen, ret, olderrno;
+       struct pcap_stat stats;
        struct passwd *pw;
 
        for (i = 1; i < _NSIG; i++)
@@ -118,6 +120,12 @@ priv_init(void)
        setproctitle("[priv]");
        close(socks[1]);
 
+
+#if notyet
+       /* This needs to do bpf ioctl */
+       if (pledge("stdio rpath wpath cpath ioctl sendfd", NULL) == -1)
+               err(1, "pledge");
+#endif
        while (!gotsig_chld) {
                if (may_read(socks[0], &cmd, sizeof(int)))
                        break;
@@ -141,17 +149,19 @@ priv_init(void)
                        logmsg(LOG_DEBUG,
                            "[priv]: msg PRIV_OPEN_LOG received");
                        /* create or append logs but do not follow symlinks */
-                       fd = open(filename,
+                       if (bpfd != -1) {
+                               close(bpfd);
+                               bpfd = -1;
+                       }
+                       bpfd = open(filename,
                            O_RDWR|O_CREAT|O_APPEND|O_NONBLOCK|O_NOFOLLOW,
                            0600);
                        olderrno = errno;
-                       send_fd(socks[0], fd);
-                       if (fd < 0)
+                       send_fd(socks[0], bpfd);
+                       if (bpfd < 0)
                                logmsg(LOG_NOTICE,
                                    "[priv]: failed to open %s: %s",
                                    filename, strerror(olderrno));
-                       else
-                               close(fd);
                        break;
 
                case PRIV_MOVE_LOG:
@@ -161,6 +171,19 @@ priv_init(void)
                        must_write(socks[0], &ret, sizeof(int));
                        break;
 
+               case PRIV_PCAP_STATS:
+                       if (ioctl(bpfd, BIOCGSTATS, &stats) == -1) {
+                               int rval = -1;
+                               memset(&stats, 0, sizeof stats);
+                               must_write(socks[0], &stats, sizeof(stats));
+                               must_write(socks[0], &rval, sizeof(rval));
+                       } else {
+                               int rval = 0;
+                               must_write(socks[0], &stats, sizeof(stats));
+                               must_write(socks[0], &rval, sizeof(rval));
+                       }
+                       break;
+                       
                default:
                        logmsg(LOG_ERR, "[priv]: unknown command %d", cmd);
                        _exit(1);
@@ -265,6 +288,7 @@ priv_open_log(void)
 
        return (fd);
 }
+
 /* Move-away and reopen log-file */
 int
 priv_move_log(void)
@@ -281,6 +305,23 @@ priv_move_log(void)
        return (ret);
 }
 
+/* Get statistics */
+int
+priv_pcap_stats(struct pcap_stat *ps)
+{
+       int cmd, ret;
+
+       if (priv_fd < 0)
+               errx(1, "%s: called from privileged portion", __func__);
+
+       cmd = PRIV_PCAP_STATS;
+       must_write(priv_fd, &cmd, sizeof (int));
+       must_read(priv_fd, ps, sizeof(*ps));
+       must_read(priv_fd, &ret, sizeof(ret));
+
+       return (ret);
+}
+
 /* If priv parent gets a TERM or HUP, pass it through to child instead */
 static void
 sig_pass_to_chld(int sig)