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