Date: Wed, 29 Apr 2026 14:48:55 +0000 From: Mark Johnston <markj@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Cc: Mariusz Zaborski <oshogbo@FreeBSD.org> Subject: git: 07296250c728 - stable/14 - libnv: add tests to verify potential overflow issues Message-ID: <69f21a57.3d58c.4e8f8088@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch stable/14 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=07296250c728644cc071fe89344ec9f0705da014 commit 07296250c728644cc071fe89344ec9f0705da014 Author: Mariusz Zaborski <oshogbo@FreeBSD.org> AuthorDate: 2024-08-29 13:46:01 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-04-29 14:45:05 +0000 libnv: add tests to verify potential overflow issues Differential Revision: https://reviews.freebsd.org/D46131 (cherry picked from commit 241a7ddd7112982ed41ccdd047c1dad59ee0256e) --- lib/libnv/tests/Makefile | 9 ++ lib/libnv/tests/nvlist_send_recv_test.c | 193 ++++++++++++++++++++++++++++++++ sys/contrib/libnv/nv_impl.h | 8 ++ sys/contrib/libnv/nvlist.c | 7 -- 4 files changed, 210 insertions(+), 7 deletions(-) diff --git a/lib/libnv/tests/Makefile b/lib/libnv/tests/Makefile index fc377e38ce83..aea416539c4a 100644 --- a/lib/libnv/tests/Makefile +++ b/lib/libnv/tests/Makefile @@ -1,7 +1,16 @@ +.include <src.opts.mk> ATF_TESTS_C= \ nvlist_send_recv_test +.PATH: ${SRCTOP}/lib/libnv +SRCS.nvlist_send_recv_test= msgio.c nvlist_send_recv_test.c +CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/sys/contrib/libnv +CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/lib/libnv +.if ${MK_ASAN} != "yes" +CFLAGS.nvlist_send_recv_test+=-DNO_ASAN +.endif + ATF_TESTS_CXX= \ cnv_tests \ dnv_tests \ diff --git a/lib/libnv/tests/nvlist_send_recv_test.c b/lib/libnv/tests/nvlist_send_recv_test.c index 5d4f392ed49c..cd97ccb6b9b9 100644 --- a/lib/libnv/tests/nvlist_send_recv_test.c +++ b/lib/libnv/tests/nvlist_send_recv_test.c @@ -44,6 +44,9 @@ #include <atf-c.h> +#include <nv_impl.h> +#include <msgio.h> + #define ALPHABET "abcdefghijklmnopqrstuvwxyz" #define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) @@ -543,6 +546,192 @@ ATF_TC_BODY(nvlist_send_recv__send_closed_fd__stream, tc) nvlist_send_recv__send_closed_fd(SOCK_STREAM); } +ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_header_size); +ATF_TC_BODY(nvlist_send_recv__overflow_header_size, tc) +{ + nvlist_t *nvl; + void *packed; + size_t packed_size; + struct nvlist_header *header; + int fd, socks[2], status; + pid_t pid; + +#ifdef NO_ASAN + atf_tc_skip("This test requires ASAN"); +#endif + + ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); + + pid = fork(); + ATF_REQUIRE(pid >= 0); + + if (pid == 0) { + /* Child. */ + fd = socks[0]; + close(socks[1]); + + nvl = nvlist_create(0); + ATF_REQUIRE(nvl != NULL); + ATF_REQUIRE(nvlist_empty(nvl)); + + packed = nvlist_pack(nvl, &packed_size); + ATF_REQUIRE(packed != NULL); + ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); + + header = (struct nvlist_header *)packed; + header->nvlh_size = SIZE_MAX - sizeof(struct nvlist_header) + 2; + + ATF_REQUIRE_EQ(write(fd, packed, packed_size), + (ssize_t)sizeof(struct nvlist_header)); + + nvlist_destroy(nvl); + free(packed); + + exit(0); + } else { + /* Parent */ + fd = socks[1]; + close(socks[0]); + + errno = 0; + nvl = nvlist_recv(fd, 0); + ATF_REQUIRE(nvl == NULL); + + /* + * Make sure it has failed on EINVAL, and not on + * errors returned by malloc or recv. + */ + ATF_REQUIRE(errno == EINVAL); + + ATF_REQUIRE(waitpid(pid, &status, 0) == pid); + ATF_REQUIRE(status == 0); + close(fd); + } +} + +ATF_TC_WITHOUT_HEAD(nvlist_send_recv__invalid_fd_size); +ATF_TC_BODY(nvlist_send_recv__invalid_fd_size, tc) +{ + nvlist_t *nvl; + void *packed; + size_t packed_size; + struct nvlist_header *header; + int fd, socks[2], status; + pid_t pid; + + ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); + + pid = fork(); + ATF_REQUIRE(pid >= 0); + + if (pid == 0) { + /* Child. */ + fd = socks[0]; + close(socks[1]); + + nvl = nvlist_create(0); + ATF_REQUIRE(nvl != NULL); + ATF_REQUIRE(nvlist_empty(nvl)); + + nvlist_add_string(nvl, "nvl/string", "test"); + ATF_REQUIRE_EQ(nvlist_error(nvl), 0); + + packed = nvlist_pack(nvl, &packed_size); + ATF_REQUIRE(packed != NULL); + ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); + + header = (struct nvlist_header *)packed; + header->nvlh_descriptors = 0x20; + + ATF_REQUIRE_EQ(write(fd, packed, packed_size), + (ssize_t)packed_size); + + nvlist_destroy(nvl); + free(packed); + + exit(0); + } else { + /* Parent */ + fd = socks[1]; + close(socks[0]); + + nvl = nvlist_recv(fd, 0); + ATF_REQUIRE(nvl == NULL); + + ATF_REQUIRE(waitpid(pid, &status, 0) == pid); + ATF_REQUIRE(status == 0); + } + + close(fd); +} + +ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_fd_size); +ATF_TC_BODY(nvlist_send_recv__overflow_fd_size, tc) +{ + nvlist_t *nvl; + void *packed; + size_t packed_size; + struct nvlist_header *header; + int fd, socks[2], fds[1], status; + pid_t pid; + + ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); + + pid = fork(); + ATF_REQUIRE(pid >= 0); + + if (pid == 0) { + /* Child. */ + fd = socks[0]; + close(socks[1]); + + nvl = nvlist_create(0); + ATF_REQUIRE(nvl != NULL); + ATF_REQUIRE(nvlist_empty(nvl)); + + nvlist_add_string(nvl, "nvl/string", "test"); + ATF_REQUIRE_EQ(nvlist_error(nvl), 0); + + packed = nvlist_pack(nvl, &packed_size); + ATF_REQUIRE(packed != NULL); + ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); + + header = (struct nvlist_header *)packed; + header->nvlh_descriptors = 0x4000000000000002; + + ATF_REQUIRE_EQ(write(fd, packed, packed_size), + (ssize_t)packed_size); + + fds[0] = dup(STDERR_FILENO); + ATF_REQUIRE(fds[0] >= 0); + ATF_REQUIRE_EQ(fd_send(fd, fds, 1), 0); + + nvlist_destroy(nvl); + free(packed); + + close(fds[0]); + close(fd); + + exit(0); + } else { + /* Parent */ + fd = socks[1]; + close(socks[0]); + + nvl = nvlist_recv(fd, 0); + ATF_REQUIRE(nvl == NULL); + + /* Make sure that fd was not parsed by nvlist */ + ATF_REQUIRE(fd_recv(fd, fds, 1) == 0); + + ATF_REQUIRE(waitpid(pid, &status, 0) == pid); + ATF_REQUIRE(status == 0); + + close(fds[0]); + close(fd); + } +} + ATF_TP_ADD_TCS(tp) { @@ -553,5 +742,9 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__dgram); ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__stream); + ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_header_size); + ATF_TP_ADD_TC(tp, nvlist_send_recv__invalid_fd_size); + ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_fd_size); + return (atf_no_error()); } diff --git a/sys/contrib/libnv/nv_impl.h b/sys/contrib/libnv/nv_impl.h index e9cd3ffabc3f..4ac57fc7b497 100644 --- a/sys/contrib/libnv/nv_impl.h +++ b/sys/contrib/libnv/nv_impl.h @@ -42,6 +42,14 @@ struct nvpair; typedef struct nvpair nvpair_t; #endif +struct nvlist_header { + uint8_t nvlh_magic; + uint8_t nvlh_version; + uint8_t nvlh_flags; + uint64_t nvlh_descriptors; + uint64_t nvlh_size; +} __packed; + #define NV_TYPE_NVLIST_ARRAY_NEXT 254 #define NV_TYPE_NVLIST_UP 255 diff --git a/sys/contrib/libnv/nvlist.c b/sys/contrib/libnv/nvlist.c index 058ec032d3a3..279f31e3a7cc 100644 --- a/sys/contrib/libnv/nvlist.c +++ b/sys/contrib/libnv/nvlist.c @@ -118,13 +118,6 @@ MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist"); #define NVLIST_HEADER_MAGIC 0x6c #define NVLIST_HEADER_VERSION 0x00 -struct nvlist_header { - uint8_t nvlh_magic; - uint8_t nvlh_version; - uint8_t nvlh_flags; - uint64_t nvlh_descriptors; - uint64_t nvlh_size; -} __packed; nvlist_t * nvlist_create(int flags)home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69f21a57.3d58c.4e8f8088>
