From 7dfeb363c60759b7b003ad6825a9742cecd330ce Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Sun, 9 Mar 2025 19:56:40 +0000 Subject: [PATCH] BPF: Start with the EOF marker set This will allow us to abort any BPF read loop if it's reset. While here, delay restarting DHCP slightly to allow privsep builds to recover the same error. Fixes #481. --- src/bpf.c | 3 +++ src/dhcp.c | 8 +++++++- src/if-linux.c | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/bpf.c b/src/bpf.c index 47375a3d..7c521261 100644 --- a/src/bpf.c +++ b/src/bpf.c @@ -170,6 +170,7 @@ bpf_open(const struct interface *ifp, if (bpf == NULL) return NULL; bpf->bpf_ifp = ifp; + bpf->bpf_flags = BPF_EOF; /* /dev/bpf is a cloner on modern kernels */ bpf->bpf_fd = open("/dev/bpf", BPF_OPEN_FLAGS); @@ -218,10 +219,12 @@ bpf_open(const struct interface *ifp, /* Get the required BPF buffer length from the kernel. */ if (ioctl(bpf->bpf_fd, BIOCGBLEN, &ibuf_len) == -1) goto eexit; + bpf->bpf_size = (size_t)ibuf_len; bpf->bpf_buffer = malloc(bpf->bpf_size); if (bpf->bpf_buffer == NULL) goto eexit; + return bpf; eexit: diff --git a/src/dhcp.c b/src/dhcp.c index f6db1a7c..436399cb 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -2236,12 +2236,18 @@ dhcp_arp_defend_failed(struct arp_state *astate) { struct interface *ifp = astate->iface; struct dhcp_state *state = D_STATE(ifp); + unsigned int delay; if (!(ifp->options->options & (DHCPCD_INFORM | DHCPCD_STATIC))) dhcp_decline(ifp); dhcp_drop(ifp, "EXPIRED"); dhcp_unlink(ifp->ctx, state->leasefile); - dhcp_start1(ifp); + + // Delay restarting to give time for the BPF ARP process to exit + // as we may spawn a new one with a different filter fairly quickly + delay = MSEC_PER_SEC + + (arc4random_uniform(MSEC_PER_SEC * 2) - MSEC_PER_SEC); + eloop_timeout_add_msec(ifp->ctx->eloop, delay, dhcp_start1, ifp); } #endif diff --git a/src/if-linux.c b/src/if-linux.c index 2e519f2a..b9082505 100644 --- a/src/if-linux.c +++ b/src/if-linux.c @@ -1850,6 +1850,7 @@ bpf_open(const struct interface *ifp, if (bpf == NULL) return NULL; bpf->bpf_ifp = ifp; + bpf->bpf_flags = BPF_EOF; /* Allocate a suitably large buffer for a single packet. */ bpf->bpf_size = ETH_FRAME_LEN; -- 2.47.3