diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile index fe23803c2267..dbf88dd89a9a 100644 --- a/tests/sys/kern/Makefile +++ b/tests/sys/kern/Makefile @@ -1,94 +1,95 @@ # $FreeBSD$ .include PACKAGE= tests TESTSRC= ${SRCTOP}/contrib/netbsd-tests/kernel .PATH: ${SRCTOP}/sys/kern TESTSDIR= ${TESTSBASE}/sys/kern ATF_TESTS_C+= basic_signal #ATF_TESTS_C+= kcov ATF_TESTS_C+= kern_copyin ATF_TESTS_C+= kern_descrip_test ATF_TESTS_C+= fdgrowtable_test ATF_TESTS_C+= kill_zombie .if ${MK_OPENSSL} != "no" ATF_TESTS_C+= ktls_test .endif +ATF_TESTS_C+= module_test ATF_TESTS_C+= ptrace_test TEST_METADATA.ptrace_test+= timeout="15" ATF_TESTS_C+= reaper ATF_TESTS_C+= sigaltstack PLAIN_TESTS_C+= subr_unit_test ATF_TESTS_C+= sysctl_kern_proc ATF_TESTS_C+= sys_getrandom ATF_TESTS_C+= unix_passfd_test ATF_TESTS_C+= unix_seqpacket_test TEST_METADATA.unix_seqpacket_test+= timeout="15" ATF_TESTS_C+= unix_socketpair_test ATF_TESTS_C+= waitpid_nohang ATF_TESTS_C+= pdeathsig ATF_TESTS_SH+= coredump_phnum_test ATF_TESTS_SH+= sonewconn_overflow TEST_METADATA.sonewconn_overflow+= required_programs="python" TEST_METADATA.sonewconn_overflow+= required_user="root" ATF_TESTS_SH+= sendfile_test ${PACKAGE}FILES+= sonewconn_overflow.py ${PACKAGE}FILESMODE_sonewconn_overflow.py=0555 BINDIR= ${TESTSDIR} PROGS+= coredump_phnum_helper PROGS+= pdeathsig_helper PROGS+= sendfile_helper CFLAGS.sys_getrandom+= -I${SRCTOP}/sys/contrib/zstd/lib LIBADD.sys_getrandom+= zstd LIBADD.sys_getrandom+= c LIBADD.sys_getrandom+= pthread LIBADD.ptrace_test+= pthread LIBADD.unix_seqpacket_test+= pthread LIBADD.kcov+= pthread LIBADD.ktls_test+= crypto LIBADD.sendfile_helper+= pthread LIBADD.fdgrowtable_test+= util pthread kvm procstat NETBSD_ATF_TESTS_C+= lockf_test NETBSD_ATF_TESTS_C+= mqueue_test NETBSD_ATF_TESTS_C+= sysv_test CFLAGS.mqueue_test+= -I${SRCTOP}/tests LIBADD.mqueue_test+= rt ATF_TESTS_C+= libkern_crc32 SRCS.libkern_crc32+= libkern_crc32.c .PATH: ${SRCTOP}/sys/libkern SRCS.libkern_crc32+= gsb_crc32.c CFLAGS.libkern_crc32+= -DTESTING .if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" .PATH: ${SRCTOP}/sys/libkern/x86 SRCS.libkern_crc32+= crc32_sse42.c .elif ${MACHINE_CPUARCH} == "aarch64" .PATH: ${SRCTOP}/sys/libkern/arm64 SRCS.libkern_crc32+= crc32c_armv8.S .endif # subr_unit.c contains functions whose prototypes lie in headers that cannot be # included in userland. But as far as subr_unit_test goes, they're effectively # static. So it's ok to disable -Wmissing-prototypes for this program. CFLAGS.subr_unit.c+= -Wno-missing-prototypes SRCS.subr_unit_test+= subr_unit.c WARNS?= 3 TESTS_SUBDIRS+= acct TESTS_SUBDIRS+= execve TESTS_SUBDIRS+= pipe .include .include diff --git a/tests/sys/kern/module_test.c b/tests/sys/kern/module_test.c new file mode 100644 index 000000000000..eaebf7196523 --- /dev/null +++ b/tests/sys/kern/module_test.c @@ -0,0 +1,197 @@ +/*- + * Copyright (c) 2022 University of Cambridge + * + * This software was developed by Ararat River Consulting, LLC under + * sponsorship from the University of Cambridge Computer Laboratory + * (Department of Computer Science and Technology) and Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +ATF_TC_WITHOUT_HEAD(modfind); +ATF_TC_BODY(modfind, tc) +{ + int modid; + + /* This module is present in sys/kern/subr_bus.c. */ + modid = modfind("rootbus"); + ATF_REQUIRE(modid > 0); + + modid = modfind("nonexistent_module"); + ATF_REQUIRE(modid == -1); + ATF_REQUIRE(errno = ENOENT); +} + +ATF_TC_WITHOUT_HEAD(modnext); +ATF_TC_BODY(modnext, tc) +{ + int modid; + + /* This assumes -1 is never used as a valid module id. */ + modid = modnext(-1); + ATF_REQUIRE(modid == -1); + ATF_REQUIRE(errno = ENOENT); + + modid = modnext(0); + ATF_REQUIRE(modid > 0); + + for (;;) { + modid = modnext(modid); + ATF_REQUIRE(modid >= 0); + if (modid == 0) + break; + } +} + +ATF_TC_WITHOUT_HEAD(modfnext); +ATF_TC_BODY(modfnext, tc) +{ + int modid; + + /* This assumes -1 is never used as a valid module id. */ + modid = modfnext(-1); + ATF_REQUIRE(modid == -1); + ATF_REQUIRE(errno = ENOENT); + + modid = modfnext(0); + ATF_REQUIRE(modid == -1); + ATF_REQUIRE(errno = ENOENT); + + modid = modnext(0); + ATF_REQUIRE(modid > 0); + + for (;;) { + modid = modfnext(modid); + ATF_REQUIRE(modid >= 0); + if (modid == 0) + break; + } +} + +ATF_TC_WITHOUT_HEAD(modstat); +ATF_TC_BODY(modstat, tc) +{ + struct module_stat ms; + int modid; + + ms.version = sizeof(ms); + ATF_REQUIRE(modstat(0, &ms) == -1); + ATF_REQUIRE(errno == ENOENT); + + modid = modnext(0); + ATF_REQUIRE(modid > 0); + + ATF_REQUIRE(modstat(modid, NULL) == -1); + ATF_REQUIRE(errno == EFAULT); + + ms.version = 0; + ATF_REQUIRE(modstat(modid, &ms) == -1); + ATF_REQUIRE(errno == EINVAL); + + ms.version = sizeof(ms); + ATF_REQUIRE(modstat(modid, &ms) == 0); + ATF_REQUIRE(ms.id == modid); + if (strnlen(ms.name, sizeof(ms.name)) < sizeof(ms.name)) + ATF_REQUIRE(modfind(ms.name) == modid); +} + +ATF_TC_WITHOUT_HEAD(modstat_v1); +ATF_TC_BODY(modstat_v1, tc) +{ + struct module_stat_v1 { + int version; + char name[32]; + int refs; + int id; + } ms; + int modid; + + ms.version = sizeof(ms); + ATF_REQUIRE(modstat(0, (struct module_stat *)&ms) == -1); + ATF_REQUIRE(errno == ENOENT); + + modid = modnext(0); + ATF_REQUIRE(modid > 0); + + ATF_REQUIRE(modstat(modid, NULL) == -1); + ATF_REQUIRE(errno == EFAULT); + + ms.version = 0; + ATF_REQUIRE(modstat(modid, (struct module_stat *)&ms) == -1); + ATF_REQUIRE(errno == EINVAL); + + ms.version = sizeof(ms); + ATF_REQUIRE(modstat(modid, (struct module_stat *)&ms) == 0); + ATF_REQUIRE(ms.id == modid); + if (strnlen(ms.name, sizeof(ms.name)) < sizeof(ms.name)) + ATF_REQUIRE(modfind(ms.name) == modid); +} + +ATF_TC_WITHOUT_HEAD(modstat_v2); +ATF_TC_BODY(modstat_v2, tc) +{ + struct module_stat_v2 { + int version; + char name[32]; + int refs; + int id; + modspecific_t data; + } ms; + int modid; + + ms.version = sizeof(ms); + ATF_REQUIRE(modstat(0, (struct module_stat *)&ms) == -1); + ATF_REQUIRE(errno == ENOENT); + + modid = modnext(0); + ATF_REQUIRE(modid > 0); + + ATF_REQUIRE(modstat(modid, NULL) == -1); + ATF_REQUIRE(errno == EFAULT); + + ms.version = 0; + ATF_REQUIRE(modstat(modid, (struct module_stat *)&ms) == -1); + ATF_REQUIRE(errno == EINVAL); + + ms.version = sizeof(ms); + ATF_REQUIRE(modstat(modid, (struct module_stat *)&ms) == 0); + ATF_REQUIRE(ms.id == modid); + if (strnlen(ms.name, sizeof(ms.name)) < sizeof(ms.name)) + ATF_REQUIRE(modfind(ms.name) == modid); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, modfind); + ATF_TP_ADD_TC(tp, modnext); + ATF_TP_ADD_TC(tp, modfnext); + ATF_TP_ADD_TC(tp, modstat); + ATF_TP_ADD_TC(tp, modstat_v1); + ATF_TP_ADD_TC(tp, modstat_v2); + + return (atf_no_error()); +}