From c3ad02a211a283e1497e57de0abc8089496adcb2 Mon Sep 17 00:00:00 2001 From: Prashant Kumar Singh Date: Mon, 26 Oct 2026 09:44:45 -0700 Subject: [PATCH] lib: cgen: detach the old Netfilter links on chain update _bf_link_update_nf() attaches the new program at the chain's other priority, then closes the old links. bf_cgen_update() unpinned them just before, so closing them only drops a reference: they stay attached until bpffs releases the pinned inode. Until then the old program keeps filtering, so a rule the update removed still applies, and its priority is still in use, so another update right after fails with -EBUSY. Detach the old links before closing them, as bf_handle_detach() does. 414b9b2 did this for the previous Netfilter update code; 2b1e12d dropped it when the links moved to bf_link. --- src/libbpfilter/cgen/prog/link.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libbpfilter/cgen/prog/link.c b/src/libbpfilter/cgen/prog/link.c index 1bbd2389..79c8d4cc 100644 --- a/src/libbpfilter/cgen/prog/link.c +++ b/src/libbpfilter/cgen/prog/link.c @@ -264,8 +264,14 @@ static int _bf_link_update_nf(struct bf_link *link, int prog_fd) return bf_err_r(r, "failed to create nf_inet6 BPF link"); new_inet6_fd = r; - // Detach old links - safe now that new ones are active + /* Detach old links - safe now that new ones are active. They were + * unpinned, so closing them only drops a reference: they would stay + * attached until bpffs releases the pinned inode, the old program would + * keep filtering, and its priority would stay busy. */ + (void)bf_bpf_link_detach(link->fd); closep(&link->fd); + if (link->fd_extra >= 0) + (void)bf_bpf_link_detach(link->fd_extra); closep(&link->fd_extra); // Update link with new file descriptors