Merge tag 'noinstr-x86-kvm-2020-05-16' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into HEAD

This commit is contained in:
Paolo Bonzini
2020-05-20 03:40:09 -04:00
868 changed files with 8787 additions and 4525 deletions
@@ -5,7 +5,8 @@
static void test_fexit_bpf2bpf_common(const char *obj_file,
const char *target_obj_file,
int prog_cnt,
const char **prog_name)
const char **prog_name,
bool run_prog)
{
struct bpf_object *obj = NULL, *pkt_obj;
int err, pkt_fd, i;
@@ -18,7 +19,8 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
err = bpf_prog_load(target_obj_file, BPF_PROG_TYPE_UNSPEC,
&pkt_obj, &pkt_fd);
if (CHECK(err, "prog_load sched cls", "err %d errno %d\n", err, errno))
if (CHECK(err, "tgt_prog_load", "file %s err %d errno %d\n",
target_obj_file, err, errno))
return;
DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,
.attach_prog_fd = pkt_fd,
@@ -33,7 +35,7 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
obj = bpf_object__open_file(obj_file, &opts);
if (CHECK(IS_ERR_OR_NULL(obj), "obj_open",
"failed to open fexit_bpf2bpf: %ld\n",
"failed to open %s: %ld\n", obj_file,
PTR_ERR(obj)))
goto close_prog;
@@ -49,6 +51,10 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
if (CHECK(IS_ERR(link[i]), "attach_trace", "failed to link\n"))
goto close_prog;
}
if (!run_prog)
goto close_prog;
data_map = bpf_object__find_map_by_name(obj, "fexit_bp.bss");
if (CHECK(!data_map, "find_data_map", "data map not found\n"))
goto close_prog;
@@ -89,7 +95,7 @@ static void test_target_no_callees(void)
test_fexit_bpf2bpf_common("./fexit_bpf2bpf_simple.o",
"./test_pkt_md_access.o",
ARRAY_SIZE(prog_name),
prog_name);
prog_name, true);
}
static void test_target_yes_callees(void)
@@ -103,7 +109,7 @@ static void test_target_yes_callees(void)
test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o",
"./test_pkt_access.o",
ARRAY_SIZE(prog_name),
prog_name);
prog_name, true);
}
static void test_func_replace(void)
@@ -120,7 +126,18 @@ static void test_func_replace(void)
test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o",
"./test_pkt_access.o",
ARRAY_SIZE(prog_name),
prog_name);
prog_name, true);
}
static void test_func_replace_verify(void)
{
const char *prog_name[] = {
"freplace/do_bind",
};
test_fexit_bpf2bpf_common("./freplace_connect4.o",
"./connect4_prog.o",
ARRAY_SIZE(prog_name),
prog_name, false);
}
void test_fexit_bpf2bpf(void)
@@ -128,4 +145,5 @@ void test_fexit_bpf2bpf(void)
test_target_no_callees();
test_target_yes_callees();
test_func_replace();
test_func_replace_verify();
}
@@ -18,11 +18,25 @@
int _version SEC("version") = 1;
__attribute__ ((noinline))
int do_bind(struct bpf_sock_addr *ctx)
{
struct sockaddr_in sa = {};
sa.sin_family = AF_INET;
sa.sin_port = bpf_htons(0);
sa.sin_addr.s_addr = bpf_htonl(SRC_REWRITE_IP4);
if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0)
return 0;
return 1;
}
SEC("cgroup/connect4")
int connect_v4_prog(struct bpf_sock_addr *ctx)
{
struct bpf_sock_tuple tuple = {};
struct sockaddr_in sa;
struct bpf_sock *sk;
/* Verify that new destination is available. */
@@ -56,17 +70,7 @@ int connect_v4_prog(struct bpf_sock_addr *ctx)
ctx->user_ip4 = bpf_htonl(DST_REWRITE_IP4);
ctx->user_port = bpf_htons(DST_REWRITE_PORT4);
/* Rewrite source. */
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = bpf_htons(0);
sa.sin_addr.s_addr = bpf_htonl(SRC_REWRITE_IP4);
if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0)
return 0;
return 1;
return do_bind(ctx) ? 1 : 0;
}
char _license[] SEC("license") = "GPL";
@@ -0,0 +1,18 @@
#include <linux/stddef.h>
#include <linux/ipv6.h>
#include <linux/bpf.h>
#include <linux/in.h>
#include <sys/socket.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>
SEC("freplace/do_bind")
int new_do_bind(struct bpf_sock_addr *ctx)
{
struct sockaddr_in sa = {};
bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa));
return 0;
}
char _license[] SEC("license") = "GPL";
@@ -20,20 +20,12 @@ struct bpf_map_def SEC("maps") btf_map = {
BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
struct dummy_tracepoint_args {
unsigned long long pad;
struct sock *sock;
};
__attribute__((noinline))
int test_long_fname_2(struct dummy_tracepoint_args *arg)
int test_long_fname_2(void)
{
struct ipv_counts *counts;
int key = 0;
if (!arg->sock)
return 0;
counts = bpf_map_lookup_elem(&btf_map, &key);
if (!counts)
return 0;
@@ -44,15 +36,15 @@ int test_long_fname_2(struct dummy_tracepoint_args *arg)
}
__attribute__((noinline))
int test_long_fname_1(struct dummy_tracepoint_args *arg)
int test_long_fname_1(void)
{
return test_long_fname_2(arg);
return test_long_fname_2();
}
SEC("dummy_tracepoint")
int _dummy_tracepoint(struct dummy_tracepoint_args *arg)
int _dummy_tracepoint(void *arg)
{
return test_long_fname_1(arg);
return test_long_fname_1();
}
char _license[] SEC("license") = "GPL";
@@ -28,20 +28,12 @@ struct {
__type(value, struct ipv_counts);
} btf_map SEC(".maps");
struct dummy_tracepoint_args {
unsigned long long pad;
struct sock *sock;
};
__attribute__((noinline))
int test_long_fname_2(struct dummy_tracepoint_args *arg)
int test_long_fname_2(void)
{
struct ipv_counts *counts;
int key = 0;
if (!arg->sock)
return 0;
counts = bpf_map_lookup_elem(&btf_map, &key);
if (!counts)
return 0;
@@ -57,15 +49,15 @@ int test_long_fname_2(struct dummy_tracepoint_args *arg)
}
__attribute__((noinline))
int test_long_fname_1(struct dummy_tracepoint_args *arg)
int test_long_fname_1(void)
{
return test_long_fname_2(arg);
return test_long_fname_2();
}
SEC("dummy_tracepoint")
int _dummy_tracepoint(struct dummy_tracepoint_args *arg)
int _dummy_tracepoint(void *arg)
{
return test_long_fname_1(arg);
return test_long_fname_1();
}
char _license[] SEC("license") = "GPL";
@@ -17,20 +17,12 @@ struct bpf_map_def SEC("maps") btf_map = {
.max_entries = 4,
};
struct dummy_tracepoint_args {
unsigned long long pad;
struct sock *sock;
};
__attribute__((noinline))
int test_long_fname_2(struct dummy_tracepoint_args *arg)
int test_long_fname_2(void)
{
struct ipv_counts *counts;
int key = 0;
if (!arg->sock)
return 0;
counts = bpf_map_lookup_elem(&btf_map, &key);
if (!counts)
return 0;
@@ -41,15 +33,15 @@ int test_long_fname_2(struct dummy_tracepoint_args *arg)
}
__attribute__((noinline))
int test_long_fname_1(struct dummy_tracepoint_args *arg)
int test_long_fname_1(void)
{
return test_long_fname_2(arg);
return test_long_fname_2();
}
SEC("dummy_tracepoint")
int _dummy_tracepoint(struct dummy_tracepoint_args *arg)
int _dummy_tracepoint(void *arg)
{
return test_long_fname_1(arg);
return test_long_fname_1();
}
char _license[] SEC("license") = "GPL";
+1 -1
View File
@@ -2854,7 +2854,7 @@ static struct btf_raw_test raw_tests[] = {
.value_type_id = 1,
.max_entries = 4,
.btf_load_err = true,
.err_str = "vlen != 0",
.err_str = "Invalid func linkage",
},
{
@@ -315,3 +315,43 @@
},
.result = ACCEPT,
},
{
"store PTR_TO_STACK in R10 to array map using BPF_B",
.insns = {
/* Load pointer to map. */
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
BPF_MOV64_IMM(BPF_REG_0, 2),
BPF_EXIT_INSN(),
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
/* Copy R10 to R9. */
BPF_MOV64_REG(BPF_REG_9, BPF_REG_10),
/* Pollute other registers with unaligned values. */
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_MOV64_IMM(BPF_REG_3, -1),
BPF_MOV64_IMM(BPF_REG_4, -1),
BPF_MOV64_IMM(BPF_REG_5, -1),
BPF_MOV64_IMM(BPF_REG_6, -1),
BPF_MOV64_IMM(BPF_REG_7, -1),
BPF_MOV64_IMM(BPF_REG_8, -1),
/* Store both R9 and R10 with BPF_B and read back. */
BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_10, 0),
BPF_LDX_MEM(BPF_B, BPF_REG_2, BPF_REG_1, 0),
BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_9, 0),
BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_1, 0),
/* Should read back as same value. */
BPF_JMP_REG(BPF_JEQ, BPF_REG_2, BPF_REG_3, 2),
BPF_MOV64_IMM(BPF_REG_0, 1),
BPF_EXIT_INSN(),
BPF_MOV64_IMM(BPF_REG_0, 42),
BPF_EXIT_INSN(),
},
.fixup_map_array_48b = { 3 },
.result = ACCEPT,
.retval = 42,
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
@@ -88,6 +88,7 @@
BPF_EXIT_INSN(),
},
.fixup_map_hash_48b = { 3 },
.errstr_unpriv = "leaking pointer from stack off -8",
.errstr = "R0 invalid mem access 'inv'",
.result = REJECT,
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3,6 +3,7 @@
#define _GNU_SOURCE
#include <poll.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <pthread.h>
#include <sys/epoll.h>
@@ -3136,4 +3137,149 @@ TEST(epoll59)
close(ctx.sfd[0]);
}
enum {
EPOLL60_EVENTS_NR = 10,
};
struct epoll60_ctx {
volatile int stopped;
int ready;
int waiters;
int epfd;
int evfd[EPOLL60_EVENTS_NR];
};
static void *epoll60_wait_thread(void *ctx_)
{
struct epoll60_ctx *ctx = ctx_;
struct epoll_event e;
sigset_t sigmask;
uint64_t v;
int ret;
/* Block SIGUSR1 */
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGUSR1);
sigprocmask(SIG_SETMASK, &sigmask, NULL);
/* Prepare empty mask for epoll_pwait() */
sigemptyset(&sigmask);
while (!ctx->stopped) {
/* Mark we are ready */
__atomic_fetch_add(&ctx->ready, 1, __ATOMIC_ACQUIRE);
/* Start when all are ready */
while (__atomic_load_n(&ctx->ready, __ATOMIC_ACQUIRE) &&
!ctx->stopped);
/* Account this waiter */
__atomic_fetch_add(&ctx->waiters, 1, __ATOMIC_ACQUIRE);
ret = epoll_pwait(ctx->epfd, &e, 1, 2000, &sigmask);
if (ret != 1) {
/* We expect only signal delivery on stop */
assert(ret < 0 && errno == EINTR && "Lost wakeup!\n");
assert(ctx->stopped);
break;
}
ret = read(e.data.fd, &v, sizeof(v));
/* Since we are on ET mode, thus each thread gets its own fd. */
assert(ret == sizeof(v));
__atomic_fetch_sub(&ctx->waiters, 1, __ATOMIC_RELEASE);
}
return NULL;
}
static inline unsigned long long msecs(void)
{
struct timespec ts;
unsigned long long msecs;
clock_gettime(CLOCK_REALTIME, &ts);
msecs = ts.tv_sec * 1000ull;
msecs += ts.tv_nsec / 1000000ull;
return msecs;
}
static inline int count_waiters(struct epoll60_ctx *ctx)
{
return __atomic_load_n(&ctx->waiters, __ATOMIC_ACQUIRE);
}
TEST(epoll60)
{
struct epoll60_ctx ctx = { 0 };
pthread_t waiters[ARRAY_SIZE(ctx.evfd)];
struct epoll_event e;
int i, n, ret;
signal(SIGUSR1, signal_handler);
ctx.epfd = epoll_create1(0);
ASSERT_GE(ctx.epfd, 0);
/* Create event fds */
for (i = 0; i < ARRAY_SIZE(ctx.evfd); i++) {
ctx.evfd[i] = eventfd(0, EFD_NONBLOCK);
ASSERT_GE(ctx.evfd[i], 0);
e.events = EPOLLIN | EPOLLET;
e.data.fd = ctx.evfd[i];
ASSERT_EQ(epoll_ctl(ctx.epfd, EPOLL_CTL_ADD, ctx.evfd[i], &e), 0);
}
/* Create waiter threads */
for (i = 0; i < ARRAY_SIZE(waiters); i++)
ASSERT_EQ(pthread_create(&waiters[i], NULL,
epoll60_wait_thread, &ctx), 0);
for (i = 0; i < 300; i++) {
uint64_t v = 1, ms;
/* Wait for all to be ready */
while (__atomic_load_n(&ctx.ready, __ATOMIC_ACQUIRE) !=
ARRAY_SIZE(ctx.evfd))
;
/* Steady, go */
__atomic_fetch_sub(&ctx.ready, ARRAY_SIZE(ctx.evfd),
__ATOMIC_ACQUIRE);
/* Wait all have gone to kernel */
while (count_waiters(&ctx) != ARRAY_SIZE(ctx.evfd))
;
/* 1ms should be enough to schedule away */
usleep(1000);
/* Quickly signal all handles at once */
for (n = 0; n < ARRAY_SIZE(ctx.evfd); n++) {
ret = write(ctx.evfd[n], &v, sizeof(v));
ASSERT_EQ(ret, sizeof(v));
}
/* Busy loop for 1s and wait for all waiters to wake up */
ms = msecs();
while (count_waiters(&ctx) && msecs() < ms + 1000)
;
ASSERT_EQ(count_waiters(&ctx), 0);
}
ctx.stopped = 1;
/* Stop waiters */
for (i = 0; i < ARRAY_SIZE(waiters); i++)
ret = pthread_kill(waiters[i], SIGUSR1);
for (i = 0; i < ARRAY_SIZE(waiters); i++)
pthread_join(waiters[i], NULL);
for (i = 0; i < ARRAY_SIZE(waiters); i++)
close(ctx.evfd[i]);
close(ctx.epfd);
}
TEST_HARNESS_MAIN
+1
View File
@@ -11,5 +11,6 @@ CONFIG_PREEMPTIRQ_DELAY_TEST=m
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_SAMPLES=y
CONFIG_SAMPLE_FTRACE_DIRECT=m
CONFIG_SAMPLE_TRACE_PRINTK=m
CONFIG_KALLSYMS_ALL=y
+30 -2
View File
@@ -17,6 +17,7 @@ echo " -v|--verbose Increase verbosity of test messages"
echo " -vv Alias of -v -v (Show all results in stdout)"
echo " -vvv Alias of -v -v -v (Show all commands immediately)"
echo " --fail-unsupported Treat UNSUPPORTED as a failure"
echo " --fail-unresolved Treat UNRESOLVED as a failure"
echo " -d|--debug Debug mode (trace all shell commands)"
echo " -l|--logdir <dir> Save logs on the <dir>"
echo " If <dir> is -, all logs output in console only"
@@ -29,8 +30,25 @@ err_ret=1
# kselftest skip code is 4
err_skip=4
# cgroup RT scheduling prevents chrt commands from succeeding, which
# induces failures in test wakeup tests. Disable for the duration of
# the tests.
readonly sched_rt_runtime=/proc/sys/kernel/sched_rt_runtime_us
sched_rt_runtime_orig=$(cat $sched_rt_runtime)
setup() {
echo -1 > $sched_rt_runtime
}
cleanup() {
echo $sched_rt_runtime_orig > $sched_rt_runtime
}
errexit() { # message
echo "Error: $1" 1>&2
cleanup
exit $err_ret
}
@@ -39,6 +57,8 @@ if [ `id -u` -ne 0 ]; then
errexit "this must be run by root user"
fi
setup
# Utilities
absdir() { # file_path
(cd `dirname $1`; pwd)
@@ -93,6 +113,10 @@ parse_opts() { # opts
UNSUPPORTED_RESULT=1
shift 1
;;
--fail-unresolved)
UNRESOLVED_RESULT=1
shift 1
;;
--logdir|-l)
LOG_DIR=$2
shift 2
@@ -157,6 +181,7 @@ KEEP_LOG=0
DEBUG=0
VERBOSE=0
UNSUPPORTED_RESULT=0
UNRESOLVED_RESULT=0
STOP_FAILURE=0
# Parse command-line options
parse_opts $*
@@ -235,6 +260,7 @@ TOTAL_RESULT=0
INSTANCE=
CASENO=0
testcase() { # testfile
CASENO=$((CASENO+1))
desc=`grep "^#[ \t]*description:" $1 | cut -f2 -d:`
@@ -260,7 +286,7 @@ eval_result() { # sigval
$UNRESOLVED)
prlog " [${color_blue}UNRESOLVED${color_reset}]"
UNRESOLVED_CASES="$UNRESOLVED_CASES $CASENO"
return 1 # this is a kind of bug.. something happened.
return $UNRESOLVED_RESULT # depends on use case
;;
$UNTESTED)
prlog " [${color_blue}UNTESTED${color_reset}]"
@@ -273,7 +299,7 @@ eval_result() { # sigval
return $UNSUPPORTED_RESULT # depends on use case
;;
$XFAIL)
prlog " [${color_red}XFAIL${color_reset}]"
prlog " [${color_green}XFAIL${color_reset}]"
XFAILED_CASES="$XFAILED_CASES $CASENO"
return 0
;;
@@ -406,5 +432,7 @@ prlog "# of unsupported: " `echo $UNSUPPORTED_CASES | wc -w`
prlog "# of xfailed: " `echo $XFAILED_CASES | wc -w`
prlog "# of undefined(test bug): " `echo $UNDEFINED_CASES | wc -w`
cleanup
# if no error, return 0
exit $TOTAL_RESULT
@@ -10,10 +10,7 @@ if ! grep -q function_graph available_tracers; then
exit_unsupported
fi
if [ ! -f set_ftrace_filter ]; then
echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
exit_unsupported
fi
check_filter_file set_ftrace_filter
do_reset() {
if [ -e /proc/sys/kernel/stack_tracer_enabled ]; then
@@ -9,6 +9,8 @@ if ! grep -q function_graph available_tracers; then
exit_unsupported
fi
check_filter_file set_ftrace_filter
fail() { # msg
echo $1
exit_fail
@@ -9,6 +9,8 @@ if ! grep -q function available_tracers; then
exit_unsupported
fi
check_filter_file set_ftrace_filter
disable_tracing
clear_trace
@@ -15,10 +15,7 @@ if [ ! -f set_ftrace_notrace_pid ]; then
exit_unsupported
fi
if [ ! -f set_ftrace_filter ]; then
echo "set_ftrace_filter not found? Is function tracer not set?"
exit_unsupported
fi
check_filter_file set_ftrace_filter
do_function_fork=1
@@ -16,10 +16,7 @@ if [ ! -f set_ftrace_pid ]; then
exit_unsupported
fi
if [ ! -f set_ftrace_filter ]; then
echo "set_ftrace_filter not found? Is function tracer not set?"
exit_unsupported
fi
check_filter_file set_ftrace_filter
do_function_fork=1
@@ -3,7 +3,7 @@
# description: ftrace - stacktrace filter command
# flags: instance
[ ! -f set_ftrace_filter ] && exit_unsupported
check_filter_file set_ftrace_filter
echo _do_fork:stacktrace >> set_ftrace_filter
@@ -11,10 +11,7 @@
#
# The triggers are set within the set_ftrace_filter file
if [ ! -f set_ftrace_filter ]; then
echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
exit_unsupported
fi
check_filter_file set_ftrace_filter
do_reset() {
reset_ftrace_filter
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-2.0
# description: ftrace - function trace on module
[ ! -f set_ftrace_filter ] && exit_unsupported
check_filter_file set_ftrace_filter
: "mod: allows to filter a non exist function"
echo 'non_exist_func:mod:non_exist_module' > set_ftrace_filter
@@ -18,10 +18,7 @@ if ! grep -q function_graph available_tracers; then
exit_unsupported;
fi
if [ ! -f set_ftrace_filter ]; then
echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
exit_unsupported
fi
check_filter_file set_ftrace_filter
if [ ! -f function_profile_enabled ]; then
echo "function_profile_enabled not found, function profiling enabled?"
@@ -10,10 +10,7 @@
#
# The triggers are set within the set_ftrace_filter file
if [ ! -f set_ftrace_filter ]; then
echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
exit_unsupported
fi
check_filter_file set_ftrace_filter
fail() { # mesg
echo $1
@@ -8,6 +8,8 @@ if [ ! -f stack_trace ]; then
exit_unsupported
fi
check_filter_file stack_trace_filter
echo > stack_trace_filter
echo 0 > stack_max_size
echo 1 > /proc/sys/kernel/stack_tracer_enabled
@@ -11,10 +11,7 @@
#
# The triggers are set within the set_ftrace_filter file
if [ ! -f set_ftrace_filter ]; then
echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
exit_unsupported
fi
check_filter_file set_ftrace_filter
fail() { # mesg
echo $1
@@ -1,3 +1,9 @@
check_filter_file() { # check filter file introduced by dynamic ftrace
if [ ! -f "$1" ]; then
echo "$1 not found? Is dynamic ftrace not set?"
exit_unsupported
fi
}
clear_trace() { # reset trace output
echo > trace
@@ -38,7 +38,7 @@ for width in 64 32 16 8; do
echo 0 > events/kprobes/testprobe/enable
: "Confirm the arguments is recorded in given types correctly"
ARGS=`grep "testprobe" trace | sed -e 's/.* arg1=\(.*\) arg2=\(.*\) arg3=\(.*\) arg4=\(.*\)/\1 \2 \3 \4/'`
ARGS=`grep "testprobe" trace | head -n 1 | sed -e 's/.* arg1=\(.*\) arg2=\(.*\) arg3=\(.*\) arg4=\(.*\)/\1 \2 \3 \4/'`
check_types $ARGS $width
: "Clear event for next loop"
@@ -5,6 +5,8 @@
[ -f kprobe_events ] || exit_unsupported # this is configurable
grep "function" available_tracers || exit_unsupported # this is configurable
check_filter_file set_ftrace_filter
# prepare
echo nop > current_tracer
echo _do_fork > set_ftrace_filter
+6 -6
View File
@@ -1,13 +1,13 @@
# SPDX-License-Identifier: GPL-2.0
MOUNT_CFLAGS := $(shell pkg-config --cflags mount 2>/dev/null)
MOUNT_LDLIBS := $(shell pkg-config --libs mount 2>/dev/null)
ifeq ($(MOUNT_LDLIBS),)
MOUNT_LDLIBS := -lmount -I/usr/include/libmount
VAR_CFLAGS := $(shell pkg-config --cflags mount 2>/dev/null)
VAR_LDLIBS := $(shell pkg-config --libs mount 2>/dev/null)
ifeq ($(VAR_LDLIBS),)
VAR_LDLIBS := -lmount -I/usr/include/libmount
endif
CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(MOUNT_CFLAGS)
LDLIBS += $(MOUNT_LDLIBS)
CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(VAR_CFLAGS)
LDLIBS += $(VAR_LDLIBS)
TEST_PROGS := gpio-mockup.sh
TEST_FILES := gpio-mockup-sysfs.sh
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE
LDLIBS := $(LDLIBS) -lm
LDLIBS += -lm
uname_M := $(shell uname -m 2>/dev/null || echo not)
ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
+1 -1
View File
@@ -137,7 +137,7 @@ int dump_queue(struct msgque_data *msgque)
for (kern_id = 0; kern_id < 256; kern_id++) {
ret = msgctl(kern_id, MSG_STAT, &ds);
if (ret < 0) {
if (errno == -EINVAL)
if (errno == EINVAL)
continue;
printf("Failed to get stats for IPC queue with id %d\n",
kern_id);
+1 -1
View File
@@ -33,7 +33,7 @@ tap_timeout()
{
# Make sure tests will time out if utility is available.
if [ -x /usr/bin/timeout ] ; then
/usr/bin/timeout "$kselftest_timeout" "$1"
/usr/bin/timeout --foreground "$kselftest_timeout" "$1"
else
"$1"
fi
+272
View File
@@ -0,0 +1,272 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# kselftest_deps.sh
#
# Checks for kselftest build dependencies on the build system.
# Copyright (c) 2020 Shuah Khan <skhan@linuxfoundation.org>
#
#
usage()
{
echo -e "Usage: $0 -[p] <compiler> [test_name]\n"
echo -e "\tkselftest_deps.sh [-p] gcc"
echo -e "\tkselftest_deps.sh [-p] gcc vm"
echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc"
echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc vm\n"
echo "- Should be run in selftests directory in the kernel repo."
echo "- Checks if Kselftests can be built/cross-built on a system."
echo "- Parses all test/sub-test Makefile to find library dependencies."
echo "- Runs compile test on a trivial C file with LDLIBS specified"
echo " in the test Makefiles to identify missing library dependencies."
echo "- Prints suggested target list for a system filtering out tests"
echo " failed the build dependency check from the TARGETS in Selftests"
echo " main Makefile when optional -p is specified."
echo "- Prints pass/fail dependency check for each tests/sub-test."
echo "- Prints pass/fail targets and libraries."
echo "- Default: runs dependency checks on all tests."
echo "- Optional test name can be specified to check dependencies for it."
exit 1
}
# Start main()
main()
{
base_dir=`pwd`
# Make sure we're in the selftests top-level directory.
if [ $(basename "$base_dir") != "selftests" ]; then
echo -e "\tPlease run $0 in"
echo -e "\ttools/testing/selftests directory ..."
exit 1
fi
print_targets=0
while getopts "p" arg; do
case $arg in
p)
print_targets=1
shift;;
esac
done
if [ $# -eq 0 ]
then
usage
fi
# Compiler
CC=$1
tmp_file=$(mktemp).c
trap "rm -f $tmp_file.o $tmp_file $tmp_file.bin" EXIT
#echo $tmp_file
pass=$(mktemp).out
trap "rm -f $pass" EXIT
#echo $pass
fail=$(mktemp).out
trap "rm -f $fail" EXIT
#echo $fail
# Generate tmp source fire for compile test
cat << "EOF" > $tmp_file
int main()
{
}
EOF
# Save results
total_cnt=0
fail_trgts=()
fail_libs=()
fail_cnt=0
pass_trgts=()
pass_libs=()
pass_cnt=0
# Get all TARGETS from selftests Makefile
targets=$(egrep "^TARGETS +|^TARGETS =" Makefile | cut -d "=" -f2)
# Single test case
if [ $# -eq 2 ]
then
test=$2/Makefile
l1_test $test
l2_test $test
l3_test $test
print_results $1 $2
exit $?
fi
# Level 1: LDLIBS set static.
#
# Find all LDLIBS set statically for all executables built by a Makefile
# and filter out VAR_LDLIBS to discard the following:
# gpio/Makefile:LDLIBS += $(VAR_LDLIBS)
# Append space at the end of the list to append more tests.
l1_tests=$(grep -r --include=Makefile "^LDLIBS" | \
grep -v "VAR_LDLIBS" | awk -F: '{print $1}')
# Level 2: LDLIBS set dynamically.
#
# Level 2
# Some tests have multiple valid LDLIBS lines for individual sub-tests
# that need dependency checks. Find them and append them to the tests
# e.g: vm/Makefile:$(OUTPUT)/userfaultfd: LDLIBS += -lpthread
# Filter out VAR_LDLIBS to discard the following:
# memfd/Makefile:$(OUTPUT)/fuse_mnt: LDLIBS += $(VAR_LDLIBS)
# Append space at the end of the list to append more tests.
l2_tests=$(grep -r --include=Makefile ": LDLIBS" | \
grep -v "VAR_LDLIBS" | awk -F: '{print $1}')
# Level 3
# gpio, memfd and others use pkg-config to find mount and fuse libs
# respectively and save it in VAR_LDLIBS. If pkg-config doesn't find
# any, VAR_LDLIBS set to default.
# Use the default value and filter out pkg-config for dependency check.
# e.g:
# gpio/Makefile
# VAR_LDLIBS := $(shell pkg-config --libs mount) 2>/dev/null)
# memfd/Makefile
# VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null)
l3_tests=$(grep -r --include=Makefile "^VAR_LDLIBS" | \
grep -v "pkg-config" | awk -F: '{print $1}')
#echo $l1_tests
#echo $l2_1_tests
#echo $l3_tests
all_tests
print_results $1 $2
exit $?
}
# end main()
all_tests()
{
for test in $l1_tests; do
l1_test $test
done
for test in $l2_tests; do
l2_test $test
done
for test in $l3_tests; do
l3_test $test
done
}
# Use same parsing used for l1_tests and pick libraries this time.
l1_test()
{
test_libs=$(grep --include=Makefile "^LDLIBS" $test | \
grep -v "VAR_LDLIBS" | \
sed -e 's/\:/ /' | \
sed -e 's/+/ /' | cut -d "=" -f 2)
check_libs $test $test_libs
}
# Use same parsing used for l2__tests and pick libraries this time.
l2_test()
{
test_libs=$(grep --include=Makefile ": LDLIBS" $test | \
grep -v "VAR_LDLIBS" | \
sed -e 's/\:/ /' | sed -e 's/+/ /' | \
cut -d "=" -f 2)
check_libs $test $test_libs
}
l3_test()
{
test_libs=$(grep --include=Makefile "^VAR_LDLIBS" $test | \
grep -v "pkg-config" | sed -e 's/\:/ /' |
sed -e 's/+/ /' | cut -d "=" -f 2)
check_libs $test $test_libs
}
check_libs()
{
if [[ ! -z "${test_libs// }" ]]
then
#echo $test_libs
for lib in $test_libs; do
let total_cnt+=1
$CC -o $tmp_file.bin $lib $tmp_file > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "FAIL: $test dependency check: $lib" >> $fail
let fail_cnt+=1
fail_libs+="$lib "
fail_target=$(echo "$test" | cut -d "/" -f1)
fail_trgts+="$fail_target "
targets=$(echo "$targets" | grep -v "$fail_target")
else
echo "PASS: $test dependency check passed $lib" >> $pass
let pass_cnt+=1
pass_libs+="$lib "
pass_trgts+="$(echo "$test" | cut -d "/" -f1) "
fi
done
fi
}
print_results()
{
echo -e "========================================================";
echo -e "Kselftest Dependency Check for [$0 $1 $2] results..."
if [ $print_targets -ne 0 ]
then
echo -e "Suggested Selftest Targets for your configuration:"
echo -e "$targets";
fi
echo -e "========================================================";
echo -e "Checked tests defining LDLIBS dependencies"
echo -e "--------------------------------------------------------";
echo -e "Total tests with Dependencies:"
echo -e "$total_cnt Pass: $pass_cnt Fail: $fail_cnt";
if [ $pass_cnt -ne 0 ]; then
echo -e "--------------------------------------------------------";
cat $pass
echo -e "--------------------------------------------------------";
echo -e "Targets passed build dependency check on system:"
echo -e "$(echo "$pass_trgts" | xargs -n1 | sort -u | xargs)"
fi
if [ $fail_cnt -ne 0 ]; then
echo -e "--------------------------------------------------------";
cat $fail
echo -e "--------------------------------------------------------";
echo -e "Targets failed build dependency check on system:"
echo -e "$(echo "$fail_trgts" | xargs -n1 | sort -u | xargs)"
echo -e "--------------------------------------------------------";
echo -e "Missing libraries system"
echo -e "$(echo "$fail_libs" | xargs -n1 | sort -u | xargs)"
fi
echo -e "--------------------------------------------------------";
echo -e "========================================================";
}
main "$@"
+3 -3
View File
@@ -705,7 +705,7 @@ static void __timeout_handler(int sig, siginfo_t *info, void *ucontext)
/* Sanity check handler execution environment. */
if (!t) {
fprintf(TH_LOG_STREAM,
"no active test in SIGARLM handler!?\n");
"no active test in SIGALRM handler!?\n");
abort();
}
if (sig != SIGALRM || sig != info->si_signo) {
@@ -731,7 +731,7 @@ void __wait_for_test(struct __test_metadata *t)
if (sigaction(SIGALRM, &action, &saved_action)) {
t->passed = 0;
fprintf(TH_LOG_STREAM,
"%s: unable to install SIGARLM handler\n",
"%s: unable to install SIGALRM handler\n",
t->name);
return;
}
@@ -743,7 +743,7 @@ void __wait_for_test(struct __test_metadata *t)
if (sigaction(SIGALRM, &saved_action, NULL)) {
t->passed = 0;
fprintf(TH_LOG_STREAM,
"%s: unable to uninstall SIGARLM handler\n",
"%s: unable to uninstall SIGALRM handler\n",
t->name);
return;
}
+28 -1
View File
@@ -5,8 +5,34 @@ all:
top_srcdir = ../../../..
KSFT_KHDR_INSTALL := 1
# For cross-builds to work, UNAME_M has to map to ARCH and arch specific
# directories and targets in this Makefile. "uname -m" doesn't map to
# arch specific sub-directory names.
#
# UNAME_M variable to used to run the compiles pointing to the right arch
# directories and build the right targets for these supported architectures.
#
# TEST_GEN_PROGS and LIBKVM are set using UNAME_M variable.
# LINUX_TOOL_ARCH_INCLUDE is set using ARCH variable.
#
# x86_64 targets are named to include x86_64 as a suffix and directories
# for includes are in x86_64 sub-directory. s390x and aarch64 follow the
# same convention. "uname -m" doesn't result in the correct mapping for
# s390x and aarch64.
#
# No change necessary for x86_64
UNAME_M := $(shell uname -m)
# Set UNAME_M for arm64 compile/install to work
ifeq ($(ARCH),arm64)
UNAME_M := aarch64
endif
# Set UNAME_M s390x compile/install to work
ifeq ($(ARCH),s390)
UNAME_M := s390x
endif
LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c lib/test_util.c
LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c
LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c
@@ -56,7 +82,7 @@ LIBKVM += $(LIBKVM_$(UNAME_M))
INSTALL_HDR_PATH = $(top_srcdir)/usr
LINUX_HDR_PATH = $(INSTALL_HDR_PATH)/include/
LINUX_TOOL_INCLUDE = $(top_srcdir)/tools/include
LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/x86/include
LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/$(ARCH)/include
CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \
-fno-stack-protector -fno-PIE -I$(LINUX_TOOL_INCLUDE) \
-I$(LINUX_TOOL_ARCH_INCLUDE) -I$(LINUX_HDR_PATH) -Iinclude \
@@ -87,6 +113,7 @@ $(LIBKVM_OBJ): $(OUTPUT)/%.o: %.c
$(OUTPUT)/libkvm.a: $(LIBKVM_OBJ)
$(AR) crs $@ $^
x := $(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS))))
all: $(STATIC_LIBS)
$(TEST_GEN_PROGS): $(STATIC_LIBS)
+14 -3
View File
@@ -4,14 +4,25 @@ CFLAGS += -I../../../../include/uapi/
CFLAGS += -I../../../../include/
CFLAGS += -I../../../../usr/include/
TEST_GEN_PROGS := memfd_test fuse_test fuse_mnt
TEST_GEN_PROGS := memfd_test
TEST_PROGS := run_fuse_test.sh run_hugetlbfs_test.sh
TEST_GEN_FILES := fuse_test fuse_mnt
fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags)
VAR_CFLAGS := $(shell pkg-config fuse --cflags 2>/dev/null)
ifeq ($(VAR_CFLAGS),)
VAR_CFLAGS := -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse
endif
VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null)
ifeq ($(VAR_LDLIBS),)
VAR_LDLIBS := -lfuse -pthread
endif
fuse_mnt.o: CFLAGS += $(VAR_CFLAGS)
include ../lib.mk
$(OUTPUT)/fuse_mnt: LDLIBS += $(shell pkg-config fuse --libs)
$(OUTPUT)/fuse_mnt: LDLIBS += $(VAR_LDLIBS)
$(OUTPUT)/memfd_test: memfd_test.c common.c
$(OUTPUT)/fuse_test: fuse_test.c common.c
@@ -749,6 +749,29 @@ ipv4_fcnal_runtime()
run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
log_test $? 0 "Ping - multipath"
run_cmd "$IP ro delete 172.16.101.1/32 nhid 122"
#
# multiple default routes
# - tests fib_select_default
run_cmd "$IP nexthop add id 501 via 172.16.1.2 dev veth1"
run_cmd "$IP ro add default nhid 501"
run_cmd "$IP ro add default via 172.16.1.3 dev veth1 metric 20"
run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
log_test $? 0 "Ping - multiple default routes, nh first"
# flip the order
run_cmd "$IP ro del default nhid 501"
run_cmd "$IP ro del default via 172.16.1.3 dev veth1 metric 20"
run_cmd "$IP ro add default via 172.16.1.2 dev veth1 metric 20"
run_cmd "$IP nexthop replace id 501 via 172.16.1.3 dev veth1"
run_cmd "$IP ro add default nhid 501 metric 20"
run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
log_test $? 0 "Ping - multiple default routes, nh second"
run_cmd "$IP nexthop delete nhid 501"
run_cmd "$IP ro del default"
#
# IPv4 with blackhole nexthops
#
+8 -2
View File
@@ -618,16 +618,22 @@ fib_nexthop_test()
fib_suppress_test()
{
echo
echo "FIB rule with suppress_prefixlength"
setup
$IP link add dummy1 type dummy
$IP link set dummy1 up
$IP -6 route add default dev dummy1
$IP -6 rule add table main suppress_prefixlength 0
ping -f -c 1000 -W 1 1234::1 || true
ping -f -c 1000 -W 1 1234::1 >/dev/null 2>&1
$IP -6 rule del table main suppress_prefixlength 0
$IP link del dummy1
# If we got here without crashing, we're good.
return 0
log_test 0 0 "FIB rule suppress test"
cleanup
}
################################################################################
+5 -2
View File
@@ -165,9 +165,10 @@ void *child_thread(void *arg)
socklen_t zc_len = sizeof(zc);
int res;
memset(&zc, 0, sizeof(zc));
zc.address = (__u64)((unsigned long)addr);
zc.length = chunk_size;
zc.recv_skip_hint = 0;
res = getsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE,
&zc, &zc_len);
if (res == -1)
@@ -281,12 +282,14 @@ static void setup_sockaddr(int domain, const char *str_addr,
static void do_accept(int fdlisten)
{
pthread_attr_t attr;
int rcvlowat;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
rcvlowat = chunk_size;
if (setsockopt(fdlisten, SOL_SOCKET, SO_RCVLOWAT,
&chunk_size, sizeof(chunk_size)) == -1) {
&rcvlowat, sizeof(rcvlowat)) == -1) {
perror("setsockopt SO_RCVLOWAT");
}
@@ -2803,12 +2803,13 @@ TEST(syscall_restart)
offsetof(struct seccomp_data, nr)),
#ifdef __NR_sigreturn
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_sigreturn, 6, 0),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_sigreturn, 7, 0),
#endif
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 5, 0),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_exit, 4, 0),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_rt_sigreturn, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_nanosleep, 4, 0),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 6, 0),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_exit, 5, 0),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_rt_sigreturn, 4, 0),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_nanosleep, 5, 0),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_clock_nanosleep, 4, 0),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_restart_syscall, 4, 0),
/* Allow __NR_write for easy logging. */
@@ -2895,7 +2896,8 @@ TEST(syscall_restart)
ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
ASSERT_EQ(0x100, msg);
EXPECT_EQ(__NR_nanosleep, get_syscall(_metadata, child_pid));
ret = get_syscall(_metadata, child_pid);
EXPECT_TRUE(ret == __NR_nanosleep || ret == __NR_clock_nanosleep);
/* Might as well check siginfo for sanity while we're here. */
ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
+2 -11
View File
@@ -1,17 +1,8 @@
#!/bin/bash
# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
self.flags = flags
# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
if [ -f /dev/tpm0 ] ; then
python -m unittest -v tpm2_tests.SmokeTest
python -m unittest -v tpm2_tests.AsyncTest
else
exit $ksft_skip
fi
python -m unittest -v tpm2_tests.SmokeTest
python -m unittest -v tpm2_tests.AsyncTest
CLEAR_CMD=$(which tpm2_clear)
if [ -n $CLEAR_CMD ]; then
+1 -8
View File
@@ -1,11 +1,4 @@
#!/bin/bash
# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
if [ -f /dev/tpmrm0 ] ; then
python -m unittest -v tpm2_tests.SpaceTest
else
exit $ksft_skip
fi
python -m unittest -v tpm2_tests.SpaceTest
+2 -2
View File
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
# Makefile for vm selftests
uname_M := $(shell uname -m 2>/dev/null || echo not)
ARCH ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/')
MACHINE ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/')
CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS)
LDLIBS = -lrt
@@ -20,7 +20,7 @@ TEST_GEN_FILES += thuge-gen
TEST_GEN_FILES += transhuge-stress
TEST_GEN_FILES += userfaultfd
ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 ppc64 riscv64 s390x sh64 sparc64 x86_64))
ifneq (,$(filter $(MACHINE),arm64 ia64 mips64 parisc64 ppc64 ppc64le riscv64 s390x sh64 sparc64 x86_64))
TEST_GEN_FILES += va_128TBswitch
TEST_GEN_FILES += virtual_address_range
TEST_GEN_FILES += write_to_hugetlbfs
+1 -1
View File
@@ -59,7 +59,7 @@ else
fi
#filter 64bit architectures
ARCH64STR="arm64 ia64 mips64 parisc64 ppc64 riscv64 s390x sh64 sparc64 x86_64"
ARCH64STR="arm64 ia64 mips64 parisc64 ppc64 ppc64le riscv64 s390x sh64 sparc64 x86_64"
if [ -z $ARCH ]; then
ARCH=`uname -m 2>/dev/null | sed -e 's/aarch64.*/arm64/'`
fi
+51 -3
View File
@@ -48,8 +48,11 @@ cleanup() {
exec 2>/dev/null
printf "$orig_message_cost" > /proc/sys/net/core/message_cost
ip0 link del dev wg0
ip0 link del dev wg1
ip1 link del dev wg0
ip1 link del dev wg1
ip2 link del dev wg0
ip2 link del dev wg1
local to_kill="$(ip netns pids $netns0) $(ip netns pids $netns1) $(ip netns pids $netns2)"
[[ -n $to_kill ]] && kill $to_kill
pp ip netns del $netns1
@@ -77,18 +80,20 @@ ip0 link set wg0 netns $netns2
key1="$(pp wg genkey)"
key2="$(pp wg genkey)"
key3="$(pp wg genkey)"
key4="$(pp wg genkey)"
pub1="$(pp wg pubkey <<<"$key1")"
pub2="$(pp wg pubkey <<<"$key2")"
pub3="$(pp wg pubkey <<<"$key3")"
pub4="$(pp wg pubkey <<<"$key4")"
psk="$(pp wg genpsk)"
[[ -n $key1 && -n $key2 && -n $psk ]]
configure_peers() {
ip1 addr add 192.168.241.1/24 dev wg0
ip1 addr add fd00::1/24 dev wg0
ip1 addr add fd00::1/112 dev wg0
ip2 addr add 192.168.241.2/24 dev wg0
ip2 addr add fd00::2/24 dev wg0
ip2 addr add fd00::2/112 dev wg0
n1 wg set wg0 \
private-key <(echo "$key1") \
@@ -230,9 +235,38 @@ n1 ping -W 1 -c 1 192.168.241.2
n1 wg set wg0 private-key <(echo "$key3")
n2 wg set wg0 peer "$pub3" preshared-key <(echo "$psk") allowed-ips 192.168.241.1/32 peer "$pub1" remove
n1 ping -W 1 -c 1 192.168.241.2
n2 wg set wg0 peer "$pub3" remove
ip1 link del wg0
# Test that we can route wg through wg
ip1 addr flush dev wg0
ip2 addr flush dev wg0
ip1 addr add fd00::5:1/112 dev wg0
ip2 addr add fd00::5:2/112 dev wg0
n1 wg set wg0 private-key <(echo "$key1") peer "$pub2" preshared-key <(echo "$psk") allowed-ips fd00::5:2/128 endpoint 127.0.0.1:2
n2 wg set wg0 private-key <(echo "$key2") listen-port 2 peer "$pub1" preshared-key <(echo "$psk") allowed-ips fd00::5:1/128 endpoint 127.212.121.99:9998
ip1 link add wg1 type wireguard
ip2 link add wg1 type wireguard
ip1 addr add 192.168.241.1/24 dev wg1
ip1 addr add fd00::1/112 dev wg1
ip2 addr add 192.168.241.2/24 dev wg1
ip2 addr add fd00::2/112 dev wg1
ip1 link set mtu 1340 up dev wg1
ip2 link set mtu 1340 up dev wg1
n1 wg set wg1 listen-port 5 private-key <(echo "$key3") peer "$pub4" allowed-ips 192.168.241.2/32,fd00::2/128 endpoint [fd00::5:2]:5
n2 wg set wg1 listen-port 5 private-key <(echo "$key4") peer "$pub3" allowed-ips 192.168.241.1/32,fd00::1/128 endpoint [fd00::5:1]:5
tests
# Try to set up a routing loop between the two namespaces
ip1 link set netns $netns0 dev wg1
ip0 addr add 192.168.241.1/24 dev wg1
ip0 link set up dev wg1
n0 ping -W 1 -c 1 192.168.241.2
n1 wg set wg0 peer "$pub2" endpoint 192.168.241.2:7
ip2 link del wg0
ip2 link del wg1
! n0 ping -W 1 -c 10 -f 192.168.241.2 || false # Should not crash kernel
ip0 link del wg1
ip1 link del wg0
# Test using NAT. We now change the topology to this:
# ┌────────────────────────────────────────┐ ┌────────────────────────────────────────────────┐ ┌────────────────────────────────────────┐
@@ -282,6 +316,20 @@ pp sleep 3
n2 ping -W 1 -c 1 192.168.241.1
n1 wg set wg0 peer "$pub2" persistent-keepalive 0
# Test that onion routing works, even when it loops
n1 wg set wg0 peer "$pub3" allowed-ips 192.168.242.2/32 endpoint 192.168.241.2:5
ip1 addr add 192.168.242.1/24 dev wg0
ip2 link add wg1 type wireguard
ip2 addr add 192.168.242.2/24 dev wg1
n2 wg set wg1 private-key <(echo "$key3") listen-port 5 peer "$pub1" allowed-ips 192.168.242.1/32
ip2 link set wg1 up
n1 ping -W 1 -c 1 192.168.242.2
ip2 link del wg1
n1 wg set wg0 peer "$pub3" endpoint 192.168.242.2:5
! n1 ping -W 1 -c 1 192.168.242.2 || false # Should not crash kernel
n1 wg set wg0 peer "$pub3" remove
ip1 addr del 192.168.242.1/24 dev wg0
# Do a wg-quick(8)-style policy routing for the default route, making sure vethc has a v6 address to tease out bugs.
ip1 -6 addr add fc00::9/96 dev vethc
ip1 -6 route add default via fc00::1
@@ -10,3 +10,4 @@ CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=hvc0 wg.success=hvc1"
CONFIG_SECTION_MISMATCH_WARN_ONLY=y
CONFIG_FRAME_WARN=1280
CONFIG_THREAD_SHIFT=14
@@ -25,7 +25,6 @@ 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