I'm revisiting some old tcpdump diffs, now that mestre@ has added proper unveil(2) support! :-)
Refresher: https://marc.info/?l=openbsd-tech&m=150535073209723&w=2 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 (currently root) monitor process. This still works as well as it already has. :-) ( ... ) [tcp sum ok] (src OS: OpenBSD 6.1) 3311509932:3311509932(0) win 16384 <mss 1460,nop,nop,sackOK,nop,wscale 6,nop,nop,timestamp 3905153931 0> (DF) (ttl 64, id 41239, len 64) The only potential difference is that if /etc/pf.os is replaced at runtime, tcpdump won't reopen it. I don't think that's a problem.. ok? -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 7 Nov 2018 23:52:48 -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.49 diff -u -p -u -r1.49 privsep.c --- usr.sbin/tcpdump/privsep.c 28 Sep 2018 06:48:59 -0000 1.49 +++ usr.sbin/tcpdump/privsep.c 7 Nov 2018 23:52:48 -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 *); @@ -277,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); @@ -297,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); @@ -309,10 +317,6 @@ priv_exec(int argc, char *argv[]) test_state(cmd, STATE_RUN); impl_init_done(sock, &bpfd); - if (oflag) { - if (unveil("/etc/pf.os", "r") == -1) - err(1, "unveil"); - } if (unveil("/etc/ethers", "r") == -1) err(1, "unveil"); if (unveil("/etc/rpc", "r") == -1) @@ -416,6 +420,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; @@ -818,6 +840,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 7 Nov 2018 23:52:48 -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.87 diff -u -p -u -r1.87 tcpdump.c --- usr.sbin/tcpdump/tcpdump.c 6 Jul 2018 07:13:21 -0000 1.87 +++ usr.sbin/tcpdump/tcpdump.c 7 Nov 2018 23:52:48 -0000 @@ -471,6 +471,8 @@ main(int argc, char **argv) bpf_dump(fcode, dflag); exit(0); } + if (oflag) + oflag = init_pfosfp(); init_addrtoname(localnet, netmask); if (WFileName) { @@ -500,8 +502,6 @@ main(int argc, char **argv) (void)fflush(stderr); } - if (oflag) - oflag = init_pfosfp(); if (tflag > 0) thiszone = gmt2local(0);
