My last diff was too big, here's an attempt to split it up for easier
review. Please apply them in order.

This hoists opening pf.os(5) fingerprints '-o' from the 'RUN' state to
the 'FILTER' state, this will allow for a reduced pledge(2) at runtime
in the monitor process.

-Bryan.

Index: pfctl_osfp.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/pfctl_osfp.c,v
retrieving revision 1.13
diff -u -p -u -r1.13 pfctl_osfp.c
--- usr.sbin/tcpdump/pfctl_osfp.c       28 May 2017 10:06:12 -0000      1.13
+++ usr.sbin/tcpdump/pfctl_osfp.c       19 Sep 2017 17:07:37 -0000
@@ -81,17 +81,14 @@ void                         print_name_list(int, struct 
name
 void                    sort_name_list(int, struct name_list *);
 struct name_entry      *lookup_name_list(struct name_list *, const char *);
 
-/* XXX arbitrary */
-#define MAX_FP_LINE 1024
-
 /* Load fingerprints from a file */
 int
 pfctl_file_fingerprints(int dev, int opts, const char *fp_filename)
 {
-       u_char buf[MAX_FP_LINE];
+       FILE *in;
        u_char *line;
        size_t len;
-       int i, lineno = 0;
+       int i, fd, lineno = 0;
        int window, w_mod, ttl, df, psize, p_mod, mss, mss_mod, wscale,
            wscale_mod, optcnt, ts0;
        pf_tcpopts_t packed_tcpopts;
@@ -99,15 +96,22 @@ pfctl_file_fingerprints(int dev, int opt
        struct pf_osfp_ioctl fp;
 
        pfctl_flush_my_fingerprints(&classes);
+       
+       fd = priv_open_pfosfp();
+       if (fd < 0)
+               return (1);
+       
+       if ((in = fdopen(fd, "r")) == NULL) {
+               warn("%s", fp_filename);
+               return (1);
+       }
+
        class = version = subtype = desc = tcpopts = NULL;
 
        if ((opts & PF_OPT_NOACTION) == 0)
                pfctl_clear_fingerprints(dev, opts);
 
-       priv_getlines(FTAB_PFOSFP);
-       while ((len = priv_getline(buf, sizeof(buf))) > 0) {
-               buf[len -1] = '\n';
-               line = buf;
+       while ((line = fgetln(in, &len)) != NULL) {
                lineno++;
                free(class);
                free(version);
Index: privsep.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/privsep.c,v
retrieving revision 1.47
diff -u -p -u -r1.47 privsep.c
--- usr.sbin/tcpdump/privsep.c  8 Sep 2017 19:30:13 -0000       1.47
+++ usr.sbin/tcpdump/privsep.c  19 Sep 2017 17:07:37 -0000
@@ -73,7 +73,8 @@ static const int allowed_max[] = {
        /* INIT */      ALLOW(PRIV_OPEN_BPF) | ALLOW(PRIV_OPEN_DUMP) |
                        ALLOW(PRIV_SETFILTER),
        /* BPF */       ALLOW(PRIV_SETFILTER),
-       /* FILTER */    ALLOW(PRIV_OPEN_OUTPUT) | ALLOW(PRIV_GETSERVENTRIES) |
+       /* FILTER */    ALLOW(PRIV_OPEN_PFOSFP) | ALLOW(PRIV_OPEN_OUTPUT) |
+                       ALLOW(PRIV_GETSERVENTRIES) |
                        ALLOW(PRIV_GETPROTOENTRIES) |
                        ALLOW(PRIV_ETHER_NTOHOST) | ALLOW(PRIV_INIT_DONE),
        /* RUN */       ALLOW(PRIV_GETHOSTBYADDR) | ALLOW(PRIV_ETHER_NTOHOST) |
@@ -114,6 +115,7 @@ extern void set_slave_signals(void);
 
 static void    impl_open_bpf(int, int *);
 static void    impl_open_dump(int, const char *);
+static void    impl_open_pfosfp(int);
 static void    impl_open_output(int, const char *);
 static void    impl_setfilter(int, char *, int *);
 static void    impl_init_done(int, int *);
@@ -207,7 +209,7 @@ __dead void
 priv_exec(int argc, char *argv[])
 {
        int bpfd = -1;
-       int i, sock, cmd, nflag = 0, Pflag = 0;
+       int i, sock, cmd, nflag = 0, oflag = 0, Pflag = 0;
        char *cmdbuf, *infile = NULL;
        char *RFileName = NULL;
        char *WFileName = NULL;
@@ -229,6 +231,10 @@ priv_exec(int argc, char *argv[])
                        nflag++;
                        break;
 
+               case 'o':
+                       oflag = 1;
+                       break;
+
                case 'r':
                        RFileName = optarg;
                        break;
@@ -273,6 +279,8 @@ priv_exec(int argc, char *argv[])
                allowed_ext[STATE_RUN] |= ALLOW(PRIV_GETRPCBYNUMBER);
                allowed_ext[STATE_FILTER] |= ALLOW(PRIV_GETPROTOENTRIES);
        }
+       if (oflag)
+               allowed_ext[STATE_FILTER] |= ALLOW(PRIV_OPEN_PFOSFP);
 
        if (infile)
                cmdbuf = read_infile(infile);
@@ -293,6 +301,10 @@ priv_exec(int argc, char *argv[])
                        test_state(cmd, STATE_BPF);
                        impl_open_dump(sock, RFileName);
                        break;
+               case PRIV_OPEN_PFOSFP:
+                       test_state(cmd, STATE_FILTER);
+                       impl_open_pfosfp(sock);
+                       break;
                case PRIV_OPEN_OUTPUT:
                        test_state(cmd, STATE_RUN);
                        impl_open_output(sock, WFileName);
@@ -404,6 +416,24 @@ impl_open_dump(int fd, const char *RFile
 }
 
 static void
+impl_open_pfosfp(int fd)
+{
+       int file, err = 0;
+
+       logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_PFOSFP received");
+
+       file = open(PF_OSFP_FILE, O_RDONLY, 0);
+       err = errno;
+       if (file < 0)
+               logmsg(LOG_DEBUG, "[priv]: failed to open %s: %s",
+                   PF_OSFP_FILE, strerror(errno));
+       send_fd(fd, file);
+       must_write(fd, &err, sizeof(int));
+       if (file >= 0)
+               close(file);
+}
+
+static void
 impl_open_output(int fd, const char *WFileName)
 {
        int file, err;
@@ -806,6 +836,22 @@ priv_getline(char *line, size_t line_len
 
        /* read the line */
        return (read_string(priv_fd, line, line_len, __func__));
+}
+
+int
+priv_open_pfosfp(void)
+{
+       int fd, err = 0;
+       write_command(priv_fd, PRIV_OPEN_PFOSFP);
+
+       fd = receive_fd(priv_fd);
+       must_read(priv_fd, &err, sizeof(int));
+       if (fd < 0) {
+               warnc(err, "%s", PF_OSFP_FILE);
+               return (-1);
+       }
+
+       return (fd);
 }
 
 /* Read all data or return 1 for error. */
Index: privsep.h
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/privsep.h,v
retrieving revision 1.10
diff -u -p -u -r1.10 privsep.h
--- usr.sbin/tcpdump/privsep.h  8 Sep 2017 19:10:57 -0000       1.10
+++ usr.sbin/tcpdump/privsep.h  19 Sep 2017 17:07:37 -0000
@@ -27,6 +27,7 @@
 enum cmd_types {
        PRIV_OPEN_BPF,          /* open a bpf descriptor */
        PRIV_OPEN_DUMP,         /* open dump file for reading */
+       PRIV_OPEN_PFOSFP,       /* open pf.os(5) fingerprint db for reading */
        PRIV_OPEN_OUTPUT,       /* open output file */
        PRIV_SETFILTER,         /* set a bpf read filter */
        PRIV_GETHOSTBYADDR,     /* resolve numeric address into hostname */
@@ -81,6 +82,9 @@ void  priv_getlines(size_t);
 /* Retrieve a single line from a file, should be called repeatedly after
    calling priv_getlines() until it returns zero */
 size_t priv_getline(char *, size_t);
+
+/* Retrieve pf.os(5) fingerprints file descriptor */
+int    priv_open_pfosfp();
 
 /* Return the pcap statistics upon completion */
 int    priv_pcap_stats(struct pcap_stat *);
Index: tcpdump.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/tcpdump.c,v
retrieving revision 1.80
diff -u -p -u -r1.80 tcpdump.c
--- usr.sbin/tcpdump/tcpdump.c  8 Sep 2017 19:10:57 -0000       1.80
+++ usr.sbin/tcpdump/tcpdump.c  19 Sep 2017 17:07:37 -0000
@@ -461,6 +461,8 @@ main(int argc, char **argv)
                bpf_dump(fcode, dflag);
                exit(0);
        }
+       if (oflag)
+               oflag = init_pfosfp();
        init_addrtoname(localnet, netmask);
 
        if (WFileName) {
@@ -490,8 +492,6 @@ main(int argc, char **argv)
                (void)fflush(stderr);
        }
 
-       if (oflag)
-               oflag = init_pfosfp();
        if (tflag > 0)
                thiszone = gmt2local(0);
 

Reply via email to