Files
freebsd/tests/sys/netlink/test_netlink_message_writer.py
T
R. Christian McDonald 5180fce1cf netlink: Make room for the unfinished message when growing the buffer
When a message outgrows the writer's buffer, _nlmsg_refill_buffer()
allocates a larger one and moves the unfinished message there.  The new
buffer was sized for the data about to be added alone, so with enough of
the message already written the caller wrote past its end and left it
with datalen > buflen.  A 20-byte message plus an attribute of 8176
bytes got a buffer of 8192 bytes for 8200 bytes of data, and reading it
panicked an INVARIANTS kernel in nl_soreceive().

Size the new buffer for both, and add a ktest for it.

Reviewed by:		glebius
Fixes:			7e5bf68495 ("netlink: add netlink support")
MFC after:		1 week
Sponsored by:		Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D60541
2026-10-11 19:58:48 -04:00

61 lines
1.8 KiB
Python

import mmap
import pytest
from atf_python.ktest import BaseKernelTest
from atf_python.sys.netlink.attrs import NlAttrU32
M_NOWAIT = 1
M_WAITOK = 2
NLMSG_SMALL = 128
NLMSG_LARGE = 2048
class TestNetlinkMessageWriter(BaseKernelTest):
KTEST_MODULE_NAME = "ktest_netlink_message_writer"
@pytest.mark.parametrize(
"malloc_flags",
[
pytest.param(M_NOWAIT, id="NOWAIT"),
pytest.param(M_WAITOK, id="WAITOK"),
],
)
@pytest.mark.parametrize(
"sz",
[
pytest.param([NLMSG_SMALL, NLMSG_SMALL], id="NLMSG_SMALL"),
pytest.param([NLMSG_LARGE, NLMSG_LARGE], id="NLMSG_LARGE"),
pytest.param([NLMSG_LARGE + 256, NLMSG_LARGE + 256], id="NLMSG_LARGE+256"),
],
)
def test_nlbuf_writer_allocation(self, sz, malloc_flags):
"""override to parametrize"""
test_meta = [
NlAttrU32(1, sz[0]), # size
NlAttrU32(2, sz[1]), # expected_avail
NlAttrU32(3, malloc_flags),
]
self.runtest(test_meta)
@pytest.mark.parametrize(
"sz",
[
# buffer size, completed message, unfinished message, attribute
pytest.param([NLMSG_SMALL, 0, 20, 112], id="small"),
pytest.param([NLMSG_SMALL, 0, 20, 8176], id="large_attr"),
pytest.param([NLMSG_LARGE, 0, 2000, 4092], id="large_msg"),
pytest.param([NLMSG_LARGE, 100, 1900, 196], id="after_completed"),
],
)
def test_nlbuf_writer_refill(self, sz):
"""override to parametrize"""
test_meta = [
NlAttrU32(1, sz[0]), # size
NlAttrU32(2, sz[1]), # completed
NlAttrU32(3, sz[2]), # unfinished
NlAttrU32(4, sz[3]), # attr_len
]
self.runtest(test_meta)