Tetragon, the BPF-based security monitoring tool, uses BPF to monitor different aspects of a running kernel and enforce user-specified policies. It sends its data to a user-space process, which forwards the data to a central monitoring service elsewhere in the network, however. This presents a point of vulnerability: if an attacker can kill Tetragon's user-space agent, it won't be able to properly report on the situation. Song Liu, Mahé Tardy, and Liam Wiseheart spoke about their work removing the need for the user-space agent at the 2026 Linux Storage, Filesystem, Memory-Management, and BPF Summit.

Wiseheart clarified that he works at Meta, not on Tetragon, but he has an interest in solving the same problem of allowing BPF programs to run entirely disconnected from any user-space components. Currently, Meta takes the approach of pinning programs at system boot time, which at least prevents the programs from being removed if the user-space components are killed, but doesn't completely avoid the problem.

The way Tetragon (presumably like Wiseheart's similar program) communicates with user space is via a ring buffer, Tardy explained. The user-space component is mostly responsible for reading messages from that ring buffer, sending them to a remote server, receiving replies, and then putting the replies back into the ring buffer. It would be a lot more efficient if the BPF program could simply talk to the remote server directly. BPF programs can already intercept incoming network packets; the missing part is the ability to send data directly from BPF.

In 2025, Tardy and company had presented a solution using splice(), but that solution was unpopular. At the time, Andrii Nakryiko thought that a synchronous option was probably a bad fit for BPF. The kernel developers at that session suggested using the netconsole code, which allows the kernel to send log messages that would ordinarily go to a serial port to a remote location instead.

"We tried that," Tardy said, and it seems to work. Netpoll, the kernel infrastructure behind netconsole, lets kernel code send packets from any context and bypasses the normal networking stack, which is handy. So, they wrote a kfunc and sent a patch set for it, with an updated version later in the year. To use it, a user-space loading program would pass network address information to the BPF program, which would call bpf_netpoll_create() to create a netpoll context. Then bpf_netpoll_send_udp() is used to send UDP packets containing arbitrary data.

Tardy then did a little demo. He booted a virtual machine, started a demo agent that installed a BPF program that sent occasional pings to the host machine, and showed those messages coming through on a separate terminal. Then he killed the user-space agent and showed that the pings kept arriving. The new packet-sending functions can be combined with the kernel's existing cryptography API to send encrypted packets, he added. Currently, his demo uses a simple symmetric key, but it's possible to use more complex schemes.

Even though the netpoll solution works, "we've had some feedback that UDP is evil," Liu said. For one thing, the packets sent by netpoll bypass the normal networking stack, which means that if a BPF program sends too much traffic, it could steal bandwidth from other processes with no real way to limit contention. One audience member suggested that it wasn't necessary to use netpoll's ability to send from any kernel context — the BPF interface could spawn a kernel thread and use that to send packets in the normal way, which would let the networking code apply all of the normal networking settings to the traffic.

As of ten hours before the talk, Liu said, they had experimented with a version that sends TCP traffic instead of UDP. The networking folks were more comfortable with that, but it prevents the kfuncs from being used in atomic contexts, much as the kernel-thread-based solution would. That prompted an extensive discussion about the merits of UDP versus TCP, although most of the assembled seemed to fall on the pro-UDP side. Alexei Starovoitov didn't see a reason to prefer TCP, especially given that netpoll already exists and is used in the kernel. John Fastabend thought that UDP was sufficient for Tetragon's use case. Wiseheart pointed out that it was harder for a broken security module hook or similar problem to interfere with netpoll-based logging, since netpoll bypasses the normal networking stack.

Starovoitov shared an example of that robustness in action: he had at one point come across a situation where a network-interface card (NIC) had partially broken, with no ability to receive packets, which messed up the whole networking stack. But the netpoll code still worked to send on that device. Another person objected that the only real problem with the netpoll-based solution was bandwidth management on the host, but that it was a serious problem. Netpoll only uses a single queue on the NIC, Starovoitov said, which he doubted was enough to cause problems. Liu asked Starovoitov for his help convincing the networking maintainers of this point of view, which he promised to provide.

Daniel Borkmann asked how many NIC drivers even supported netpoll, or whether it was a generic utility that worked on every driver. Starovoitov thought that around 90% of drivers did not support netpoll — either intentionally, or just because things were broken. Only the drivers regularly used at Meta definitely handled it correctly, he said.

Nobody seemed to disagree with this, which made it unclear whether netpoll really was the best approach to use. Unfortunately, at that point the session was out of time. Since the conference, Tardy and company have continued working on the problem, posting a new patch set on July 6 that allows BPF programs to create and use UDP kernel sockets, instead of using netpoll.


Index entries for this article
ConferenceStorage, Filesystem, Memory-Management and BPF Summit/2026