mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-21 07:15:49 +00:00
libnv: add tests to verify potential overflow issues
Differential Revision: https://reviews.freebsd.org/D46131
This commit is contained in:
parent
2981431e04
commit
241a7ddd71
@ -1,6 +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 \
|
||||
|
@ -43,6 +43,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)
|
||||
|
||||
@ -542,6 +545,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)
|
||||
{
|
||||
|
||||
@ -552,5 +741,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());
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user