Contributed by Peter N. M. Hansteen on from the BPF my daemons, Puffy! dept.
bpf(4)
interface to filter on the sockets they handle?
In a recent
message
to tech@ titled
bpf filtering on arbitrary sockets,
Damien Miller (djm@) presents a preliminary patch and explains,
List: openbsd-tech Subject: bpf filtering on arbitrary sockets From: Damien Miller <djm () mindrot ! org> Date: 2025-10-30 5:03:00 Hi, This is an idea that came up while talking with dlg@ about network daemons. Quite a few programs and daemons use SOCK_RAW to send link-level packets after pledge(). E.g. usr.sbin/relayd/check_icmp.c wants to send ICMP packets. The problem with this is that, if they get compromised, they still hold a very powerful socket that can send pretty much arbitrary packets. If one of these programs gets compromised then the attacker can pretty easily pivot through the existing raw socket.
What if we allowed attaching a bpf instances to sockets? On the receive side, these could be used to limit the types of messages received. Similarly, on the send side, they could restrict the ability of the socket to send arbitrary messages. E.g. for something like ping(1), a bpf program like: { 0x28, 0, 0, 0x0000000c }, { 0x15, 0, 7, 0x00000800 }, { 0x30, 0, 0, 0x00000017 }, { 0x15, 0, 5, 0x00000001 }, { 0x20, 0, 0, 0x0000001a }, { 0x15, 2, 0, src_addr }, { 0x20, 0, 0, 0x0000001e }, { 0x15, 0, 1, dst_addr }, { 0x6, 0, 0, 0x00000074 }, { 0x6, 0, 0, 0x00000000 }, could be used on the send side to drastically limit the power of the raw socket. These programs are trivial to write using `tcpdump -dd`; with a small tweak to tcpdump it might be possible to generate them from a Makefile rule. Practically, this would mean a few new setsockopt()s: 1. Attach a bpf program to a socket that filter received packets 2. Attach a bpf program to a socket that filters sent packets 3. An equivalent to BIOCLOCK to lock the bpf filters for a socket Programs would set up their SOCK_RAW sockets as usual, then attach the filters, then lock the filters then pledge. Here's what this looks like for the output side. It's pretty simple (too simple?) - there's a SOL_SOCKET SO_SEND_BPF setsockopt that loads a bpf_program to a socket fd. Packets that fail to match the filter are denied with EPERM. Note that the filter is applied to just the data that is passed to send(), sendto(), etc and not any protocol-level headers. AFAIK it can work with any datagram socket type in addition to SOCK_RAW, so could for example be used to limit the structure of USP messages, etc in addition to low-level SOCK_RAW control. There's also a SO_BPF_LOCK setsockopt that locks the program as you'd expect. What do you think? What would be a good daemon to try this against? I was thinking dhcpleased but that seems to use bpf for most of its sending, though that should IMO be converted to AF_FRAME now that we have it. -d Index: kern/uipc_socket.c =================================================================== […]
with the patch (as always, against -current) that contains the proposed code changes in the rest of the message.
The discussion is ongoing, expect to see further development and surgery on one or more daemons in the near future.
