Commit 65d88d04 authored by Jason A. Donenfeld's avatar Jason A. Donenfeld Committed by David S. Miller

wireguard: selftests: import harness makefile for test suite

WireGuard has been using this on build.wireguard.com for the last
several years with considerable success. It allows for very quick and
iterative development cycles, and supports several platforms.

To run the test suite on your current platform in QEMU:

  $ make -C tools/testing/selftests/wireguard/qemu -j$(nproc)

To run it with KASAN and such turned on:

  $ DEBUG_KERNEL=yes make -C tools/testing/selftests/wireguard/qemu -j$(nproc)

To run it emulated for another platform in QEMU:

  $ ARCH=arm make -C tools/testing/selftests/wireguard/qemu -j$(nproc)

At the moment, we support aarch64_be, aarch64, arm, armeb, i686, m68k,
mips64, mips64el, mips, mipsel, powerpc64le, powerpc, and x86_64.

The system supports incremental rebuilding, so it should be very fast to
change a single file and then test it out and have immediate feedback.

This requires for the right toolchain and qemu to be installed prior.
I've had success with those from musl.cc.

This is tailored for WireGuard at the moment, though later projects
might generalize it for other network testing.
Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c5dea815
This diff is collapsed.
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyAMA0 wg.success=ttyAMA1"
CONFIG_FRAME_WARN=1280
CONFIG_CPU_BIG_ENDIAN=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyAMA0 wg.success=ttyAMA1"
CONFIG_FRAME_WARN=1280
CONFIG_MMU=y
CONFIG_ARCH_MULTI_V7=y
CONFIG_ARCH_VIRT=y
CONFIG_THUMB2_KERNEL=n
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyAMA0 wg.success=ttyAMA1"
CONFIG_FRAME_WARN=1024
CONFIG_MMU=y
CONFIG_ARCH_MULTI_V7=y
CONFIG_ARCH_VIRT=y
CONFIG_THUMB2_KERNEL=n
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyAMA0 wg.success=ttyAMA1"
CONFIG_CPU_BIG_ENDIAN=y
CONFIG_FRAME_WARN=1024
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1"
CONFIG_FRAME_WARN=1024
CONFIG_MMU=y
CONFIG_M68040=y
CONFIG_MAC=y
CONFIG_SERIAL_PMACZILOG=y
CONFIG_SERIAL_PMACZILOG_TTYS=y
CONFIG_SERIAL_PMACZILOG_CONSOLE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1"
CONFIG_FRAME_WARN=1024
CONFIG_CPU_MIPS32_R2=y
CONFIG_MIPS_MALTA=y
CONFIG_MIPS_CPS=y
CONFIG_MIPS_FP_SUPPORT=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1"
CONFIG_FRAME_WARN=1024
CONFIG_64BIT=y
CONFIG_CPU_MIPS64_R2=y
CONFIG_MIPS32_N32=y
CONFIG_CPU_HAS_MSA=y
CONFIG_MIPS_MALTA=y
CONFIG_MIPS_CPS=y
CONFIG_MIPS_FP_SUPPORT=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1"
CONFIG_FRAME_WARN=1280
CONFIG_64BIT=y
CONFIG_CPU_MIPS64_R2=y
CONFIG_MIPS32_N32=y
CONFIG_CPU_HAS_MSA=y
CONFIG_MIPS_MALTA=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_MIPS_CPS=y
CONFIG_MIPS_FP_SUPPORT=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1"
CONFIG_FRAME_WARN=1280
CONFIG_CPU_MIPS32_R2=y
CONFIG_MIPS_MALTA=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_MIPS_CPS=y
CONFIG_MIPS_FP_SUPPORT=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1"
CONFIG_FRAME_WARN=1024
CONFIG_PPC_QEMU_E500=y
CONFIG_FSL_SOC_BOOKE=y
CONFIG_PPC_85xx=y
CONFIG_PHYS_64BIT=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_MATH_EMULATION=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1"
CONFIG_FRAME_WARN=1024
CONFIG_PPC64=y
CONFIG_PPC_PSERIES=y
CONFIG_ALTIVEC=y
CONFIG_VSX=y
CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
CONFIG_PPC_RADIX_MMU=y
CONFIG_HVC_CONSOLE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=hvc0 wg.success=hvc1"
CONFIG_SECTION_MISMATCH_WARN_ONLY=y
CONFIG_FRAME_WARN=1280
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1"
CONFIG_FRAME_WARN=1280
CONFIG_LOCALVERSION="-debug"
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_POINTER=y
CONFIG_STACK_VALIDATION=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_PAGE_EXTENSION=y
CONFIG_PAGE_POISONING=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_FREE=y
CONFIG_DEBUG_OBJECTS_TIMERS=y
CONFIG_DEBUG_OBJECTS_WORK=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
CONFIG_SLUB_DEBUG_ON=y
CONFIG_DEBUG_VM=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_HAVE_ARCH_KMEMCHECK=y
CONFIG_HAVE_ARCH_KASAN=y
CONFIG_KASAN=y
CONFIG_KASAN_INLINE=y
CONFIG_UBSAN=y
CONFIG_UBSAN_SANITIZE_ALL=y
CONFIG_UBSAN_NO_ALIGNMENT=y
CONFIG_UBSAN_NULL=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=8192
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_SHIRQ=y
CONFIG_WQ_WATCHDOG=y
CONFIG_SCHED_DEBUG=y
CONFIG_SCHED_INFO=y
CONFIG_SCHEDSTATS=y
CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_DEBUG_TIMEKEEPING=y
CONFIG_TIMER_STATS=y
CONFIG_DEBUG_PREEMPT=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_PROVE_LOCKING=y
CONFIG_LOCKDEP=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_TRACE_IRQFLAGS=y
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_PI_LIST=y
CONFIG_PROVE_RCU=y
CONFIG_SPARSE_RCU_POINTER=y
CONFIG_RCU_CPU_STALL_TIMEOUT=21
CONFIG_RCU_TRACE=y
CONFIG_RCU_EQS_DEBUG=y
CONFIG_USER_STACKTRACE_SUPPORT=y
CONFIG_DEBUG_SG=y
CONFIG_DEBUG_NOTIFIERS=y
CONFIG_DOUBLEFAULT=y
CONFIG_X86_DEBUG_FPU=y
CONFIG_DEBUG_SECTION_MISMATCH=y
CONFIG_DEBUG_PAGEALLOC=y
CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*/
#define _GNU_SOURCE
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/io.h>
#include <sys/ioctl.h>
#include <sys/reboot.h>
#include <sys/utsname.h>
#include <sys/sendfile.h>
#include <linux/random.h>
#include <linux/version.h>
__attribute__((noreturn)) static void poweroff(void)
{
fflush(stdout);
fflush(stderr);
reboot(RB_AUTOBOOT);
sleep(30);
fprintf(stderr, "\x1b[37m\x1b[41m\x1b[1mFailed to power off!!!\x1b[0m\n");
exit(1);
}
static void panic(const char *what)
{
fprintf(stderr, "\n\n\x1b[37m\x1b[41m\x1b[1mSOMETHING WENT HORRIBLY WRONG\x1b[0m\n\n \x1b[31m\x1b[1m%s: %s\x1b[0m\n\n\x1b[37m\x1b[44m\x1b[1mPower off...\x1b[0m\n\n", what, strerror(errno));
poweroff();
}
#define pretty_message(msg) puts("\x1b[32m\x1b[1m" msg "\x1b[0m")
static void print_banner(void)
{
struct utsname utsname;
int len;
if (uname(&utsname) < 0)
panic("uname");
len = strlen(" WireGuard Test Suite on ") + strlen(utsname.sysname) + strlen(utsname.release) + strlen(utsname.machine);
printf("\x1b[45m\x1b[33m\x1b[1m%*.s\x1b[0m\n\x1b[45m\x1b[33m\x1b[1m WireGuard Test Suite on %s %s %s \x1b[0m\n\x1b[45m\x1b[33m\x1b[1m%*.s\x1b[0m\n\n", len, "", utsname.sysname, utsname.release, utsname.machine, len, "");
}
static void seed_rng(void)
{
int fd;
struct {
int entropy_count;
int buffer_size;
unsigned char buffer[256];
} entropy = {
.entropy_count = sizeof(entropy.buffer) * 8,
.buffer_size = sizeof(entropy.buffer),
.buffer = "Adding real entropy is not actually important for these tests. Don't try this at home, kids!"
};
if (mknod("/dev/urandom", S_IFCHR | 0644, makedev(1, 9)))
panic("mknod(/dev/urandom)");
fd = open("/dev/urandom", O_WRONLY);
if (fd < 0)
panic("open(urandom)");
for (int i = 0; i < 256; ++i) {
if (ioctl(fd, RNDADDENTROPY, &entropy) < 0)
panic("ioctl(urandom)");
}
close(fd);
}
static void mount_filesystems(void)
{
pretty_message("[+] Mounting filesystems...");
mkdir("/dev", 0755);
mkdir("/proc", 0755);
mkdir("/sys", 0755);
mkdir("/tmp", 0755);
mkdir("/run", 0755);
mkdir("/var", 0755);
if (mount("none", "/dev", "devtmpfs", 0, NULL))
panic("devtmpfs mount");
if (mount("none", "/proc", "proc", 0, NULL))
panic("procfs mount");
if (mount("none", "/sys", "sysfs", 0, NULL))
panic("sysfs mount");
if (mount("none", "/tmp", "tmpfs", 0, NULL))
panic("tmpfs mount");
if (mount("none", "/run", "tmpfs", 0, NULL))
panic("tmpfs mount");
if (mount("none", "/sys/kernel/debug", "debugfs", 0, NULL))
; /* Not a problem if it fails.*/
if (symlink("/run", "/var/run"))
panic("run symlink");
if (symlink("/proc/self/fd", "/dev/fd"))
panic("fd symlink");
}
static void enable_logging(void)
{
int fd;
pretty_message("[+] Enabling logging...");
fd = open("/proc/sys/kernel/printk", O_WRONLY);
if (fd >= 0) {
if (write(fd, "9\n", 2) != 2)
panic("write(printk)");
close(fd);
}
fd = open("/proc/sys/debug/exception-trace", O_WRONLY);
if (fd >= 0) {
if (write(fd, "1\n", 2) != 2)
panic("write(exception-trace)");
close(fd);
}
fd = open("/proc/sys/kernel/panic_on_warn", O_WRONLY);
if (fd >= 0) {
if (write(fd, "1\n", 2) != 2)
panic("write(panic_on_warn)");
close(fd);
}
}
static void kmod_selftests(void)
{
FILE *file;
char line[2048], *start, *pass;
bool success = true;
pretty_message("[+] Module self-tests:");
file = fopen("/proc/kmsg", "r");
if (!file)
panic("fopen(kmsg)");
if (fcntl(fileno(file), F_SETFL, O_NONBLOCK) < 0)
panic("fcntl(kmsg, nonblock)");
while (fgets(line, sizeof(line), file)) {
start = strstr(line, "wireguard: ");
if (!start)
continue;
start += 11;
*strchrnul(start, '\n') = '\0';
if (strstr(start, "www.wireguard.com"))
break;
pass = strstr(start, ": pass");
if (!pass || pass[6] != '\0') {
success = false;
printf(" \x1b[31m* %s\x1b[0m\n", start);
} else
printf(" \x1b[32m* %s\x1b[0m\n", start);
}
fclose(file);
if (!success) {
puts("\x1b[31m\x1b[1m[-] Tests failed! \u2639\x1b[0m");
poweroff();
}
}
static void launch_tests(void)
{
char cmdline[4096], *success_dev;
int status, fd;
pid_t pid;
pretty_message("[+] Launching tests...");
pid = fork();
if (pid == -1)
panic("fork");
else if (pid == 0) {
execl("/init.sh", "init", NULL);
panic("exec");
}
if (waitpid(pid, &status, 0) < 0)
panic("waitpid");
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
pretty_message("[+] Tests successful! :-)");
fd = open("/proc/cmdline", O_RDONLY);
if (fd < 0)
panic("open(/proc/cmdline)");
if (read(fd, cmdline, sizeof(cmdline) - 1) <= 0)
panic("read(/proc/cmdline)");
cmdline[sizeof(cmdline) - 1] = '\0';
for (success_dev = strtok(cmdline, " \n"); success_dev; success_dev = strtok(NULL, " \n")) {
if (strncmp(success_dev, "wg.success=", 11))
continue;
memcpy(success_dev + 11 - 5, "/dev/", 5);
success_dev += 11 - 5;
break;
}
if (!success_dev || !strlen(success_dev))
panic("Unable to find success device");
fd = open(success_dev, O_WRONLY);
if (fd < 0)
panic("open(success_dev)");
if (write(fd, "success\n", 8) != 8)
panic("write(success_dev)");
close(fd);
} else {
const char *why = "unknown cause";
int what = -1;
if (WIFEXITED(status)) {
why = "exit code";
what = WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) {
why = "signal";
what = WTERMSIG(status);
}
printf("\x1b[31m\x1b[1m[-] Tests failed with %s %d! \u2639\x1b[0m\n", why, what);
}
}
static void ensure_console(void)
{
for (unsigned int i = 0; i < 1000; ++i) {
int fd = open("/dev/console", O_RDWR);
if (fd < 0) {
usleep(50000);
continue;
}
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
close(fd);
if (write(1, "\0\0\0\0\n", 5) == 5)
return;
}
panic("Unable to open console device");
}
static void clear_leaks(void)
{
int fd;
fd = open("/sys/kernel/debug/kmemleak", O_WRONLY);
if (fd < 0)
return;
pretty_message("[+] Starting memory leak detection...");
write(fd, "clear\n", 5);
close(fd);
}
static void check_leaks(void)
{
int fd;
fd = open("/sys/kernel/debug/kmemleak", O_WRONLY);
if (fd < 0)
return;
pretty_message("[+] Scanning for memory leaks...");
sleep(2); /* Wait for any grace periods. */
write(fd, "scan\n", 5);
close(fd);
fd = open("/sys/kernel/debug/kmemleak", O_RDONLY);
if (fd < 0)
return;
if (sendfile(1, fd, NULL, 0x7ffff000) > 0)
panic("Memory leaks encountered");
close(fd);
}
int main(int argc, char *argv[])
{
seed_rng();
ensure_console();
print_banner();
mount_filesystems();
kmod_selftests();
enable_logging();
clear_leaks();
launch_tests();
check_leaks();
poweroff();
return 1;
}
CONFIG_LOCALVERSION=""
CONFIG_NET=y
CONFIG_NETDEVICES=y
CONFIG_NET_CORE=y
CONFIG_NET_IPIP=y
CONFIG_DUMMY=y
CONFIG_VETH=y
CONFIG_MULTIUSER=y
CONFIG_NAMESPACES=y
CONFIG_NET_NS=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IPV6=y
CONFIG_NETFILTER=y
CONFIG_NETFILTER_ADVANCED=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_NAT=y
CONFIG_NETFILTER_XTABLES=y
CONFIG_NETFILTER_XT_NAT=y
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_NF_NAT_IPV4=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_NAT=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_TTY=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_SCRIPT=y
CONFIG_VDSO=y
CONFIG_VIRTUALIZATION=y
CONFIG_HYPERVISOR_GUEST=y
CONFIG_PARAVIRT=y
CONFIG_KVM_GUEST=y
CONFIG_PARAVIRT_SPINLOCKS=y
CONFIG_PRINTK=y
CONFIG_KALLSYMS=y
CONFIG_BUG=y
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
CONFIG_EMBEDDED=n
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_SHMEM=y
CONFIG_SLUB=y
CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_SMP=y
CONFIG_SCHED_SMT=y
CONFIG_SCHED_MC=y
CONFIG_NUMA=y
CONFIG_PREEMPT=y
CONFIG_NO_HZ=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NO_HZ_FULL=n
CONFIG_HZ_PERIODIC=n
CONFIG_HIGH_RES_TIMERS=y
CONFIG_ARCH_RANDOM=y
CONFIG_FILE_LOCKING=y
CONFIG_POSIX_TIMERS=y
CONFIG_DEVTMPFS=y
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15
CONFIG_PRINTK_TIME=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_LEGACY_VSYSCALL_NONE=y
CONFIG_KERNEL_GZIP=y
CONFIG_PANIC_ON_OOPS=y
CONFIG_BUG_ON_DATA_CORRUPTION=y
CONFIG_LOCKUP_DETECTOR=y
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_HARDLOCKUP_DETECTOR=y
CONFIG_WQ_WATCHDOG=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
CONFIG_PANIC_TIMEOUT=-1
CONFIG_STACKTRACE=y
CONFIG_EARLY_PRINTK=y
CONFIG_GDB_SCRIPTS=y
CONFIG_WIREGUARD=y
CONFIG_WIREGUARD_DEBUG=y
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment