Skip to content

Add pcap_setwritefilter() and pcap_lockfilter()#1683

Open
rsmarples wants to merge 1 commit into
the-tcpdump-group:masterfrom
rsmarples:writefilter
Open

Add pcap_setwritefilter() and pcap_lockfilter()#1683
rsmarples wants to merge 1 commit into
the-tcpdump-group:masterfrom
rsmarples:writefilter

Conversation

@rsmarples
Copy link
Copy Markdown

When using libpcap in a public facing application, such as a DHCP client or ARP proxy, the application is vulnerable to malicious attacks.

If exploited, an attacker could use libpcap to write arbitary packets to the network.

To mitigate this potential exploit, applications can call pcap_setwritefilter() to ensure injected packets match how the application expects outbound packets to look, or just drop all outbound packets if it's not using libpcap to inject packets. Once set, the application should call pcap_lockfilter() to ensure the in kernel read and write filters cannot be changed or removed.

Note that this mechanism only works for kernel filtering.

When using libpcap in a public facing application, such as a
DHCP client or ARP proxy, the application is vulnerable to
malicious attacks.

If exploited, an attacker could use libpcap to write arbitary
packets to the network.

To mitigate this potential exploit, applications can call
pcap_setwritefilter() to ensure injected packets match how the
application expects outbound packets to look, or just drop all
outbound packets if it's not using libpcap to inject packets.
Once set, the application should call pcap_lockfilter() to ensure
the in kernel read and write filters cannot be changed or removed.

Note that this mechanism only works for kernel filtering.
rsmarples added a commit to NetworkConfiguration/dhcpcd that referenced this pull request May 18, 2026
@infrastation
Copy link
Copy Markdown
Member

The new pcap_setwritefilter() function would work with the BPF module only, and would be equivalent to an ioctl() call on the return value of the existing pcap_fileno(), correct?

@rsmarples
Copy link
Copy Markdown
Author

The new pcap_setwritefilter() function would work with the BPF module only, and would be equivalent to an ioctl() call on the return value of the existing pcap_fileno(), correct?

Correct.

@infrastation
Copy link
Copy Markdown
Member

Then this half of the proposed change is loosely related to #869.

@guyharris
Copy link
Copy Markdown
Member

Note that this mechanism only works for kernel filtering

...on systems that have BPF as the capturing mechanisms and that support whichever of BIOCSETWF and BIOCLOCK you are, in effect, using.

I.e., anybody who uses this who expects it to protect from that sort of attack on all platforms is making a mistake.

If this can be done on, for example, Linux, it would be useful to support it there, and a case could be made for it. It's good that they're declared with PCAP_WARN_UNUSED_RESULT, as programmers using it should check for an error and handle that appropriately, whether "giving up because it's not protected" or "warn that it's not protected" or....

@rsmarples
Copy link
Copy Markdown
Author

Note that this mechanism only works for kernel filtering

...on systems that have BPF as the capturing mechanisms and that support whichever of BIOCSETWF and BIOCLOCK you are, in effect, using.

I.e., anybody who uses this who expects it to protect from that sort of attack on all platforms is making a mistake.

Agreed.

If this can be done on, for example, Linux, it would be useful to support it there, and a case could be made for it. It's good that they're declared with PCAP_WARN_UNUSED_RESULT, as programmers using it should check for an error and handle that appropriately, whether "giving up because it's not protected" or "warn that it's not protected" or....

In the absence of the same ioctl being added to Linux (and it should be fairly easy - it didn't take me that long to add it to NetBSD many years ago), what do you feel a good option is to move forwards for people who wish to use libpcap in a public facing application?

  • Accept the limitation of it being BPF only for the time being
  • Document the potential vulnerability and workaround for supported BSD systems in pcap_setfilter(3)
  • Document that libpcap shouldn't be used in a public facing application and explain why
  • Pretend it doesn't exist and do nothing

So basically I've been given a sequence of patches to add GNU/Hurd support to my DHCP client and one of them was for using libpcap as there isn't a BSD BPF interface. As I can't get GNU/Hurd installed as a VM to any of my machines I've just been testing on my BSD systems and I was toying with the idea of just using libpcap, came across this limitation and here we are.

@infrastation
Copy link
Copy Markdown
Member

infrastation commented May 18, 2026

GNU/Hurd runs as a VM rather easy. The images are here, amd64 tends to be broken, but i386 works well. Snapshot 20250807 definitely works, and I've seen reports of other people using a more recent snapshot (there are two others).

Regarding the proposed functions, this is an interesting idea, but it needs a bit more thought before setting it in stone.

@guyharris
Copy link
Copy Markdown
Member

So basically I've been given a sequence of patches to add GNU/Hurd support to my DHCP client and one of them was for using libpcap as there isn't a BSD BPF interface. As I can't get GNU/Hurd installed as a VM to any of my machines I've just been testing on my BSD systems and I was toying with the idea of just using libpcap, came across this limitation and here we are.

Perhaps the answer is "have a separate library for link-layer network access, separate from the library for passive link-layer packet capture and packet injection for testing purposes". That library might either 1) use a different mechanism from the one used for packet capture, if that other mechanism is better suited to that purpose or 2) use the same mechanism but in a different fashion better suited to that purpose. For an example of case 2, packet capture involves binding a Linux PF_PACKET socket to the ETH_P_ALL "protocol", i.e. saying "show me all packets", but implementing some particular link-layer protocol might involve binding it to a particular EtherType value.

Perhaps GNU Hurd has another mechanism that would work better for a DHCP client than the mechanism currently used by libpcap? (Perhaps GNU Hurd should have another mechanism that would work better for a packets sniffer than the mechanism currently used by libpcap, but that's another matter. :-))

The notes I have on the "separate library for link-layer network access" are:

Linux:
PF_PACKET sockets, you can bind to a particular Ethertype,
although looking for a given DSAP or for a given SNAP
OUI/protocol is harder.

FreeBSD:
netgraph?

Other BSD:
BPF? Any alternatives?

DLPI:
don't go SAP-promiscuous?

macOS:
PF_NDRV sockets

Windows:
something similar to NPF, but can you bind to a particular
Ethertype/whatever in NDIS?

The idea I had was a sockets-like API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants