Page MenuHomeFreeBSD

netlink: return ENOBUFS on RX overflow
Needs ReviewPublic

Authored by zishun.yi.dev_gmail.com on Jun 24 2026, 6:59 AM.
Tags
None
Referenced Files
Unknown Object (File)
Wed, Jul 22, 1:36 PM
Unknown Object (File)
Tue, Jul 21, 8:51 PM
Unknown Object (File)
Tue, Jul 21, 2:30 PM
Unknown Object (File)
Wed, Jul 8, 11:30 PM
Unknown Object (File)
Wed, Jul 8, 12:53 AM
Unknown Object (File)
Tue, Jul 7, 4:50 PM
Unknown Object (File)
Mon, Jul 6, 12:16 AM
Unknown Object (File)
Mon, Jul 6, 12:13 AM

Details

Reviewers
obiwac
melifaro
glebius
Group Reviewers
network
Summary

In send() sync mode, as Linux does, if the recv buffer is full but the user
keeps sending, we record how many replies we dropped, and return ENOBUFS the
next time the user calls recv().

Doing this by checking the dropped bytes at the beginning of nl_soreceive(),
resetting them, and then returning immediately.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 74976
Build 71859: arc lint + arc unit

Event Timeline

could also be interesting to add a test to check whether data is copied into receive buffer or not and that ENOBUFS is returned correctly, but this can be done separately

sys/netlink/netlink_domain.c
858–861

I would rather commit this one before adding NLF_SND_SYNC, so if you can apply the suggested edit and move this down in the stack that'd be great

This revision is now accepted and ready to land.Jun 24 2026, 1:21 PM
This revision now requires review to proceed.Thu, Jun 25, 9:57 AM

Can you please elaborate what software expects this and what problems the patch tries to address?

Returning ENOBUFS on recv(2) when we actually have data that can be successfully given to the application doesn't look correct at all. I know that Linux likes to return error from one syscall as a return to an other syscall, this was "a feature" since Linux 2.2 and UDP socket. While netlink is originally Linux idea, but it still is a socket(2), and it should behave as a normal socket and recv(2) shall return error from a receive operation, not status of a past send(2). We may want to emulate this bug on sockets opened by processes with Linux ABI, but I definitely don't want to be the behavior of the native socket.

@obiwac please don't rush with pushing this change

Returning ENOBUFS on recv(2) when we actually have data that can be successfully given to the application doesn't look correct at all. I know that Linux likes to return error from one syscall as a return to an other syscall, this was "a feature" since Linux 2.2 and UDP socket. While netlink is originally Linux idea, but it still is a socket(2), and it should behave as a normal socket and recv(2) shall return error from a receive operation, not status of a past send(2). We may want to emulate this bug on sockets opened by processes with Linux ABI, but I definitely don't want to be the behavior of the native socket.

that makes sense. was mainly operating under the idea of keeping our netlink behaviour close to linux's. I will defer to your opinion though.

@obiwac please don't rush with pushing this change

no worries, i wasn't going to commit this before @melifaro had a chance to comment on this anyways :)

Can you please elaborate what software expects this and what problems the patch tries to address?

Linux actually has a specific netlink socket flag, NETLINK_NO_ENOBUFS, which suggests that a lot of Linux software depends on the default ENOBUFS behavior.
As obiwac@ mentioned, our initial thought was to align this behavior with Linux, especially in preparation for the synchronous Netlink patch I plan to introduce.

Returning ENOBUFS on recv(2) when we actually have data that can be successfully given to the application doesn't look correct at all. I know that Linux likes to return error from one syscall as a return to an other syscall, this was "a feature" since Linux 2.2 and UDP socket. While netlink is originally Linux idea, but it still is a socket(2), and it should behave as a normal socket and recv(2) shall return error from a receive operation, not status of a past send(2). We may want to emulate this bug on sockets opened by processes with Linux ABI, but I definitely don't want to be the behavior of the native socket.

I agree with you. I saw the Linux udp(7) manual and know BSD doesn't send asynchronous errors to recv(2).
So, maybe we should implement this in the Linux ABI and implement NETLINK_NO_ENOBUFS along the way. And keep NETLINK_NO_ENOBUFS's behavior as the default behavior in FreeBSD?

What are the actual applications that depend on that?

What are the actual applications that depend on that?

I find a few:

I also found that libnl doesn't depend on it; it depends on NLMSG_OVERRUN: https://github.com/thom311/libnl/blob/655a638d4e1f74be9256a3108ae2abb84827a9ce/lib/nl.c#L957
So maybe implementing the TODO for NLMSG_OVERRUN in FreeBSD would be a better approach. (but I know freebsd use snl(3))

Implement ENOBUFS and NETLINK_NO_ENOBUFS in the Linux ABI, and send
NLMSG_OVERRUN in the FreeBSD ABI.

aokblast added inline comments.
sys/netlink/netlink_domain.c
703

I am wondering if we should preserve the value here and let the next packet handle this while this packet has uio->uio_resid < sizeof(struct nlmsghdr)?

709

It might break 32bit build, uint64_t == llu

724

Result of uiomove should not be ignored

724

Should we just return after here?

sys/netlink/netlink_domain.c
724

If you mean returning on uiomove() failure, I agree.
If you mean returning after a successful NLMSG_OVERRUN copyout, I don't think that's necessary. we can keep filling the buffer and let user handle or ignore the overrun message.

Sorry for being slow. This review is on my TODO list.