summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2026-01-26 17:03:53 -0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2026-01-26 17:03:53 -0300
commitd3b402c5a2d47f51eb0581da1a7b142f82cb10d1 (patch)
treecf5b202147ca9d061067f87339450834aa25a7f0 /tools
parent3d06db9bad1ad8e67c3981964cfba224c07fc306 (diff)
parentfcb70a56f4d81450114034b2c61f48ce7444a0e2 (diff)
Merge remote-tracking branch 'torvalds/master' into perf-tools-next
Merge with upstream to pick up fixes from perf-tools and from other tools/ parts that interact with tools/perf. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/include/io_uring/mini_liburing.h59
-rw-r--r--tools/include/uapi/linux/perf_event.h2
-rw-r--r--tools/net/ynl/Makefile4
-rw-r--r--tools/net/ynl/pyynl/lib/doc_generator.py9
-rwxr-xr-xtools/net/ynl/ynl-regen.sh2
-rw-r--r--tools/objtool/Makefile41
-rw-r--r--tools/objtool/include/objtool/warn.h4
-rw-r--r--tools/perf/builtin-list.c2
-rw-r--r--tools/perf/util/parse-events.c7
-rw-r--r--tools/testing/cxl/test/cxl_translate.c30
-rw-r--r--tools/testing/selftests/alsa/utimer-test.c1
-rw-r--r--tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c14
-rw-r--r--tools/testing/selftests/drivers/net/hw/lib/py/__init__.py4
-rw-r--r--tools/testing/selftests/drivers/net/hw/toeplitz.c4
-rwxr-xr-xtools/testing/selftests/drivers/net/hw/toeplitz.py6
-rwxr-xr-xtools/testing/selftests/drivers/net/netdevsim/peer.sh59
-rw-r--r--tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc18
-rw-r--r--tools/testing/selftests/hid/Makefile2
-rw-r--r--tools/testing/selftests/hid/tests/conftest.py14
-rw-r--r--tools/testing/selftests/hid/tests/test_multitouch.py61
-rw-r--r--tools/testing/selftests/kvm/x86/amx_test.c144
-rw-r--r--tools/testing/selftests/landlock/common.h1
-rw-r--r--tools/testing/selftests/landlock/fs_test.c34
-rw-r--r--tools/testing/selftests/landlock/net_test.c30
-rw-r--r--tools/testing/selftests/landlock/ptrace_test.c154
-rw-r--r--tools/testing/selftests/landlock/scoped_abstract_unix_test.c23
-rw-r--r--tools/testing/selftests/landlock/scoped_base_variants.h9
-rw-r--r--tools/testing/selftests/mm/gup_longterm.c2
-rw-r--r--tools/testing/selftests/mm/merge.c384
-rw-r--r--tools/testing/selftests/net/Makefile1
-rwxr-xr-xtools/testing/selftests/net/amt.sh7
-rw-r--r--tools/testing/selftests/net/config2
-rwxr-xr-xtools/testing/selftests/net/fib-onlink-tests.sh71
-rwxr-xr-xtools/testing/selftests/net/ipvtap_test.sh168
-rw-r--r--tools/testing/selftests/net/lib/py/__init__.py4
-rw-r--r--tools/testing/selftests/net/mptcp/Makefile1
-rw-r--r--tools/testing/selftests/net/mptcp/mptcp_connect.c3
-rw-r--r--tools/testing/selftests/net/mptcp/mptcp_diag.c3
-rw-r--r--tools/testing/selftests/net/mptcp/mptcp_inq.c5
-rw-r--r--tools/testing/selftests/net/mptcp/mptcp_sockopt.c5
-rwxr-xr-xtools/testing/selftests/net/netfilter/nft_concat_range.sh45
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json47
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/teql.json25
-rw-r--r--tools/testing/selftests/ublk/kublk.c11
-rw-r--r--tools/testing/selftests/vDSO/vgetrandom-chacha.S2
-rw-r--r--tools/testing/selftests/x86/Makefile1
-rw-r--r--tools/testing/vsock/util.c12
-rw-r--r--tools/testing/vsock/util.h2
-rw-r--r--tools/testing/vsock/vsock_test.c149
-rw-r--r--tools/testing/vsock/vsock_test_zerocopy.c74
-rw-r--r--tools/testing/vsock/vsock_test_zerocopy.h3
51 files changed, 1360 insertions, 405 deletions
diff --git a/tools/include/io_uring/mini_liburing.h b/tools/include/io_uring/mini_liburing.h
index 9ccb16074eb5..44be4446feda 100644
--- a/tools/include/io_uring/mini_liburing.h
+++ b/tools/include/io_uring/mini_liburing.h
@@ -6,6 +6,7 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <sys/uio.h>
struct io_sq_ring {
unsigned int *head;
@@ -55,6 +56,7 @@ struct io_uring {
struct io_uring_sq sq;
struct io_uring_cq cq;
int ring_fd;
+ unsigned flags;
};
#if defined(__x86_64) || defined(__i386__)
@@ -72,7 +74,14 @@ static inline int io_uring_mmap(int fd, struct io_uring_params *p,
void *ptr;
int ret;
- sq->ring_sz = p->sq_off.array + p->sq_entries * sizeof(unsigned int);
+ if (p->flags & IORING_SETUP_NO_SQARRAY) {
+ sq->ring_sz = p->cq_off.cqes;
+ sq->ring_sz += p->cq_entries * sizeof(struct io_uring_cqe);
+ } else {
+ sq->ring_sz = p->sq_off.array;
+ sq->ring_sz += p->sq_entries * sizeof(unsigned int);
+ }
+
ptr = mmap(0, sq->ring_sz, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQ_RING);
if (ptr == MAP_FAILED)
@@ -83,7 +92,8 @@ static inline int io_uring_mmap(int fd, struct io_uring_params *p,
sq->kring_entries = ptr + p->sq_off.ring_entries;
sq->kflags = ptr + p->sq_off.flags;
sq->kdropped = ptr + p->sq_off.dropped;
- sq->array = ptr + p->sq_off.array;
+ if (!(p->flags & IORING_SETUP_NO_SQARRAY))
+ sq->array = ptr + p->sq_off.array;
size = p->sq_entries * sizeof(struct io_uring_sqe);
sq->sqes = mmap(0, size, PROT_READ | PROT_WRITE,
@@ -126,28 +136,39 @@ static inline int io_uring_enter(int fd, unsigned int to_submit,
flags, sig, _NSIG / 8);
}
-static inline int io_uring_queue_init(unsigned int entries,
- struct io_uring *ring,
- unsigned int flags)
+static inline int io_uring_queue_init_params(unsigned int entries,
+ struct io_uring *ring,
+ struct io_uring_params *p)
{
- struct io_uring_params p;
int fd, ret;
memset(ring, 0, sizeof(*ring));
- memset(&p, 0, sizeof(p));
- p.flags = flags;
- fd = io_uring_setup(entries, &p);
+ fd = io_uring_setup(entries, p);
if (fd < 0)
return fd;
- ret = io_uring_mmap(fd, &p, &ring->sq, &ring->cq);
- if (!ret)
+ ret = io_uring_mmap(fd, p, &ring->sq, &ring->cq);
+ if (!ret) {
ring->ring_fd = fd;
- else
+ ring->flags = p->flags;
+ } else {
close(fd);
+ }
return ret;
}
+static inline int io_uring_queue_init(unsigned int entries,
+ struct io_uring *ring,
+ unsigned int flags)
+{
+ struct io_uring_params p;
+
+ memset(&p, 0, sizeof(p));
+ p.flags = flags;
+
+ return io_uring_queue_init_params(entries, ring, &p);
+}
+
/* Get a sqe */
static inline struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring)
{
@@ -199,10 +220,18 @@ static inline int io_uring_submit(struct io_uring *ring)
ktail = *sq->ktail;
to_submit = sq->sqe_tail - sq->sqe_head;
- for (submitted = 0; submitted < to_submit; submitted++) {
- read_barrier();
- sq->array[ktail++ & mask] = sq->sqe_head++ & mask;
+
+ if (!(ring->flags & IORING_SETUP_NO_SQARRAY)) {
+ for (submitted = 0; submitted < to_submit; submitted++) {
+ read_barrier();
+ sq->array[ktail++ & mask] = sq->sqe_head++ & mask;
+ }
+ } else {
+ ktail += to_submit;
+ sq->sqe_head += to_submit;
+ submitted = to_submit;
}
+
if (!submitted)
return 0;
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index c44a8fb3e418..72f03153dd32 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -2,7 +2,7 @@
/*
* Performance events:
*
- * Copyright (C) 2008-2009, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright (C) 2008-2009, Linutronix GmbH, Thomas Gleixner <tglx@kernel.org>
* Copyright (C) 2008-2011, Red Hat, Inc., Ingo Molnar
* Copyright (C) 2008-2011, Red Hat, Inc., Peter Zijlstra
*
diff --git a/tools/net/ynl/Makefile b/tools/net/ynl/Makefile
index 7736b492f559..9b692f368be7 100644
--- a/tools/net/ynl/Makefile
+++ b/tools/net/ynl/Makefile
@@ -41,7 +41,7 @@ clean distclean:
rm -rf pyynl.egg-info
rm -rf build
-install: libynl.a lib/*.h
+install: libynl.a lib/*.h ynltool
@echo -e "\tINSTALL libynl.a"
@$(INSTALL) -d $(DESTDIR)$(libdir)
@$(INSTALL) -m 0644 libynl.a $(DESTDIR)$(libdir)/libynl.a
@@ -51,7 +51,7 @@ install: libynl.a lib/*.h
@echo -e "\tINSTALL pyynl"
@pip install --prefix=$(DESTDIR)$(prefix) .
@make -C generated install
- @make -C tests install
+ @make -C ynltool install
run_tests:
@$(MAKE) -C tests run_tests
diff --git a/tools/net/ynl/pyynl/lib/doc_generator.py b/tools/net/ynl/pyynl/lib/doc_generator.py
index 3a16b8eb01ca..8b922d8f89e8 100644
--- a/tools/net/ynl/pyynl/lib/doc_generator.py
+++ b/tools/net/ynl/pyynl/lib/doc_generator.py
@@ -166,13 +166,13 @@ class YnlDocGenerator:
continue
lines.append(self.fmt.rst_paragraph(self.fmt.bold(key), level + 1))
if key in ['request', 'reply']:
- lines.append(self.parse_do_attributes(do_dict[key], level + 1) + "\n")
+ lines.append(self.parse_op_attributes(do_dict[key], level + 1) + "\n")
else:
lines.append(self.fmt.headroom(level + 2) + do_dict[key] + "\n")
return "\n".join(lines)
- def parse_do_attributes(self, attrs: Dict[str, Any], level: int = 0) -> str:
+ def parse_op_attributes(self, attrs: Dict[str, Any], level: int = 0) -> str:
"""Parse 'attributes' section"""
if "attributes" not in attrs:
return ""
@@ -184,7 +184,7 @@ class YnlDocGenerator:
def parse_operations(self, operations: List[Dict[str, Any]], namespace: str) -> str:
"""Parse operations block"""
- preprocessed = ["name", "doc", "title", "do", "dump", "flags"]
+ preprocessed = ["name", "doc", "title", "do", "dump", "flags", "event"]
linkable = ["fixed-header", "attribute-set"]
lines = []
@@ -217,6 +217,9 @@ class YnlDocGenerator:
if "dump" in operation:
lines.append(self.fmt.rst_paragraph(":dump:", 0))
lines.append(self.parse_do(operation["dump"], 0))
+ if "event" in operation:
+ lines.append(self.fmt.rst_paragraph(":event:", 0))
+ lines.append(self.parse_op_attributes(operation["event"], 0))
# New line after fields
lines.append("\n")
diff --git a/tools/net/ynl/ynl-regen.sh b/tools/net/ynl/ynl-regen.sh
index 81b4ecd89100..d9809276db98 100755
--- a/tools/net/ynl/ynl-regen.sh
+++ b/tools/net/ynl/ynl-regen.sh
@@ -21,7 +21,7 @@ files=$(git grep --files-with-matches '^/\* YNL-GEN \(kernel\|uapi\|user\)')
for f in $files; do
# params: 0 1 2 3
# $YAML YNL-GEN kernel $mode
- params=( $(git grep -B1 -h '/\* YNL-GEN' $f | sed 's@/\*\(.*\)\*/@\1@') )
+ params=( $(git grep --no-line-number -B1 -h '/\* YNL-GEN' $f | sed 's@/\*\(.*\)\*/@\1@') )
args=$(sed -n 's@/\* YNL-ARG \(.*\) \*/@\1@p' $f)
if [ $f -nt ${params[0]} -a -z "$force" ]; then
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index ad6e1ec706ce..a40f30232929 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -72,23 +72,40 @@ HOST_OVERRIDES := CC="$(HOSTCC)" LD="$(HOSTLD)" AR="$(HOSTAR)"
#
# To support disassembly, objtool needs libopcodes which is provided
-# with libbdf (binutils-dev or binutils-devel package).
+# with libbfd (binutils-dev or binutils-devel package).
#
-FEATURE_USER = .objtool
-FEATURE_TESTS = libbfd disassembler-init-styled
-FEATURE_DISPLAY =
-include $(srctree)/tools/build/Makefile.feature
-
-ifeq ($(feature-disassembler-init-styled), 1)
- OBJTOOL_CFLAGS += -DDISASM_INIT_STYLED
-endif
+# We check using HOSTCC directly rather than the shared feature framework
+# because objtool is a host tool that links against host libraries.
+#
+# When using shared libraries, -lopcodes is sufficient as dependencies are
+# resolved automatically. With static libraries, we must explicitly link
+# against libopcodes' dependencies: libbfd, libiberty, and sometimes libz.
+# Try each combination and use the first one that succeeds.
+#
+LIBOPCODES_LIBS := $(shell \
+ for libs in "-lopcodes" \
+ "-lopcodes -lbfd" \
+ "-lopcodes -lbfd -liberty" \
+ "-lopcodes -lbfd -liberty -lz"; do \
+ echo 'extern void disassemble_init_for_target(void *);' \
+ 'int main(void) { disassemble_init_for_target(0); return 0; }' | \
+ $(HOSTCC) -xc - -o /dev/null $$libs 2>/dev/null && \
+ echo "$$libs" && break; \
+ done)
+
+# Styled disassembler support requires binutils >= 2.39
+HAVE_DISASM_STYLED := $(shell echo '$(pound)include <dis-asm.h>' | \
+ $(HOSTCC) -E -xc - 2>/dev/null | grep -q disassembler_style && echo y)
BUILD_DISAS := n
-ifeq ($(feature-libbfd),1)
+ifneq ($(LIBOPCODES_LIBS),)
BUILD_DISAS := y
- OBJTOOL_CFLAGS += -DDISAS -DPACKAGE="objtool"
- OBJTOOL_LDFLAGS += -lopcodes
+ OBJTOOL_CFLAGS += -DDISAS -DPACKAGE='"objtool"'
+ OBJTOOL_LDFLAGS += $(LIBOPCODES_LIBS)
+ifeq ($(HAVE_DISASM_STYLED),y)
+ OBJTOOL_CFLAGS += -DDISASM_INIT_STYLED
+endif
endif
export BUILD_DISAS
diff --git a/tools/objtool/include/objtool/warn.h b/tools/objtool/include/objtool/warn.h
index 25ff7942b4d5..2b27b54096b8 100644
--- a/tools/objtool/include/objtool/warn.h
+++ b/tools/objtool/include/objtool/warn.h
@@ -152,8 +152,8 @@ static inline void unindent(int *unused) { indent--; }
if (unlikely(insn->sym && insn->sym->pfunc && \
insn->sym->pfunc->debug_checksum)) { \
char *insn_off = offstr(insn->sec, insn->offset); \
- __dbg("checksum: %s %s %016lx", \
- func->name, insn_off, checksum); \
+ __dbg("checksum: %s %s %016llx", \
+ func->name, insn_off, (unsigned long long)checksum);\
free(insn_off); \
} \
})
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index ac7bd0e41aa1..50f69c2c0d51 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -4,7 +4,7 @@
*
* Builtin list command: list all event types
*
- * Copyright (C) 2009, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright (C) 2009, Linutronix GmbH, Thomas Gleixner <tglx@kernel.org>
* Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
* Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*/
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 6e1185d7be1b..d4647ded340f 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -251,8 +251,11 @@ __add_event(struct list_head *list, int *idx,
event_attr_init(attr);
evsel = evsel__new_idx(attr, *idx);
- if (!evsel)
- goto out_err;
+ if (!evsel) {
+ perf_cpu_map__put(cpus);
+ perf_cpu_map__put(pmu_cpus);
+ return NULL;
+ }
if (name) {
evsel->name = strdup(name);
diff --git a/tools/testing/cxl/test/cxl_translate.c b/tools/testing/cxl/test/cxl_translate.c
index 2200ae21795c..16328b2112b2 100644
--- a/tools/testing/cxl/test/cxl_translate.c
+++ b/tools/testing/cxl/test/cxl_translate.c
@@ -68,6 +68,8 @@ static u64 to_hpa(u64 dpa_offset, int pos, u8 r_eiw, u16 r_eig, u8 hb_ways,
/* Calculate base HPA offset from DPA and position */
hpa_offset = cxl_calculate_hpa_offset(dpa_offset, pos, r_eiw, r_eig);
+ if (hpa_offset == ULLONG_MAX)
+ return ULLONG_MAX;
if (math == XOR_MATH) {
cximsd->nr_maps = hbiw_to_nr_maps[hb_ways];
@@ -258,19 +260,23 @@ static int test_random_params(void)
pos = get_random_u32() % ways;
dpa = get_random_u64() >> 12;
+ reverse_dpa = ULLONG_MAX;
+ reverse_pos = -1;
+
hpa = cxl_calculate_hpa_offset(dpa, pos, eiw, eig);
- reverse_dpa = cxl_calculate_dpa_offset(hpa, eiw, eig);
- reverse_pos = cxl_calculate_position(hpa, eiw, eig);
-
- if (reverse_dpa != dpa || reverse_pos != pos) {
- pr_err("test random iter %d FAIL hpa=%llu, dpa=%llu reverse_dpa=%llu, pos=%d reverse_pos=%d eiw=%u eig=%u\n",
- i, hpa, dpa, reverse_dpa, pos, reverse_pos, eiw,
- eig);
-
- if (failures++ > 10) {
- pr_err("test random too many failures, stop\n");
- break;
- }
+ if (hpa != ULLONG_MAX) {
+ reverse_dpa = cxl_calculate_dpa_offset(hpa, eiw, eig);
+ reverse_pos = cxl_calculate_position(hpa, eiw, eig);
+ if (reverse_dpa == dpa && reverse_pos == pos)
+ continue;
+ }
+
+ pr_err("test random iter %d FAIL hpa=%llu, dpa=%llu reverse_dpa=%llu, pos=%d reverse_pos=%d eiw=%u eig=%u\n",
+ i, hpa, dpa, reverse_dpa, pos, reverse_pos, eiw, eig);
+
+ if (failures++ > 10) {
+ pr_err("test random too many failures, stop\n");
+ break;
}
}
pr_info("..... test random: PASS %d FAIL %d\n", i - failures, failures);
diff --git a/tools/testing/selftests/alsa/utimer-test.c b/tools/testing/selftests/alsa/utimer-test.c
index c45cb226bd8f..d221972cd8fb 100644
--- a/tools/testing/selftests/alsa/utimer-test.c
+++ b/tools/testing/selftests/alsa/utimer-test.c
@@ -141,7 +141,6 @@ TEST_F(timer_f, utimer) {
TEST(wrong_timers_test) {
int timer_dev_fd;
int utimer_fd;
- size_t i;
struct snd_timer_uinfo wrong_timer = {
.resolution = 0,
.id = UTIMER_DEFAULT_ID,
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c b/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
index ee94c281888a..26159e0499c7 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
@@ -47,6 +47,7 @@ void test_xdp_context_test_run(void)
struct test_xdp_context_test_run *skel = NULL;
char data[sizeof(pkt_v4) + sizeof(__u32)];
char bad_ctx[sizeof(struct xdp_md) + 1];
+ char large_data[256];
struct xdp_md ctx_in, ctx_out;
DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts,
.data_in = &data,
@@ -94,9 +95,6 @@ void test_xdp_context_test_run(void)
test_xdp_context_error(prog_fd, opts, 4, sizeof(__u32), sizeof(data),
0, 0, 0);
- /* Meta data must be 255 bytes or smaller */
- test_xdp_context_error(prog_fd, opts, 0, 256, sizeof(data), 0, 0, 0);
-
/* Total size of data must be data_end - data_meta or larger */
test_xdp_context_error(prog_fd, opts, 0, sizeof(__u32),
sizeof(data) + 1, 0, 0, 0);
@@ -116,6 +114,16 @@ void test_xdp_context_test_run(void)
test_xdp_context_error(prog_fd, opts, 0, sizeof(__u32), sizeof(data),
0, 0, 1);
+ /* Meta data must be 216 bytes or smaller (256 - sizeof(struct
+ * xdp_frame)). Test both nearest invalid size and nearest invalid
+ * 4-byte-aligned size, and make sure data_in is large enough that we
+ * actually hit the check on metadata length
+ */
+ opts.data_in = large_data;
+ opts.data_size_in = sizeof(large_data);
+ test_xdp_context_error(prog_fd, opts, 0, 217, sizeof(large_data), 0, 0, 0);
+ test_xdp_context_error(prog_fd, opts, 0, 220, sizeof(large_data), 0, 0, 0);
+
test_xdp_context_test_run__destroy(skel);
}
diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
index 766bfc4ad842..d5d247eca6b7 100644
--- a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
@@ -22,7 +22,7 @@ try:
NlError, RtnlFamily, DevlinkFamily, PSPFamily
from net.lib.py import CmdExitFailure
from net.lib.py import bkg, cmd, bpftool, bpftrace, defer, ethtool, \
- fd_read_timeout, ip, rand_port, wait_port_listen, wait_file
+ fd_read_timeout, ip, rand_port, wait_port_listen, wait_file, tool
from net.lib.py import KsftSkipEx, KsftFailEx, KsftXfailEx
from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \
ksft_setup, ksft_variants, KsftNamedVariant
@@ -37,7 +37,7 @@ try:
"CmdExitFailure",
"bkg", "cmd", "bpftool", "bpftrace", "defer", "ethtool",
"fd_read_timeout", "ip", "rand_port",
- "wait_port_listen", "wait_file",
+ "wait_port_listen", "wait_file", "tool",
"KsftSkipEx", "KsftFailEx", "KsftXfailEx",
"ksft_disruptive", "ksft_exit", "ksft_pr", "ksft_run",
"ksft_setup", "ksft_variants", "KsftNamedVariant",
diff --git a/tools/testing/selftests/drivers/net/hw/toeplitz.c b/tools/testing/selftests/drivers/net/hw/toeplitz.c
index d23b3b0c20a3..285bb17df9c2 100644
--- a/tools/testing/selftests/drivers/net/hw/toeplitz.c
+++ b/tools/testing/selftests/drivers/net/hw/toeplitz.c
@@ -485,8 +485,8 @@ static void parse_rps_bitmap(const char *arg)
bitmap = strtoul(arg, NULL, 0);
- if (bitmap & ~(RPS_MAX_CPUS - 1))
- error(1, 0, "rps bitmap 0x%lx out of bounds 0..%lu",
+ if (bitmap & ~((1UL << RPS_MAX_CPUS) - 1))
+ error(1, 0, "rps bitmap 0x%lx out of bounds, max cpu %lu",
bitmap, RPS_MAX_CPUS - 1);
for (i = 0; i < RPS_MAX_CPUS; i++)
diff --git a/tools/testing/selftests/drivers/net/hw/toeplitz.py b/tools/testing/selftests/drivers/net/hw/toeplitz.py
index d2db5ee9e358..d288c57894f6 100755
--- a/tools/testing/selftests/drivers/net/hw/toeplitz.py
+++ b/tools/testing/selftests/drivers/net/hw/toeplitz.py
@@ -94,12 +94,14 @@ def _configure_rps(cfg, rps_cpus):
mask = 0
for cpu in rps_cpus:
mask |= (1 << cpu)
- mask = hex(mask)[2:]
+
+ mask = hex(mask)
# Set RPS bitmap for all rx queues
for rps_file in glob.glob(f"/sys/class/net/{cfg.ifname}/queues/rx-*/rps_cpus"):
with open(rps_file, "w", encoding="utf-8") as fp:
- fp.write(mask)
+ # sysfs expects hex without '0x' prefix, toeplitz.c needs the prefix
+ fp.write(mask[2:])
return mask
diff --git a/tools/testing/selftests/drivers/net/netdevsim/peer.sh b/tools/testing/selftests/drivers/net/netdevsim/peer.sh
index 7f32b5600925..f4721f7636dd 100755
--- a/tools/testing/selftests/drivers/net/netdevsim/peer.sh
+++ b/tools/testing/selftests/drivers/net/netdevsim/peer.sh
@@ -52,6 +52,39 @@ cleanup_ns()
ip netns del nssv
}
+is_carrier_up()
+{
+ local netns="$1"
+ local nsim_dev="$2"
+
+ test "$(ip netns exec "$netns" \
+ cat /sys/class/net/"$nsim_dev"/carrier 2>/dev/null)" -eq 1
+}
+
+assert_carrier_up()
+{
+ local netns="$1"
+ local nsim_dev="$2"
+
+ if ! is_carrier_up "$netns" "$nsim_dev"; then
+ echo "$nsim_dev's carrier should be UP, but it isn't"
+ cleanup_ns
+ exit 1
+ fi
+}
+
+assert_carrier_down()
+{
+ local netns="$1"
+ local nsim_dev="$2"
+
+ if is_carrier_up "$netns" "$nsim_dev"; then
+ echo "$nsim_dev's carrier should be DOWN, but it isn't"
+ cleanup_ns
+ exit 1
+ fi
+}
+
###
### Code start
###
@@ -113,6 +146,32 @@ if [ $? -eq 0 ]; then
exit 1
fi
+# netdevsim carrier state consistency checking
+assert_carrier_up nssv "$NSIM_DEV_1_NAME"
+assert_carrier_up nscl "$NSIM_DEV_2_NAME"
+
+echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX" > "$NSIM_DEV_SYS_UNLINK"
+
+assert_carrier_down nssv "$NSIM_DEV_1_NAME"
+assert_carrier_down nscl "$NSIM_DEV_2_NAME"
+
+ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" down
+ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" up
+
+assert_carrier_down nssv "$NSIM_DEV_1_NAME"
+assert_carrier_down nscl "$NSIM_DEV_2_NAME"
+
+echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX $NSIM_DEV_2_FD:$NSIM_DEV_2_IFIDX" > $NSIM_DEV_SYS_LINK
+
+assert_carrier_up nssv "$NSIM_DEV_1_NAME"
+assert_carrier_up nscl "$NSIM_DEV_2_NAME"
+
+ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" down
+ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" up
+
+assert_carrier_up nssv "$NSIM_DEV_1_NAME"
+assert_carrier_up nscl "$NSIM_DEV_2_NAME"
+
# send/recv packets
tmp_file=$(mktemp)
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc b/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc
index 7daf7292209e..a2c42e13f614 100644
--- a/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc
+++ b/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc
@@ -89,6 +89,7 @@ test_buffer() {
# The id must be four bytes, test that 3 bytes fails a write
if echo -n abc > ./trace_marker_raw ; then
echo "Too small of write expected to fail but did not"
+ echo ${ORIG} > buffer_size_kb
exit_fail
fi
@@ -99,9 +100,24 @@ test_buffer() {
if write_buffer 0xdeadbeef $size ; then
echo "Too big of write expected to fail but did not"
+ echo ${ORIG} > buffer_size_kb
exit_fail
fi
}
+ORIG=`cat buffer_size_kb`
+
+# test_multiple_writes test needs at least 12KB buffer
+NEW_SIZE=12
+
+if [ ${ORIG} -lt ${NEW_SIZE} ]; then
+ echo ${NEW_SIZE} > buffer_size_kb
+fi
+
test_buffer
-test_multiple_writes
+if ! test_multiple_writes; then
+ echo ${ORIG} > buffer_size_kb
+ exit_fail
+fi
+
+echo ${ORIG} > buffer_size_kb
diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
index 2839d2612ce3..50ec9e0406ab 100644
--- a/tools/testing/selftests/hid/Makefile
+++ b/tools/testing/selftests/hid/Makefile
@@ -184,6 +184,8 @@ MENDIAN=$(if $(IS_LITTLE_ENDIAN),-mlittle-endian,-mbig-endian)
CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG))
BPF_CFLAGS = -g -Werror -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN) \
+ -Wno-microsoft-anon-tag \
+ -fms-extensions \
-I$(INCLUDE_DIR)
CLANG_CFLAGS = $(CLANG_SYS_INCLUDES) \
diff --git a/tools/testing/selftests/hid/tests/conftest.py b/tools/testing/selftests/hid/tests/conftest.py
index 1361ec981db6..985a535324b2 100644
--- a/tools/testing/selftests/hid/tests/conftest.py
+++ b/tools/testing/selftests/hid/tests/conftest.py
@@ -5,6 +5,7 @@
# Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com>
# Copyright (c) 2017 Red Hat, Inc.
+from packaging.version import Version
import platform
import pytest
import re
@@ -14,6 +15,19 @@ from .base import HIDTestUdevRule
from pathlib import Path
+@pytest.fixture(autouse=True)
+def hidtools_version_check():
+ HIDTOOLS_VERSION = "0.12"
+ try:
+ import hidtools
+
+ version = hidtools.__version__ # type: ignore
+ if Version(version) < Version(HIDTOOLS_VERSION):
+ pytest.skip(reason=f"have hidtools {version}, require >={HIDTOOLS_VERSION}")
+ except Exception:
+ pytest.skip(reason=f"hidtools >={HIDTOOLS_VERSION} required")
+
+
# See the comment in HIDTestUdevRule, this doesn't set up but it will clean
# up once the last test exited.
@pytest.fixture(autouse=True, scope="session")
diff --git a/tools/testing/selftests/hid/tests/test_multitouch.py b/tools/testing/selftests/hid/tests/test_multitouch.py
index ece0ba8e7d34..fa4fb2054bd4 100644
--- a/tools/testing/selftests/hid/tests/test_multitouch.py
+++ b/tools/testing/selftests/hid/tests/test_multitouch.py
@@ -9,6 +9,7 @@
from . import base
from hidtools.hut import HUT
from hidtools.util import BusType
+import enum
import libevdev
import logging
import pytest
@@ -232,11 +233,17 @@ class Digitizer(base.UHIDTestDevice):
return 0
+class HIDButtonType(enum.IntEnum):
+ CLICKPAD = 0
+ PRESSUREPAD = 1
+ DISCRETE_BUTTONS = 2
+
+
class PTP(Digitizer):
def __init__(
self,
name,
- type="Click Pad",
+ buttontype=HIDButtonType.CLICKPAD,
rdesc_str=None,
rdesc=None,
application="Touch Pad",
@@ -244,11 +251,8 @@ class PTP(Digitizer):
max_contacts=None,
input_info=None,
):
- self.type = type.lower().replace(" ", "")
- if self.type == "clickpad":
- self.buttontype = 0
- else: # pressurepad
- self.buttontype = 1
+ self.buttontype = buttontype
+
self.clickpad_state = False
self.left_state = False
self.right_state = False
@@ -975,15 +979,36 @@ class BaseTest:
assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_ORIENTATION, 90) in events
class TestPTP(TestWin8Multitouch):
+ def test_buttontype(self):
+ """Check for the right ButtonType."""
+ uhdev = self.uhdev
+ assert uhdev is not None
+ evdev = uhdev.get_evdev()
+
+ # If libevdev.so is not yet compiled with INPUT_PROP_PRESSUREPAD
+ # python-libevdev won't have it either, let's fake it
+ if not getattr(libevdev, "INPUT_PROP_PRESSUREPAD", None):
+ prop = libevdev.InputProperty(name="INPUT_PROP_PRESSUREPAD", value=0x7)
+ libevdev.INPUT_PROP_PRESSUREPAD = prop
+ libevdev.props.append(prop)
+
+ if uhdev.buttontype == HIDButtonType.CLICKPAD:
+ assert libevdev.INPUT_PROP_BUTTONPAD in evdev.properties
+ elif uhdev.buttontype == HIDButtonType.PRESSUREPAD:
+ assert libevdev.INPUT_PROP_PRESSUREPAD in evdev.properties
+ else:
+ assert libevdev.INPUT_PROP_PRESSUREPAD not in evdev.properties
+ assert libevdev.INPUT_PROP_BUTTONPAD not in evdev.properties
+
def test_ptp_buttons(self):
"""check for button reliability.
- There are 2 types of touchpads: the click pads and the pressure pads.
- Each should reliably report the BTN_LEFT events.
+ There are 3 types of touchpads: click pads + pressure pads and
+ those with discrete buttons. Each should reliably report the BTN_LEFT events.
"""
uhdev = self.uhdev
evdev = uhdev.get_evdev()
- if uhdev.type == "clickpad":
+ if uhdev.buttontype in [HIDButtonType.CLICKPAD, HIDButtonType.PRESSUREPAD]:
r = uhdev.event(click=True)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
@@ -995,7 +1020,7 @@ class BaseTest:
self.debug_reports(r, uhdev, events)
assert libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0) in events
assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0
- else:
+ elif uhdev.buttontype == HIDButtonType.DISCRETE_BUTTONS:
r = uhdev.event(left=True)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
@@ -1918,7 +1943,7 @@ class Testdell_044e_1220(BaseTest.TestPTP):
def create_device(self):
return PTP(
"uhid test dell_044e_1220",
- type="pressurepad",
+ buttontype=HIDButtonType.DISCRETE_BUTTONS,
rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 75 01 95 03 81 02 95 05 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 09 38 95 01 81 06 05 0c 0a 38 02 81 06 c0 c0 05 0d 09 05 a1 01 85 08 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 af 04 75 10 55 0e 65 11 09 30 35 00 46 e8 03 95 01 81 02 26 7b 02 46 12 02 09 31 81 02 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 05 0d 09 56 81 02 09 54 25 05 95 01 75 08 81 02 05 09 19 01 29 03 25 01 75 01 95 03 81 02 95 05 81 03 05 0d 85 09 09 55 75 08 95 01 25 05 b1 02 06 00 ff 85 0a 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 01 ff 09 01 a1 01 85 03 09 01 15 00 26 ff 00 95 1b 81 02 85 04 09 02 95 50 81 02 85 05 09 03 95 07 b1 02 85 06 09 04 81 02 c0 06 02 ff 09 01 a1 01 85 07 09 02 95 86 75 08 b1 02 c0 05 0d 09 0e a1 01 85 0b 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 0c 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0",
)
@@ -2018,7 +2043,7 @@ class Testelan_04f3_313a(BaseTest.TestPTP):
def create_device(self):
return PTP(
"uhid test elan_04f3_313a",
- type="touchpad",
+ buttontype=HIDButtonType.DISCRETE_BUTTONS,
input_info=(BusType.I2C, 0x04F3, 0x313A),
rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 75 01 95 03 81 02 95 05 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 75 08 95 05 81 03 c0 06 00 ff 09 01 85 0e 09 c5 15 00 26 ff 00 75 08 95 04 b1 02 85 0a 09 c6 15 00 26 ff 00 75 08 95 04 b1 02 c0 06 00 ff 09 01 a1 01 85 5c 09 01 95 0b 75 08 81 06 85 0d 09 c5 15 00 26 ff 00 75 08 95 04 b1 02 85 0c 09 c6 96 80 03 75 08 b1 02 85 0b 09 c7 95 82 75 08 b1 02 c0 05 0d 09 05 a1 01 85 04 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 05 09 09 02 09 03 15 00 25 01 75 01 95 02 81 02 05 0d 95 01 75 04 25 0f 09 51 81 02 05 01 15 00 26 d7 0e 75 10 55 0d 65 11 09 30 35 00 46 44 2f 95 01 81 02 46 12 16 26 eb 06 26 eb 06 09 31 81 02 05 0d 15 00 25 64 95 03 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 7f 95 01 75 08 81 02 25 01 75 01 95 08 81 03 09 c5 75 08 95 02 81 03 05 0d 85 02 09 55 09 59 75 04 95 02 25 0f b1 02 85 07 09 60 75 01 95 01 15 00 25 01 b1 02 95 0f b1 03 06 00 ff 06 00 ff 85 06 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 0e a1 01 85 03 09 22 a1 00 09 52 15 00 25 0a 75 10 95 01 b1 02 c0 09 22 a1 00 85 05 09 57 09 58 75 01 95 02 25 01 b1 02 95 0e b1 03 c0 c0 05 01 09 02 a1 01 85 2a 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 75 01 95 03 81 02 95 05 81 03 05 01 09 30 09 31 15 81 25 7f 35 81 45 7f 55 00 65 13 75 08 95 02 81 06 75 08 95 05 81 03 c0 c0",
)
@@ -2058,6 +2083,16 @@ class Testite_06cb_2968(BaseTest.TestPTP):
)
+class Testven_0488_108c(BaseTest.TestPTP):
+ def create_device(self):
+ return PTP(
+ "uhid test ven_0488_108c",
+ rdesc="05 01 09 02 a1 01 85 06 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05 81 03 05 01 09 30 09 31 09 38 15 81 25 7f 75 08 95 03 81 06 c0 c0 05 0d 09 05 a1 01 85 01 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 81 03 05 01 15 00 26 ba 0d 75 10 55 0e 65 11 09 30 35 00 46 d0 05 95 01 81 02 26 d0 06 46 bb 02 09 31 81 02 05 0d 95 01 75 10 26 ff 7f 46 ff 7f 09 30 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 81 03 05 01 15 00 26 ba 0d 75 10 55 0e 65 11 09 30 35 00 46 d0 05 95 01 81 02 26 d0 06 46 bb 02 09 31 81 02 05 0d 95 01 75 10 26 ff 7f 46 ff 7f 09 30 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 81 03 05 01 15 00 26 ba 0d 75 10 55 0e 65 11 09 30 35 00 46 d0 05 95 01 81 02 26 d0 06 46 bb 02 09 31 81 02 05 0d 95 01 75 10 26 ff 7f 46 ff 7f 09 30 81 02 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 05 0d 09 56 81 02 09 54 25 05 95 01 75 08 81 02 05 09 09 01 25 01 75 01 95 01 81 02 95 07 81 03 05 0d 85 02 09 55 75 08 95 01 25 05 b1 02 09 59 b1 02 06 00 ff 85 03 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 05 0e 09 01 a1 02 85 13 09 23 15 00 25 64 75 08 95 01 b1 02 c0 c0 05 0d 09 0e a1 01 85 04 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 05 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0 06 01 ff 09 02 a1 01 09 00 85 07 15 00 26 ff 00 75 08 96 12 02 b1 02 c0 06 00 ff 09 01 a1 01 85 0d 15 00 26 ff 00 75 08 95 11 09 01 81 02 09 01 91 02 c0 05 0e 09 01 a1 01 85 11 09 35 15 00 26 ff 00 75 08 95 17 b1 02 c0 06 81 ff 09 01 a1 01 09 20 85 17 15 00 26 ff 00 75 08 95 3f 09 01 81 02 09 01 91 02 c0",
+ input_info=(0x18, 0x0488, 0x108C),
+ buttontype=HIDButtonType.PRESSUREPAD,
+ )
+
+
class Testn_trig_1b96_0c01(BaseTest.TestWin8Multitouch):
def create_device(self):
return Digitizer(
@@ -2110,7 +2145,7 @@ class Testsipodev_0603_0002(BaseTest.TestPTP):
def create_device(self):
return PTP(
"uhid test sipodev_0603_0002",
- type="clickpad",
+ buttontype=HIDButtonType.CLICKPAD,
rdesc="05 01 09 02 a1 01 85 03 09 01 a1 00 05 09 19 01 29 02 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 80 25 7f 75 08 95 02 81 06 c0 c0 05 0d 09 05 a1 01 85 04 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 75 01 95 02 81 03 95 01 75 04 25 05 09 51 81 02 05 01 15 00 26 44 0a 75 0c 55 0e 65 11 09 30 35 00 46 ac 03 95 01 81 02 46 fe 01 26 34 05 75 0c 09 31 81 02 05 0d c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 0a 95 01 75 04 81 02 75 01 95 03 81 03 05 09 09 01 25 01 75 01 95 01 81 02 05 0d 85 0a 09 55 09 59 75 04 95 02 25 0f b1 02 85 0b 09 60 75 01 95 01 15 00 25 01 b1 02 95 07 b1 03 85 09 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 0e a1 01 85 06 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 07 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0 05 01 09 0c a1 01 85 08 15 00 25 01 09 c6 75 01 95 01 81 06 75 07 81 03 c0 05 01 09 80 a1 01 85 01 15 00 25 01 75 01 0a 81 00 0a 82 00 0a 83 00 95 03 81 06 95 05 81 01 c0 06 0c 00 09 01 a1 01 85 02 25 01 15 00 75 01 0a b5 00 0a b6 00 0a b7 00 0a cd 00 0a e2 00 0a a2 00 0a e9 00 0a ea 00 95 08 81 02 0a 83 01 0a 6f 00 0a 70 00 0a 88 01 0a 8a 01 0a 92 01 0a a8 02 0a 24 02 95 08 81 02 0a 21 02 0a 23 02 0a 96 01 0a 25 02 0a 26 02 0a 27 02 0a 23 02 0a b1 02 95 08 81 02 c0 06 00 ff 09 01 a1 01 85 05 15 00 26 ff 00 19 01 29 02 75 08 95 05 b1 02 c0",
)
diff --git a/tools/testing/selftests/kvm/x86/amx_test.c b/tools/testing/selftests/kvm/x86/amx_test.c
index f4ce5a185a7d..37b166260ee3 100644
--- a/tools/testing/selftests/kvm/x86/amx_test.c
+++ b/tools/testing/selftests/kvm/x86/amx_test.c
@@ -69,6 +69,12 @@ static inline void __tileloadd(void *tile)
: : "a"(tile), "d"(0));
}
+static inline int tileloadd_safe(void *tile)
+{
+ return kvm_asm_safe(".byte 0xc4,0xe2,0x7b,0x4b,0x04,0x10",
+ "a"(tile), "d"(0));
+}
+
static inline void __tilerelease(void)
{
asm volatile(".byte 0xc4, 0xe2, 0x78, 0x49, 0xc0" ::);
@@ -124,27 +130,52 @@ static void set_tilecfg(struct tile_config *cfg)
}
}
+enum {
+ /* Retrieve TMM0 from guest, stash it for TEST_RESTORE_TILEDATA */
+ TEST_SAVE_TILEDATA = 1,
+
+ /* Check TMM0 against tiledata */
+ TEST_COMPARE_TILEDATA = 2,
+
+ /* Restore TMM0 from earlier save */
+ TEST_RESTORE_TILEDATA = 4,
+
+ /* Full VM save/restore */
+ TEST_SAVE_RESTORE = 8,
+};
+
static void __attribute__((__flatten__)) guest_code(struct tile_config *amx_cfg,
struct tile_data *tiledata,
struct xstate *xstate)
{
+ int vector;
+
GUEST_ASSERT(this_cpu_has(X86_FEATURE_XSAVE) &&
this_cpu_has(X86_FEATURE_OSXSAVE));
check_xtile_info();
- GUEST_SYNC(1);
+ GUEST_SYNC(TEST_SAVE_RESTORE);
/* xfd=0, enable amx */
wrmsr(MSR_IA32_XFD, 0);
- GUEST_SYNC(2);
+ GUEST_SYNC(TEST_SAVE_RESTORE);
GUEST_ASSERT(rdmsr(MSR_IA32_XFD) == 0);
set_tilecfg(amx_cfg);
__ldtilecfg(amx_cfg);
- GUEST_SYNC(3);
+ GUEST_SYNC(TEST_SAVE_RESTORE);
/* Check save/restore when trap to userspace */
__tileloadd(tiledata);
- GUEST_SYNC(4);
+ GUEST_SYNC(TEST_SAVE_TILEDATA | TEST_COMPARE_TILEDATA | TEST_SAVE_RESTORE);
+
+ /* xfd=0x40000, disable amx tiledata */
+ wrmsr(MSR_IA32_XFD, XFEATURE_MASK_XTILE_DATA);
+
+ /* host tries setting tiledata while guest XFD is set */
+ GUEST_SYNC(TEST_RESTORE_TILEDATA);
+ GUEST_SYNC(TEST_SAVE_RESTORE);
+
+ wrmsr(MSR_IA32_XFD, 0);
__tilerelease();
- GUEST_SYNC(5);
+ GUEST_SYNC(TEST_SAVE_RESTORE);
/*
* After XSAVEC, XTILEDATA is cleared in the xstate_bv but is set in
* the xcomp_bv.
@@ -154,6 +185,8 @@ static void __attribute__((__flatten__)) guest_code(struct tile_config *amx_cfg,
GUEST_ASSERT(!(xstate->header.xstate_bv & XFEATURE_MASK_XTILE_DATA));
GUEST_ASSERT(xstate->header.xcomp_bv & XFEATURE_MASK_XTILE_DATA);
+ /* #NM test */
+
/* xfd=0x40000, disable amx tiledata */
wrmsr(MSR_IA32_XFD, XFEATURE_MASK_XTILE_DATA);
@@ -166,32 +199,33 @@ static void __attribute__((__flatten__)) guest_code(struct tile_config *amx_cfg,
GUEST_ASSERT(!(xstate->header.xstate_bv & XFEATURE_MASK_XTILE_DATA));
GUEST_ASSERT((xstate->header.xcomp_bv & XFEATURE_MASK_XTILE_DATA));
- GUEST_SYNC(6);
+ GUEST_SYNC(TEST_SAVE_RESTORE);
GUEST_ASSERT(rdmsr(MSR_IA32_XFD) == XFEATURE_MASK_XTILE_DATA);
set_tilecfg(amx_cfg);
__ldtilecfg(amx_cfg);
- /* Trigger #NM exception */
- __tileloadd(tiledata);
- GUEST_SYNC(10);
- GUEST_DONE();
-}
+ /* Trigger #NM exception */
+ vector = tileloadd_safe(tiledata);
+ __GUEST_ASSERT(vector == NM_VECTOR,
+ "Wanted #NM on tileloadd with XFD[18]=1, got %s",
+ ex_str(vector));
-void guest_nm_handler(struct ex_regs *regs)
-{
- /* Check if #NM is triggered by XFEATURE_MASK_XTILE_DATA */
- GUEST_SYNC(7);
GUEST_ASSERT(!(get_cr0() & X86_CR0_TS));
GUEST_ASSERT(rdmsr(MSR_IA32_XFD_ERR) == XFEATURE_MASK_XTILE_DATA);
GUEST_ASSERT(rdmsr(MSR_IA32_XFD) == XFEATURE_MASK_XTILE_DATA);
- GUEST_SYNC(8);
+ GUEST_SYNC(TEST_SAVE_RESTORE);
GUEST_ASSERT(rdmsr(MSR_IA32_XFD_ERR) == XFEATURE_MASK_XTILE_DATA);
GUEST_ASSERT(rdmsr(MSR_IA32_XFD) == XFEATURE_MASK_XTILE_DATA);
/* Clear xfd_err */
wrmsr(MSR_IA32_XFD_ERR, 0);
/* xfd=0, enable amx */
wrmsr(MSR_IA32_XFD, 0);
- GUEST_SYNC(9);
+ GUEST_SYNC(TEST_SAVE_RESTORE);
+
+ __tileloadd(tiledata);
+ GUEST_SYNC(TEST_COMPARE_TILEDATA | TEST_SAVE_RESTORE);
+
+ GUEST_DONE();
}
int main(int argc, char *argv[])
@@ -200,10 +234,10 @@ int main(int argc, char *argv[])
struct kvm_vcpu *vcpu;
struct kvm_vm *vm;
struct kvm_x86_state *state;
+ struct kvm_x86_state *tile_state = NULL;
int xsave_restore_size;
vm_vaddr_t amx_cfg, tiledata, xstate;
struct ucall uc;
- u32 amx_offset;
int ret;
/*
@@ -228,9 +262,6 @@ int main(int argc, char *argv[])
vcpu_regs_get(vcpu, &regs1);
- /* Register #NM handler */
- vm_install_exception_handler(vm, NM_VECTOR, guest_nm_handler);
-
/* amx cfg for guest_code */
amx_cfg = vm_vaddr_alloc_page(vm);
memset(addr_gva2hva(vm, amx_cfg), 0x0, getpagesize());
@@ -244,6 +275,7 @@ int main(int argc, char *argv[])
memset(addr_gva2hva(vm, xstate), 0, PAGE_SIZE * DIV_ROUND_UP(XSAVE_SIZE, PAGE_SIZE));
vcpu_args_set(vcpu, 3, amx_cfg, tiledata, xstate);
+ int iter = 0;
for (;;) {
vcpu_run(vcpu);
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
@@ -253,37 +285,47 @@ int main(int argc, char *argv[])
REPORT_GUEST_ASSERT(uc);
/* NOT REACHED */
case UCALL_SYNC:
- switch (uc.args[1]) {
- case 1:
- case 2:
- case 3:
- case 5:
- case 6:
- case 7:
- case 8:
- fprintf(stderr, "GUEST_SYNC(%ld)\n", uc.args[1]);
- break;
- case 4:
- case 10:
- fprintf(stderr,
- "GUEST_SYNC(%ld), check save/restore status\n", uc.args[1]);
+ ++iter;
+ if (uc.args[1] & TEST_SAVE_TILEDATA) {
+ fprintf(stderr, "GUEST_SYNC #%d, save tiledata\n", iter);
+ tile_state = vcpu_save_state(vcpu);
+ }
+ if (uc.args[1] & TEST_COMPARE_TILEDATA) {
+ fprintf(stderr, "GUEST_SYNC #%d, check TMM0 contents\n", iter);
/* Compacted mode, get amx offset by xsave area
* size subtract 8K amx size.
*/
- amx_offset = xsave_restore_size - NUM_TILES*TILE_SIZE;
- state = vcpu_save_state(vcpu);
- void *amx_start = (void *)state->xsave + amx_offset;
+ u32 amx_offset = xsave_restore_size - NUM_TILES*TILE_SIZE;
+ void *amx_start = (void *)tile_state->xsave + amx_offset;
void *tiles_data = (void *)addr_gva2hva(vm, tiledata);
/* Only check TMM0 register, 1 tile */
ret = memcmp(amx_start, tiles_data, TILE_SIZE);
TEST_ASSERT(ret == 0, "memcmp failed, ret=%d", ret);
+ }
+ if (uc.args[1] & TEST_RESTORE_TILEDATA) {
+ fprintf(stderr, "GUEST_SYNC #%d, before KVM_SET_XSAVE\n", iter);
+ vcpu_xsave_set(vcpu, tile_state->xsave);
+ fprintf(stderr, "GUEST_SYNC #%d, after KVM_SET_XSAVE\n", iter);
+ }
+ if (uc.args[1] & TEST_SAVE_RESTORE) {
+ fprintf(stderr, "GUEST_SYNC #%d, save/restore VM state\n", iter);
+ state = vcpu_save_state(vcpu);
+ memset(&regs1, 0, sizeof(regs1));
+ vcpu_regs_get(vcpu, &regs1);
+
+ kvm_vm_release(vm);
+
+ /* Restore state in a new VM. */
+ vcpu = vm_recreate_with_one_vcpu(vm);
+ vcpu_load_state(vcpu, state);
kvm_x86_state_cleanup(state);
- break;
- case 9:
- fprintf(stderr,
- "GUEST_SYNC(%ld), #NM exception and enable amx\n", uc.args[1]);
- break;
+
+ memset(&regs2, 0, sizeof(regs2));
+ vcpu_regs_get(vcpu, &regs2);
+ TEST_ASSERT(!memcmp(&regs1, &regs2, sizeof(regs2)),
+ "Unexpected register values after vcpu_load_state; rdi: %lx rsi: %lx",
+ (ulong) regs2.rdi, (ulong) regs2.rsi);
}
break;
case UCALL_DONE:
@@ -293,22 +335,6 @@ int main(int argc, char *argv[])
TEST_FAIL("Unknown ucall %lu", uc.cmd);
}
- state = vcpu_save_state(vcpu);
- memset(&regs1, 0, sizeof(regs1));
- vcpu_regs_get(vcpu, &regs1);
-
- kvm_vm_release(vm);
-
- /* Restore state in a new VM. */
- vcpu = vm_recreate_with_one_vcpu(vm);
- vcpu_load_state(vcpu, state);
- kvm_x86_state_cleanup(state);
-
- memset(&regs2, 0, sizeof(regs2));
- vcpu_regs_get(vcpu, &regs2);
- TEST_ASSERT(!memcmp(&regs1, &regs2, sizeof(regs2)),
- "Unexpected register values after vcpu_load_state; rdi: %lx rsi: %lx",
- (ulong) regs2.rdi, (ulong) regs2.rsi);
}
done:
kvm_vm_free(vm);
diff --git a/tools/testing/selftests/landlock/common.h b/tools/testing/selftests/landlock/common.h
index 230b75f6015b..90551650299c 100644
--- a/tools/testing/selftests/landlock/common.h
+++ b/tools/testing/selftests/landlock/common.h
@@ -237,6 +237,7 @@ struct service_fixture {
struct sockaddr_un unix_addr;
socklen_t unix_addr_len;
};
+ struct sockaddr_storage _largest;
};
};
diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c
index eee814e09dd7..968a91c927a4 100644
--- a/tools/testing/selftests/landlock/fs_test.c
+++ b/tools/testing/selftests/landlock/fs_test.c
@@ -4362,22 +4362,24 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)
{
const char *const path = file1_s1d1;
int srv_fd, cli_fd, ruleset_fd;
- socklen_t size;
- struct sockaddr_un srv_un, cli_un;
+ struct sockaddr_un srv_un = {
+ .sun_family = AF_UNIX,
+ };
+ struct sockaddr_un cli_un = {
+ .sun_family = AF_UNIX,
+ };
const struct landlock_ruleset_attr attr = {
.handled_access_fs = LANDLOCK_ACCESS_FS_IOCTL_DEV,
};
/* Sets up a server */
- srv_un.sun_family = AF_UNIX;
- strncpy(srv_un.sun_path, path, sizeof(srv_un.sun_path));
-
ASSERT_EQ(0, unlink(path));
srv_fd = socket(AF_UNIX, SOCK_STREAM, 0);
ASSERT_LE(0, srv_fd);
- size = offsetof(struct sockaddr_un, sun_path) + strlen(srv_un.sun_path);
- ASSERT_EQ(0, bind(srv_fd, (struct sockaddr *)&srv_un, size));
+ strncpy(srv_un.sun_path, path, sizeof(srv_un.sun_path));
+ ASSERT_EQ(0, bind(srv_fd, (struct sockaddr *)&srv_un, sizeof(srv_un)));
+
ASSERT_EQ(0, listen(srv_fd, 10 /* qlen */));
/* Enables Landlock. */
@@ -4387,24 +4389,18 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)
ASSERT_EQ(0, close(ruleset_fd));
/* Sets up a client connection to it */
- cli_un.sun_family = AF_UNIX;
cli_fd = socket(AF_UNIX, SOCK_STREAM, 0);
ASSERT_LE(0, cli_fd);
- size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path);
- ASSERT_EQ(0, bind(cli_fd, (struct sockaddr *)&cli_un, size));
-
- bzero(&cli_un, sizeof(cli_un));
- cli_un.sun_family = AF_UNIX;
strncpy(cli_un.sun_path, path, sizeof(cli_un.sun_path));
- size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path);
-
- ASSERT_EQ(0, connect(cli_fd, (struct sockaddr *)&cli_un, size));
+ ASSERT_EQ(0,
+ connect(cli_fd, (struct sockaddr *)&cli_un, sizeof(cli_un)));
/* FIONREAD and other IOCTLs should not be forbidden. */
EXPECT_EQ(0, test_fionread_ioctl(cli_fd));
- ASSERT_EQ(0, close(cli_fd));
+ EXPECT_EQ(0, close(cli_fd));
+ EXPECT_EQ(0, close(srv_fd));
}
/* clang-format off */
@@ -7074,8 +7070,8 @@ static int matches_log_fs_extra(struct __test_metadata *const _metadata,
return -E2BIG;
/*
- * It is assume that absolute_path does not contain control characters nor
- * spaces, see audit_string_contains_control().
+ * It is assumed that absolute_path does not contain control
+ * characters nor spaces, see audit_string_contains_control().
*/
absolute_path = realpath(path, NULL);
if (!absolute_path)
diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c
index 2a45208551e6..b34b139b3f89 100644
--- a/tools/testing/selftests/landlock/net_test.c
+++ b/tools/testing/selftests/landlock/net_test.c
@@ -121,6 +121,10 @@ static socklen_t get_addrlen(const struct service_fixture *const srv,
{
switch (srv->protocol.domain) {
case AF_UNSPEC:
+ if (minimal)
+ return sizeof(sa_family_t);
+ return sizeof(struct sockaddr_storage);
+
case AF_INET:
return sizeof(srv->ipv4_addr);
@@ -758,6 +762,11 @@ TEST_F(protocol, bind_unspec)
bind_fd = socket_variant(&self->srv0);
ASSERT_LE(0, bind_fd);
+ /* Tries to bind with too small addrlen. */
+ EXPECT_EQ(-EINVAL, bind_variant_addrlen(
+ bind_fd, &self->unspec_any0,
+ get_addrlen(&self->unspec_any0, true) - 1));
+
/* Allowed bind on AF_UNSPEC/INADDR_ANY. */
ret = bind_variant(bind_fd, &self->unspec_any0);
if (variant->prot.domain == AF_INET) {
@@ -766,6 +775,8 @@ TEST_F(protocol, bind_unspec)
TH_LOG("Failed to bind to unspec/any socket: %s",
strerror(errno));
}
+ } else if (variant->prot.domain == AF_INET6) {
+ EXPECT_EQ(-EAFNOSUPPORT, ret);
} else {
EXPECT_EQ(-EINVAL, ret);
}
@@ -792,6 +803,8 @@ TEST_F(protocol, bind_unspec)
} else {
EXPECT_EQ(0, ret);
}
+ } else if (variant->prot.domain == AF_INET6) {
+ EXPECT_EQ(-EAFNOSUPPORT, ret);
} else {
EXPECT_EQ(-EINVAL, ret);
}
@@ -801,7 +814,8 @@ TEST_F(protocol, bind_unspec)
bind_fd = socket_variant(&self->srv0);
ASSERT_LE(0, bind_fd);
ret = bind_variant(bind_fd, &self->unspec_srv0);
- if (variant->prot.domain == AF_INET) {
+ if (variant->prot.domain == AF_INET ||
+ variant->prot.domain == AF_INET6) {
EXPECT_EQ(-EAFNOSUPPORT, ret);
} else {
EXPECT_EQ(-EINVAL, ret)
@@ -892,7 +906,19 @@ TEST_F(protocol, connect_unspec)
EXPECT_EQ(0, close(ruleset_fd));
}
- ret = connect_variant(connect_fd, &self->unspec_any0);
+ /* Try to re-disconnect with a truncated address struct. */
+ EXPECT_EQ(-EINVAL,
+ connect_variant_addrlen(
+ connect_fd, &self->unspec_any0,
+ get_addrlen(&self->unspec_any0, true) - 1));
+
+ /*
+ * Re-disconnect, with a minimal sockaddr struct (just a
+ * bare af_family=AF_UNSPEC field).
+ */
+ ret = connect_variant_addrlen(connect_fd, &self->unspec_any0,
+ get_addrlen(&self->unspec_any0,
+ true));
if (self->srv0.protocol.domain == AF_UNIX &&
self->srv0.protocol.type == SOCK_STREAM) {
EXPECT_EQ(-EINVAL, ret);
diff --git a/tools/testing/selftests/landlock/ptrace_test.c b/tools/testing/selftests/landlock/ptrace_test.c
index 4e356334ecb7..4f64c90583cd 100644
--- a/tools/testing/selftests/landlock/ptrace_test.c
+++ b/tools/testing/selftests/landlock/ptrace_test.c
@@ -86,16 +86,9 @@ static int get_yama_ptrace_scope(void)
}
/* clang-format off */
-FIXTURE(hierarchy) {};
+FIXTURE(scoped_domains) {};
/* clang-format on */
-FIXTURE_VARIANT(hierarchy)
-{
- const bool domain_both;
- const bool domain_parent;
- const bool domain_child;
-};
-
/*
* Test multiple tracing combinations between a parent process P1 and a child
* process P2.
@@ -104,155 +97,18 @@ FIXTURE_VARIANT(hierarchy)
* restriction is enforced in addition to any Landlock check, which means that
* all P2 requests to trace P1 would be denied.
*/
+#include "scoped_base_variants.h"
-/*
- * No domain
- *
- * P1-. P1 -> P2 : allow
- * \ P2 -> P1 : allow
- * 'P2
- */
-/* clang-format off */
-FIXTURE_VARIANT_ADD(hierarchy, allow_without_domain) {
- /* clang-format on */
- .domain_both = false,
- .domain_parent = false,
- .domain_child = false,
-};
-
-/*
- * Child domain
- *
- * P1--. P1 -> P2 : allow
- * \ P2 -> P1 : deny
- * .'-----.
- * | P2 |
- * '------'
- */
-/* clang-format off */
-FIXTURE_VARIANT_ADD(hierarchy, allow_with_one_domain) {
- /* clang-format on */
- .domain_both = false,
- .domain_parent = false,
- .domain_child = true,
-};
-
-/*
- * Parent domain
- * .------.
- * | P1 --. P1 -> P2 : deny
- * '------' \ P2 -> P1 : allow
- * '
- * P2
- */
-/* clang-format off */
-FIXTURE_VARIANT_ADD(hierarchy, deny_with_parent_domain) {
- /* clang-format on */
- .domain_both = false,
- .domain_parent = true,
- .domain_child = false,
-};
-
-/*
- * Parent + child domain (siblings)
- * .------.
- * | P1 ---. P1 -> P2 : deny
- * '------' \ P2 -> P1 : deny
- * .---'--.
- * | P2 |
- * '------'
- */
-/* clang-format off */
-FIXTURE_VARIANT_ADD(hierarchy, deny_with_sibling_domain) {
- /* clang-format on */
- .domain_both = false,
- .domain_parent = true,
- .domain_child = true,
-};
-
-/*
- * Same domain (inherited)
- * .-------------.
- * | P1----. | P1 -> P2 : allow
- * | \ | P2 -> P1 : allow
- * | ' |
- * | P2 |
- * '-------------'
- */
-/* clang-format off */
-FIXTURE_VARIANT_ADD(hierarchy, allow_sibling_domain) {
- /* clang-format on */
- .domain_both = true,
- .domain_parent = false,
- .domain_child = false,
-};
-
-/*
- * Inherited + child domain
- * .-----------------.
- * | P1----. | P1 -> P2 : allow
- * | \ | P2 -> P1 : deny
- * | .-'----. |
- * | | P2 | |
- * | '------' |
- * '-----------------'
- */
-/* clang-format off */
-FIXTURE_VARIANT_ADD(hierarchy, allow_with_nested_domain) {
- /* clang-format on */
- .domain_both = true,
- .domain_parent = false,
- .domain_child = true,
-};
-
-/*
- * Inherited + parent domain
- * .-----------------.
- * |.------. | P1 -> P2 : deny
- * || P1 ----. | P2 -> P1 : allow
- * |'------' \ |
- * | ' |
- * | P2 |
- * '-----------------'
- */
-/* clang-format off */
-FIXTURE_VARIANT_ADD(hierarchy, deny_with_nested_and_parent_domain) {
- /* clang-format on */
- .domain_both = true,
- .domain_parent = true,
- .domain_child = false,
-};
-
-/*
- * Inherited + parent and child domain (siblings)
- * .-----------------.
- * | .------. | P1 -> P2 : deny
- * | | P1 . | P2 -> P1 : deny
- * | '------'\ |
- * | \ |
- * | .--'---. |
- * | | P2 | |
- * | '------' |
- * '-----------------'
- */
-/* clang-format off */
-FIXTURE_VARIANT_ADD(hierarchy, deny_with_forked_domain) {
- /* clang-format on */
- .domain_both = true,
- .domain_parent = true,
- .domain_child = true,
-};
-
-FIXTURE_SETUP(hierarchy)
+FIXTURE_SETUP(scoped_domains)
{
}
-FIXTURE_TEARDOWN(hierarchy)
+FIXTURE_TEARDOWN(scoped_domains)
{
}
/* Test PTRACE_TRACEME and PTRACE_ATTACH for parent and child. */
-TEST_F(hierarchy, trace)
+TEST_F(scoped_domains, trace)
{
pid_t child, parent;
int status, err_proc_read;
diff --git a/tools/testing/selftests/landlock/scoped_abstract_unix_test.c b/tools/testing/selftests/landlock/scoped_abstract_unix_test.c
index 6825082c079c..72f97648d4a7 100644
--- a/tools/testing/selftests/landlock/scoped_abstract_unix_test.c
+++ b/tools/testing/selftests/landlock/scoped_abstract_unix_test.c
@@ -543,7 +543,7 @@ TEST_F(scoped_vs_unscoped, unix_scoping)
ASSERT_EQ(1, write(pipe_child[1], ".", 1));
ASSERT_EQ(grand_child, waitpid(grand_child, &status, 0));
- EXPECT_EQ(0, close(stream_server_child))
+ EXPECT_EQ(0, close(stream_server_child));
EXPECT_EQ(0, close(dgram_server_child));
return;
}
@@ -779,7 +779,6 @@ FIXTURE_TEARDOWN(various_address_sockets)
TEST_F(various_address_sockets, scoped_pathname_sockets)
{
- socklen_t size_stream, size_dgram;
pid_t child;
int status;
char buf_child, buf_parent;
@@ -798,12 +797,8 @@ TEST_F(various_address_sockets, scoped_pathname_sockets)
/* Pathname address. */
snprintf(stream_pathname_addr.sun_path,
sizeof(stream_pathname_addr.sun_path), "%s", stream_path);
- size_stream = offsetof(struct sockaddr_un, sun_path) +
- strlen(stream_pathname_addr.sun_path);
snprintf(dgram_pathname_addr.sun_path,
sizeof(dgram_pathname_addr.sun_path), "%s", dgram_path);
- size_dgram = offsetof(struct sockaddr_un, sun_path) +
- strlen(dgram_pathname_addr.sun_path);
/* Abstract address. */
memset(&stream_abstract_addr, 0, sizeof(stream_abstract_addr));
@@ -841,8 +836,9 @@ TEST_F(various_address_sockets, scoped_pathname_sockets)
/* Connects with pathname sockets. */
stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0);
ASSERT_LE(0, stream_pathname_socket);
- ASSERT_EQ(0, connect(stream_pathname_socket,
- &stream_pathname_addr, size_stream));
+ ASSERT_EQ(0,
+ connect(stream_pathname_socket, &stream_pathname_addr,
+ sizeof(stream_pathname_addr)));
ASSERT_EQ(1, write(stream_pathname_socket, "b", 1));
EXPECT_EQ(0, close(stream_pathname_socket));
@@ -850,12 +846,13 @@ TEST_F(various_address_sockets, scoped_pathname_sockets)
dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
ASSERT_LE(0, dgram_pathname_socket);
err = sendto(dgram_pathname_socket, "c", 1, 0,
- &dgram_pathname_addr, size_dgram);
+ &dgram_pathname_addr, sizeof(dgram_pathname_addr));
EXPECT_EQ(1, err);
/* Sends with connection. */
- ASSERT_EQ(0, connect(dgram_pathname_socket,
- &dgram_pathname_addr, size_dgram));
+ ASSERT_EQ(0,
+ connect(dgram_pathname_socket, &dgram_pathname_addr,
+ sizeof(dgram_pathname_addr)));
ASSERT_EQ(1, write(dgram_pathname_socket, "d", 1));
EXPECT_EQ(0, close(dgram_pathname_socket));
@@ -910,13 +907,13 @@ TEST_F(various_address_sockets, scoped_pathname_sockets)
stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0);
ASSERT_LE(0, stream_pathname_socket);
ASSERT_EQ(0, bind(stream_pathname_socket, &stream_pathname_addr,
- size_stream));
+ sizeof(stream_pathname_addr)));
ASSERT_EQ(0, listen(stream_pathname_socket, backlog));
dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
ASSERT_LE(0, dgram_pathname_socket);
ASSERT_EQ(0, bind(dgram_pathname_socket, &dgram_pathname_addr,
- size_dgram));
+ sizeof(dgram_pathname_addr)));
/* Sets up abstract servers. */
stream_abstract_socket = socket(AF_UNIX, SOCK_STREAM, 0);
diff --git a/tools/testing/selftests/landlock/scoped_base_variants.h b/tools/testing/selftests/landlock/scoped_base_variants.h
index d3b1fa8a584e..7116728ebc68 100644
--- a/tools/testing/selftests/landlock/scoped_base_variants.h
+++ b/tools/testing/selftests/landlock/scoped_base_variants.h
@@ -1,8 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Landlock scoped_domains variants
+ * Landlock scoped_domains test variant definition.
*
- * See the hierarchy variants from ptrace_test.c
+ * This file defines a fixture variant "scoped_domains" that has all
+ * permutations of parent/child process being in separate or shared
+ * Landlock domain, or not being in a Landlock domain at all.
+ *
+ * Scoped access tests can include this file to avoid repeating these
+ * combinations.
*
* Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
* Copyright © 2019-2020 ANSSI
diff --git a/tools/testing/selftests/mm/gup_longterm.c b/tools/testing/selftests/mm/gup_longterm.c
index 6279893a0adc..f61150d28eb2 100644
--- a/tools/testing/selftests/mm/gup_longterm.c
+++ b/tools/testing/selftests/mm/gup_longterm.c
@@ -179,7 +179,7 @@ static void do_test(int fd, size_t size, enum test_type type, bool shared)
if (rw && shared && fs_is_unknown(fs_type)) {
ksft_print_msg("Unknown filesystem\n");
result = KSFT_SKIP;
- return;
+ break;
}
/*
* R/O pinning or pinning in a private mapping is always
diff --git a/tools/testing/selftests/mm/merge.c b/tools/testing/selftests/mm/merge.c
index 363c1033cc7d..10b686102b79 100644
--- a/tools/testing/selftests/mm/merge.c
+++ b/tools/testing/selftests/mm/merge.c
@@ -22,12 +22,37 @@ FIXTURE(merge)
struct procmap_fd procmap;
};
+static char *map_carveout(unsigned int page_size)
+{
+ return mmap(NULL, 30 * page_size, PROT_NONE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+}
+
+static pid_t do_fork(struct procmap_fd *procmap)
+{
+ pid_t pid = fork();
+
+ if (pid == -1)
+ return -1;
+ if (pid != 0) {
+ wait(NULL);
+ return pid;
+ }
+
+ /* Reopen for child. */
+ if (close_procmap(procmap))
+ return -1;
+ if (open_self_procmap(procmap))
+ return -1;
+
+ return 0;
+}
+
FIXTURE_SETUP(merge)
{
self->page_size = psize();
/* Carve out PROT_NONE region to map over. */
- self->carveout = mmap(NULL, 30 * self->page_size, PROT_NONE,
- MAP_ANON | MAP_PRIVATE, -1, 0);
+ self->carveout = map_carveout(self->page_size);
ASSERT_NE(self->carveout, MAP_FAILED);
/* Setup PROCMAP_QUERY interface. */
ASSERT_EQ(open_self_procmap(&self->procmap), 0);
@@ -36,7 +61,8 @@ FIXTURE_SETUP(merge)
FIXTURE_TEARDOWN(merge)
{
ASSERT_EQ(munmap(self->carveout, 30 * self->page_size), 0);
- ASSERT_EQ(close_procmap(&self->procmap), 0);
+ /* May fail for parent of forked process. */
+ close_procmap(&self->procmap);
/*
* Clear unconditionally, as some tests set this. It is no issue if this
* fails (KSM may be disabled for instance).
@@ -44,6 +70,44 @@ FIXTURE_TEARDOWN(merge)
prctl(PR_SET_MEMORY_MERGE, 0, 0, 0, 0);
}
+FIXTURE(merge_with_fork)
+{
+ unsigned int page_size;
+ char *carveout;
+ struct procmap_fd procmap;
+};
+
+FIXTURE_VARIANT(merge_with_fork)
+{
+ bool forked;
+};
+
+FIXTURE_VARIANT_ADD(merge_with_fork, forked)
+{
+ .forked = true,
+};
+
+FIXTURE_VARIANT_ADD(merge_with_fork, unforked)
+{
+ .forked = false,
+};
+
+FIXTURE_SETUP(merge_with_fork)
+{
+ self->page_size = psize();
+ self->carveout = map_carveout(self->page_size);
+ ASSERT_NE(self->carveout, MAP_FAILED);
+ ASSERT_EQ(open_self_procmap(&self->procmap), 0);
+}
+
+FIXTURE_TEARDOWN(merge_with_fork)
+{
+ ASSERT_EQ(munmap(self->carveout, 30 * self->page_size), 0);
+ ASSERT_EQ(close_procmap(&self->procmap), 0);
+ /* See above. */
+ prctl(PR_SET_MEMORY_MERGE, 0, 0, 0, 0);
+}
+
TEST_F(merge, mprotect_unfaulted_left)
{
unsigned int page_size = self->page_size;
@@ -322,8 +386,8 @@ TEST_F(merge, forked_target_vma)
unsigned int page_size = self->page_size;
char *carveout = self->carveout;
struct procmap_fd *procmap = &self->procmap;
- pid_t pid;
char *ptr, *ptr2;
+ pid_t pid;
int i;
/*
@@ -344,19 +408,10 @@ TEST_F(merge, forked_target_vma)
*/
ptr[0] = 'x';
- pid = fork();
+ pid = do_fork(&self->procmap);
ASSERT_NE(pid, -1);
-
- if (pid != 0) {
- wait(NULL);
+ if (pid != 0)
return;
- }
-
- /* Child process below: */
-
- /* Reopen for child. */
- ASSERT_EQ(close_procmap(&self->procmap), 0);
- ASSERT_EQ(open_self_procmap(&self->procmap), 0);
/* unCOWing everything does not cause the AVC to go away. */
for (i = 0; i < 5 * page_size; i += page_size)
@@ -386,8 +441,8 @@ TEST_F(merge, forked_source_vma)
unsigned int page_size = self->page_size;
char *carveout = self->carveout;
struct procmap_fd *procmap = &self->procmap;
- pid_t pid;
char *ptr, *ptr2;
+ pid_t pid;
int i;
/*
@@ -408,19 +463,10 @@ TEST_F(merge, forked_source_vma)
*/
ptr[0] = 'x';
- pid = fork();
+ pid = do_fork(&self->procmap);
ASSERT_NE(pid, -1);
-
- if (pid != 0) {
- wait(NULL);
+ if (pid != 0)
return;
- }
-
- /* Child process below: */
-
- /* Reopen for child. */
- ASSERT_EQ(close_procmap(&self->procmap), 0);
- ASSERT_EQ(open_self_procmap(&self->procmap), 0);
/* unCOWing everything does not cause the AVC to go away. */
for (i = 0; i < 5 * page_size; i += page_size)
@@ -1171,4 +1217,288 @@ TEST_F(merge, mremap_correct_placed_faulted)
ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr + 15 * page_size);
}
+TEST_F(merge_with_fork, mremap_faulted_to_unfaulted_prev)
+{
+ struct procmap_fd *procmap = &self->procmap;
+ unsigned int page_size = self->page_size;
+ unsigned long offset;
+ char *ptr_a, *ptr_b;
+
+ /*
+ * mremap() such that A and B merge:
+ *
+ * |------------|
+ * | \ |
+ * |-----------| | / |---------|
+ * | unfaulted | v \ | faulted |
+ * |-----------| / |---------|
+ * B \ A
+ */
+
+ /* Map VMA A into place. */
+ ptr_a = mmap(&self->carveout[page_size + 3 * page_size],
+ 3 * page_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ ASSERT_NE(ptr_a, MAP_FAILED);
+ /* Fault it in. */
+ ptr_a[0] = 'x';
+
+ if (variant->forked) {
+ pid_t pid = do_fork(&self->procmap);
+
+ ASSERT_NE(pid, -1);
+ if (pid != 0)
+ return;
+ }
+
+ /*
+ * Now move it out of the way so we can place VMA B in position,
+ * unfaulted.
+ */
+ ptr_a = mremap(ptr_a, 3 * page_size, 3 * page_size,
+ MREMAP_FIXED | MREMAP_MAYMOVE, &self->carveout[20 * page_size]);
+ ASSERT_NE(ptr_a, MAP_FAILED);
+
+ /* Map VMA B into place. */
+ ptr_b = mmap(&self->carveout[page_size], 3 * page_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ ASSERT_NE(ptr_b, MAP_FAILED);
+
+ /*
+ * Now move VMA A into position with MREMAP_DONTUNMAP to catch incorrect
+ * anon_vma propagation.
+ */
+ ptr_a = mremap(ptr_a, 3 * page_size, 3 * page_size,
+ MREMAP_FIXED | MREMAP_MAYMOVE | MREMAP_DONTUNMAP,
+ &self->carveout[page_size + 3 * page_size]);
+ ASSERT_NE(ptr_a, MAP_FAILED);
+
+ /* The VMAs should have merged, if not forked. */
+ ASSERT_TRUE(find_vma_procmap(procmap, ptr_b));
+ ASSERT_EQ(procmap->query.vma_start, (unsigned long)ptr_b);
+
+ offset = variant->forked ? 3 * page_size : 6 * page_size;
+ ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr_b + offset);
+}
+
+TEST_F(merge_with_fork, mremap_faulted_to_unfaulted_next)
+{
+ struct procmap_fd *procmap = &self->procmap;
+ unsigned int page_size = self->page_size;
+ unsigned long offset;
+ char *ptr_a, *ptr_b;
+
+ /*
+ * mremap() such that A and B merge:
+ *
+ * |---------------------------|
+ * | \ |
+ * | |-----------| / |---------|
+ * v | unfaulted | \ | faulted |
+ * |-----------| / |---------|
+ * B \ A
+ *
+ * Then unmap VMA A to trigger the bug.
+ */
+
+ /* Map VMA A into place. */
+ ptr_a = mmap(&self->carveout[page_size], 3 * page_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ ASSERT_NE(ptr_a, MAP_FAILED);
+ /* Fault it in. */
+ ptr_a[0] = 'x';
+
+ if (variant->forked) {
+ pid_t pid = do_fork(&self->procmap);
+
+ ASSERT_NE(pid, -1);
+ if (pid != 0)
+ return;
+ }
+
+ /*
+ * Now move it out of the way so we can place VMA B in position,
+ * unfaulted.
+ */
+ ptr_a = mremap(ptr_a, 3 * page_size, 3 * page_size,
+ MREMAP_FIXED | MREMAP_MAYMOVE, &self->carveout[20 * page_size]);
+ ASSERT_NE(ptr_a, MAP_FAILED);
+
+ /* Map VMA B into place. */
+ ptr_b = mmap(&self->carveout[page_size + 3 * page_size], 3 * page_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ ASSERT_NE(ptr_b, MAP_FAILED);
+
+ /*
+ * Now move VMA A into position with MREMAP_DONTUNMAP to catch incorrect
+ * anon_vma propagation.
+ */
+ ptr_a = mremap(ptr_a, 3 * page_size, 3 * page_size,
+ MREMAP_FIXED | MREMAP_MAYMOVE | MREMAP_DONTUNMAP,
+ &self->carveout[page_size]);
+ ASSERT_NE(ptr_a, MAP_FAILED);
+
+ /* The VMAs should have merged, if not forked. */
+ ASSERT_TRUE(find_vma_procmap(procmap, ptr_a));
+ ASSERT_EQ(procmap->query.vma_start, (unsigned long)ptr_a);
+ offset = variant->forked ? 3 * page_size : 6 * page_size;
+ ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr_a + offset);
+}
+
+TEST_F(merge_with_fork, mremap_faulted_to_unfaulted_prev_unfaulted_next)
+{
+ struct procmap_fd *procmap = &self->procmap;
+ unsigned int page_size = self->page_size;
+ unsigned long offset;
+ char *ptr_a, *ptr_b, *ptr_c;
+
+ /*
+ * mremap() with MREMAP_DONTUNMAP such that A, B and C merge:
+ *
+ * |---------------------------|
+ * | \ |
+ * |-----------| | |-----------| / |---------|
+ * | unfaulted | v | unfaulted | \ | faulted |
+ * |-----------| |-----------| / |---------|
+ * A C \ B
+ */
+
+ /* Map VMA B into place. */
+ ptr_b = mmap(&self->carveout[page_size + 3 * page_size], 3 * page_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ ASSERT_NE(ptr_b, MAP_FAILED);
+ /* Fault it in. */
+ ptr_b[0] = 'x';
+
+ if (variant->forked) {
+ pid_t pid = do_fork(&self->procmap);
+
+ ASSERT_NE(pid, -1);
+ if (pid != 0)
+ return;
+ }
+
+ /*
+ * Now move it out of the way so we can place VMAs A, C in position,
+ * unfaulted.
+ */
+ ptr_b = mremap(ptr_b, 3 * page_size, 3 * page_size,
+ MREMAP_FIXED | MREMAP_MAYMOVE, &self->carveout[20 * page_size]);
+ ASSERT_NE(ptr_b, MAP_FAILED);
+
+ /* Map VMA A into place. */
+
+ ptr_a = mmap(&self->carveout[page_size], 3 * page_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ ASSERT_NE(ptr_a, MAP_FAILED);
+
+ /* Map VMA C into place. */
+ ptr_c = mmap(&self->carveout[page_size + 3 * page_size + 3 * page_size],
+ 3 * page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ ASSERT_NE(ptr_c, MAP_FAILED);
+
+ /*
+ * Now move VMA B into position with MREMAP_DONTUNMAP to catch incorrect
+ * anon_vma propagation.
+ */
+ ptr_b = mremap(ptr_b, 3 * page_size, 3 * page_size,
+ MREMAP_FIXED | MREMAP_MAYMOVE | MREMAP_DONTUNMAP,
+ &self->carveout[page_size + 3 * page_size]);
+ ASSERT_NE(ptr_b, MAP_FAILED);
+
+ /* The VMAs should have merged, if not forked. */
+ ASSERT_TRUE(find_vma_procmap(procmap, ptr_a));
+ ASSERT_EQ(procmap->query.vma_start, (unsigned long)ptr_a);
+ offset = variant->forked ? 3 * page_size : 9 * page_size;
+ ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr_a + offset);
+
+ /* If forked, B and C should also not have merged. */
+ if (variant->forked) {
+ ASSERT_TRUE(find_vma_procmap(procmap, ptr_b));
+ ASSERT_EQ(procmap->query.vma_start, (unsigned long)ptr_b);
+ ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr_b + 3 * page_size);
+ }
+}
+
+TEST_F(merge_with_fork, mremap_faulted_to_unfaulted_prev_faulted_next)
+{
+ struct procmap_fd *procmap = &self->procmap;
+ unsigned int page_size = self->page_size;
+ char *ptr_a, *ptr_b, *ptr_bc;
+
+ /*
+ * mremap() with MREMAP_DONTUNMAP such that A, B and C merge:
+ *
+ * |---------------------------|
+ * | \ |
+ * |-----------| | |-----------| / |---------|
+ * | unfaulted | v | faulted | \ | faulted |
+ * |-----------| |-----------| / |---------|
+ * A C \ B
+ */
+
+ /*
+ * Map VMA B and C into place. We have to map them together so their
+ * anon_vma is the same and the vma->vm_pgoff's are correctly aligned.
+ */
+ ptr_bc = mmap(&self->carveout[page_size + 3 * page_size],
+ 3 * page_size + 3 * page_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ ASSERT_NE(ptr_bc, MAP_FAILED);
+
+ /* Fault it in. */
+ ptr_bc[0] = 'x';
+
+ if (variant->forked) {
+ pid_t pid = do_fork(&self->procmap);
+
+ ASSERT_NE(pid, -1);
+ if (pid != 0)
+ return;
+ }
+
+ /*
+ * Now move VMA B out the way (splitting VMA BC) so we can place VMA A
+ * in position, unfaulted, and leave the remainder of the VMA we just
+ * moved in place, faulted, as VMA C.
+ */
+ ptr_b = mremap(ptr_bc, 3 * page_size, 3 * page_size,
+ MREMAP_FIXED | MREMAP_MAYMOVE, &self->carveout[20 * page_size]);
+ ASSERT_NE(ptr_b, MAP_FAILED);
+
+ /* Map VMA A into place. */
+ ptr_a = mmap(&self->carveout[page_size], 3 * page_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ ASSERT_NE(ptr_a, MAP_FAILED);
+
+ /*
+ * Now move VMA B into position with MREMAP_DONTUNMAP to catch incorrect
+ * anon_vma propagation.
+ */
+ ptr_b = mremap(ptr_b, 3 * page_size, 3 * page_size,
+ MREMAP_FIXED | MREMAP_MAYMOVE | MREMAP_DONTUNMAP,
+ &self->carveout[page_size + 3 * page_size]);
+ ASSERT_NE(ptr_b, MAP_FAILED);
+
+ /* The VMAs should have merged. A,B,C if unforked, B, C if forked. */
+ if (variant->forked) {
+ ASSERT_TRUE(find_vma_procmap(procmap, ptr_b));
+ ASSERT_EQ(procmap->query.vma_start, (unsigned long)ptr_b);
+ ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr_b + 6 * page_size);
+ } else {
+ ASSERT_TRUE(find_vma_procmap(procmap, ptr_a));
+ ASSERT_EQ(procmap->query.vma_start, (unsigned long)ptr_a);
+ ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr_a + 9 * page_size);
+ }
+}
+
TEST_HARNESS_MAIN
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index b66ba04f19d9..45c4ea381bc3 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -48,6 +48,7 @@ TEST_PROGS := \
ipv6_flowlabel.sh \
ipv6_force_forwarding.sh \
ipv6_route_update_soft_lockup.sh \
+ ipvtap_test.sh \
l2_tos_ttl_inherit.sh \
l2tp.sh \
link_netns.py \
diff --git a/tools/testing/selftests/net/amt.sh b/tools/testing/selftests/net/amt.sh
index 3ef209cacb8e..663744305e52 100755
--- a/tools/testing/selftests/net/amt.sh
+++ b/tools/testing/selftests/net/amt.sh
@@ -73,6 +73,8 @@
# +------------------------+
#==============================================================================
+source lib.sh
+
readonly LISTENER=$(mktemp -u listener-XXXXXXXX)
readonly GATEWAY=$(mktemp -u gateway-XXXXXXXX)
readonly RELAY=$(mktemp -u relay-XXXXXXXX)
@@ -246,14 +248,15 @@ test_ipv6_forward()
send_mcast4()
{
- sleep 2
+ sleep 5
+ wait_local_port_listen ${LISTENER} 4000 udp
ip netns exec "${SOURCE}" bash -c \
'printf "%s %128s" 172.17.0.2 | nc -w 1 -u 239.0.0.1 4000' &
}
send_mcast6()
{
- sleep 2
+ wait_local_port_listen ${LISTENER} 6000 udp
ip netns exec "${SOURCE}" bash -c \
'printf "%s %128s" 2001:db8:3::2 | nc -w 1 -u ff0e::5:6 6000' &
}
diff --git a/tools/testing/selftests/net/config b/tools/testing/selftests/net/config
index 1e1f253118f5..b84362b9b508 100644
--- a/tools/testing/selftests/net/config
+++ b/tools/testing/selftests/net/config
@@ -48,6 +48,7 @@ CONFIG_IPV6_SEG6_LWTUNNEL=y
CONFIG_IPV6_SIT=y
CONFIG_IPV6_VTI=y
CONFIG_IPVLAN=m
+CONFIG_IPVTAP=m
CONFIG_KALLSYMS=y
CONFIG_L2TP=m
CONFIG_L2TP_ETH=m
@@ -116,6 +117,7 @@ CONFIG_PROC_SYSCTL=y
CONFIG_PSAMPLE=m
CONFIG_RPS=y
CONFIG_SYSFS=y
+CONFIG_TAP=m
CONFIG_TCP_MD5SIG=y
CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_TEST_BPF=m
diff --git a/tools/testing/selftests/net/fib-onlink-tests.sh b/tools/testing/selftests/net/fib-onlink-tests.sh
index ec2d6ceb1f08..c01be076b210 100755
--- a/tools/testing/selftests/net/fib-onlink-tests.sh
+++ b/tools/testing/selftests/net/fib-onlink-tests.sh
@@ -120,7 +120,7 @@ log_subsection()
run_cmd()
{
- local cmd="$*"
+ local cmd="$1"
local out
local rc
@@ -145,7 +145,7 @@ get_linklocal()
local pfx
local addr
- addr=$(${pfx} ip -6 -br addr show dev ${dev} | \
+ addr=$(${pfx} ${IP} -6 -br addr show dev ${dev} | \
awk '{
for (i = 3; i <= NF; ++i) {
if ($i ~ /^fe80/)
@@ -173,58 +173,48 @@ setup()
set -e
- # create namespace
- setup_ns PEER_NS
+ # create namespaces
+ setup_ns ns1
+ IP="ip -netns $ns1"
+ setup_ns ns2
# add vrf table
- ip li add ${VRF} type vrf table ${VRF_TABLE}
- ip li set ${VRF} up
- ip ro add table ${VRF_TABLE} unreachable default metric 8192
- ip -6 ro add table ${VRF_TABLE} unreachable default metric 8192
+ ${IP} li add ${VRF} type vrf table ${VRF_TABLE}
+ ${IP} li set ${VRF} up
+ ${IP} ro add table ${VRF_TABLE} unreachable default metric 8192
+ ${IP} -6 ro add table ${VRF_TABLE} unreachable default metric 8192
# create test interfaces
- ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}
- ip li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]}
- ip li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]}
- ip li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]}
+ ${IP} li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}
+ ${IP} li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]}
+ ${IP} li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]}
+ ${IP} li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]}
# enslave vrf interfaces
for n in 5 7; do
- ip li set ${NETIFS[p${n}]} vrf ${VRF}
+ ${IP} li set ${NETIFS[p${n}]} vrf ${VRF}
done
# add addresses
for n in 1 3 5 7; do
- ip li set ${NETIFS[p${n}]} up
- ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
- ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
+ ${IP} li set ${NETIFS[p${n}]} up
+ ${IP} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
+ ${IP} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
done
# move peer interfaces to namespace and add addresses
for n in 2 4 6 8; do
- ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up
- ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
- ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
+ ${IP} li set ${NETIFS[p${n}]} netns ${ns2} up
+ ip -netns $ns2 addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
+ ip -netns $ns2 addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
done
- ip -6 ro add default via ${V6ADDRS[p3]/::[0-9]/::64}
- ip -6 ro add table ${VRF_TABLE} default via ${V6ADDRS[p7]/::[0-9]/::64}
+ ${IP} -6 ro add default via ${V6ADDRS[p3]/::[0-9]/::64}
+ ${IP} -6 ro add table ${VRF_TABLE} default via ${V6ADDRS[p7]/::[0-9]/::64}
set +e
}
-cleanup()
-{
- # make sure we start from a clean slate
- cleanup_ns ${PEER_NS} 2>/dev/null
- for n in 1 3 5 7; do
- ip link del ${NETIFS[p${n}]} 2>/dev/null
- done
- ip link del ${VRF} 2>/dev/null
- ip ro flush table ${VRF_TABLE}
- ip -6 ro flush table ${VRF_TABLE}
-}
-
################################################################################
# IPv4 tests
#
@@ -241,7 +231,7 @@ run_ip()
# dev arg may be empty
[ -n "${dev}" ] && dev="dev ${dev}"
- run_cmd ip ro add table "${table}" "${prefix}"/32 via "${gw}" "${dev}" onlink
+ run_cmd "${IP} ro add table ${table} ${prefix}/32 via ${gw} ${dev} onlink"
log_test $? ${exp_rc} "${desc}"
}
@@ -257,8 +247,8 @@ run_ip_mpath()
# dev arg may be empty
[ -n "${dev}" ] && dev="dev ${dev}"
- run_cmd ip ro add table "${table}" "${prefix}"/32 \
- nexthop via ${nh1} nexthop via ${nh2}
+ run_cmd "${IP} ro add table ${table} ${prefix}/32 \
+ nexthop via ${nh1} nexthop via ${nh2}"
log_test $? ${exp_rc} "${desc}"
}
@@ -339,7 +329,7 @@ run_ip6()
# dev arg may be empty
[ -n "${dev}" ] && dev="dev ${dev}"
- run_cmd ip -6 ro add table "${table}" "${prefix}"/128 via "${gw}" "${dev}" onlink
+ run_cmd "${IP} -6 ro add table ${table} ${prefix}/128 via ${gw} ${dev} onlink"
log_test $? ${exp_rc} "${desc}"
}
@@ -353,8 +343,8 @@ run_ip6_mpath()
local exp_rc="$6"
local desc="$7"
- run_cmd ip -6 ro add table "${table}" "${prefix}"/128 "${opts}" \
- nexthop via ${nh1} nexthop via ${nh2}
+ run_cmd "${IP} -6 ro add table ${table} ${prefix}/128 ${opts} \
+ nexthop via ${nh1} nexthop via ${nh2}"
log_test $? ${exp_rc} "${desc}"
}
@@ -491,10 +481,9 @@ do
esac
done
-cleanup
setup
run_onlink_tests
-cleanup
+cleanup_ns ${ns1} ${ns2}
if [ "$TESTS" != "none" ]; then
printf "\nTests passed: %3d\n" ${nsuccess}
diff --git a/tools/testing/selftests/net/ipvtap_test.sh b/tools/testing/selftests/net/ipvtap_test.sh
new file mode 100755
index 000000000000..354ca7ce8584
--- /dev/null
+++ b/tools/testing/selftests/net/ipvtap_test.sh
@@ -0,0 +1,168 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Simple tests for ipvtap
+
+
+#
+# The testing environment looks this way:
+#
+# |------HNS-------| |------PHY-------|
+# | veth<----------------->veth |
+# |------|--|------| |----------------|
+# | |
+# | | |-----TST0-------|
+# | |------------|----ipvlan |
+# | |----------------|
+# |
+# | |-----TST1-------|
+# |---------------|----ipvlan |
+# |----------------|
+#
+
+ALL_TESTS="
+ test_ip_set
+"
+
+source lib.sh
+
+DEBUG=0
+
+VETH_HOST=vethtst.h
+VETH_PHY=vethtst.p
+
+NS_COUNT=32
+IP_ITERATIONS=1024
+IPSET_TIMEOUT="60s"
+
+ns_run() {
+ ns=$1
+ shift
+ if [[ "$ns" == "global" ]]; then
+ "$@" >/dev/null
+ else
+ ip netns exec "$ns" "$@" >/dev/null
+ fi
+}
+
+test_ip_setup_env() {
+ setup_ns NS_PHY
+ setup_ns HST_NS
+
+ # setup simulated other-host (phy) and host itself
+ ns_run "$HST_NS" ip link add $VETH_HOST type veth peer name $VETH_PHY \
+ netns "$NS_PHY" >/dev/null
+ ns_run "$HST_NS" ip link set $VETH_HOST up
+ ns_run "$NS_PHY" ip link set $VETH_PHY up
+
+ for ((i=0; i<NS_COUNT; i++)); do
+ setup_ns ipvlan_ns_$i
+ ns="ipvlan_ns_$i"
+ if [ "$DEBUG" = "1" ]; then
+ echo "created NS ${!ns}"
+ fi
+ if ! ns_run "$HST_NS" ip link add netns ${!ns} ipvlan0 \
+ link $VETH_HOST \
+ type ipvtap mode l2 bridge; then
+ exit_error "FAIL: Failed to configure ipvlan link."
+ fi
+ done
+}
+
+test_ip_cleanup_env() {
+ ns_run "$HST_NS" ip link del $VETH_HOST
+ cleanup_all_ns
+}
+
+exit_error() {
+ echo "$1"
+ exit $ksft_fail
+}
+
+rnd() {
+ echo $(( RANDOM % 32 + 16 ))
+}
+
+test_ip_set_thread() {
+ # Here we are trying to create some IP conflicts between namespaces.
+ # If just add/remove IP, nothing interesting will happen.
+ # But if add random IP and then remove random IP,
+ # eventually conflicts start to apear.
+ ip link set ipvlan0 up
+ for ((i=0; i<IP_ITERATIONS; i++)); do
+ v=$(rnd)
+ ip a a "172.25.0.$v/24" dev ipvlan0 2>/dev/null
+ ip a a "fc00::$v/64" dev ipvlan0 2>/dev/null
+ v=$(rnd)
+ ip a d "172.25.0.$v/24" dev ipvlan0 2>/dev/null
+ ip a d "fc00::$v/64" dev ipvlan0 2>/dev/null
+ done
+}
+
+test_ip_set() {
+ RET=0
+
+ trap test_ip_cleanup_env EXIT
+
+ test_ip_setup_env
+
+ declare -A ns_pids
+ for ((i=0; i<NS_COUNT; i++)); do
+ ns="ipvlan_ns_$i"
+ ns_run ${!ns} timeout "$IPSET_TIMEOUT" \
+ bash -c "$0 test_ip_set_thread"&
+ ns_pids[$i]=$!
+ done
+
+ for ((i=0; i<NS_COUNT; i++)); do
+ wait "${ns_pids[$i]}"
+ done
+
+ declare -A all_ips
+ for ((i=0; i<NS_COUNT; i++)); do
+ ns="ipvlan_ns_$i"
+ ip_output=$(ip netns exec ${!ns} ip a l dev ipvlan0 | grep inet)
+ while IFS= read -r nsip_out; do
+ if [[ -z $nsip_out ]]; then
+ continue;
+ fi
+ nsip=$(awk '{print $2}' <<< "$nsip_out")
+ if [[ -v all_ips[$nsip] ]]; then
+ RET=$ksft_fail
+ log_test "conflict for $nsip"
+ return "$RET"
+ else
+ all_ips[$nsip]=$i
+ fi
+ done <<< "$ip_output"
+ done
+
+ if [ "$DEBUG" = "1" ]; then
+ for key in "${!all_ips[@]}"; do
+ echo "$key: ${all_ips[$key]}"
+ done
+ fi
+
+ trap - EXIT
+ test_ip_cleanup_env
+
+ log_test "test multithreaded ip set"
+}
+
+if [[ "$1" == "-d" ]]; then
+ DEBUG=1
+ shift
+fi
+
+if [[ "$1" == "-t" ]]; then
+ shift
+ TESTS="$*"
+fi
+
+if [[ "$1" == "test_ip_set_thread" ]]; then
+ test_ip_set_thread
+else
+ require_command ip
+
+ tests_run
+fi
diff --git a/tools/testing/selftests/net/lib/py/__init__.py b/tools/testing/selftests/net/lib/py/__init__.py
index 40f9ce307dd1..f528b67639de 100644
--- a/tools/testing/selftests/net/lib/py/__init__.py
+++ b/tools/testing/selftests/net/lib/py/__init__.py
@@ -13,7 +13,7 @@ from .ksft import KsftFailEx, KsftSkipEx, KsftXfailEx, ksft_pr, ksft_eq, \
from .netns import NetNS, NetNSEnter
from .nsim import NetdevSim, NetdevSimDev
from .utils import CmdExitFailure, fd_read_timeout, cmd, bkg, defer, \
- bpftool, ip, ethtool, bpftrace, rand_port, wait_port_listen, wait_file
+ bpftool, ip, ethtool, bpftrace, rand_port, wait_port_listen, wait_file, tool
from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily, RtnlAddrFamily
from .ynl import NetshaperFamily, DevlinkFamily, PSPFamily
@@ -26,7 +26,7 @@ __all__ = ["KSRC",
"NetNS", "NetNSEnter",
"CmdExitFailure", "fd_read_timeout", "cmd", "bkg", "defer",
"bpftool", "ip", "ethtool", "bpftrace", "rand_port",
- "wait_port_listen", "wait_file",
+ "wait_port_listen", "wait_file", "tool",
"NetdevSim", "NetdevSimDev",
"NetshaperFamily", "DevlinkFamily", "PSPFamily", "NlError",
"YnlFamily", "EthtoolFamily", "NetdevFamily", "RtnlFamily",
diff --git a/tools/testing/selftests/net/mptcp/Makefile b/tools/testing/selftests/net/mptcp/Makefile
index 15d144a25d82..4dd6278cd3dd 100644
--- a/tools/testing/selftests/net/mptcp/Makefile
+++ b/tools/testing/selftests/net/mptcp/Makefile
@@ -3,6 +3,7 @@
top_srcdir = ../../../../..
CFLAGS += -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir)/usr/include $(KHDR_INCLUDES)
+CFLAGS += -I$(top_srcdir)/tools/include
TEST_PROGS := \
diag.sh \
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
index 404a77bf366a..10f6f99cfd4e 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
@@ -33,6 +33,7 @@
#include <linux/tcp.h>
#include <linux/time_types.h>
#include <linux/sockios.h>
+#include <linux/compiler.h>
extern int optind;
@@ -140,7 +141,7 @@ static void die_usage(void)
exit(1);
}
-static void xerror(const char *fmt, ...)
+static void __noreturn xerror(const char *fmt, ...)
{
va_list ap;
diff --git a/tools/testing/selftests/net/mptcp/mptcp_diag.c b/tools/testing/selftests/net/mptcp/mptcp_diag.c
index e084796e804d..8e0b1b8d84b6 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_diag.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_diag.c
@@ -5,6 +5,7 @@
#include <linux/rtnetlink.h>
#include <linux/inet_diag.h>
#include <linux/netlink.h>
+#include <linux/compiler.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/tcp.h>
@@ -87,7 +88,7 @@ enum {
#define rta_getattr(type, value) (*(type *)RTA_DATA(value))
-static void die_perror(const char *msg)
+static void __noreturn die_perror(const char *msg)
{
perror(msg);
exit(1);
diff --git a/tools/testing/selftests/net/mptcp/mptcp_inq.c b/tools/testing/selftests/net/mptcp/mptcp_inq.c
index 8e8f6441ad8b..5716998da192 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_inq.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_inq.c
@@ -28,6 +28,7 @@
#include <linux/tcp.h>
#include <linux/sockios.h>
+#include <linux/compiler.h>
#ifndef IPPROTO_MPTCP
#define IPPROTO_MPTCP 262
@@ -40,7 +41,7 @@ static int pf = AF_INET;
static int proto_tx = IPPROTO_MPTCP;
static int proto_rx = IPPROTO_MPTCP;
-static void die_perror(const char *msg)
+static void __noreturn die_perror(const char *msg)
{
perror(msg);
exit(1);
@@ -52,7 +53,7 @@ static void die_usage(int r)
exit(r);
}
-static void xerror(const char *fmt, ...)
+static void __noreturn xerror(const char *fmt, ...)
{
va_list ap;
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index 286164f7246e..b6e58d936ebe 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -25,6 +25,7 @@
#include <netinet/in.h>
#include <linux/tcp.h>
+#include <linux/compiler.h>
static int pf = AF_INET;
@@ -127,7 +128,7 @@ struct so_state {
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
-static void die_perror(const char *msg)
+static void __noreturn die_perror(const char *msg)
{
perror(msg);
exit(1);
@@ -139,7 +140,7 @@ static void die_usage(int r)
exit(r);
}
-static void xerror(const char *fmt, ...)
+static void __noreturn xerror(const char *fmt, ...)
{
va_list ap;
diff --git a/tools/testing/selftests/net/netfilter/nft_concat_range.sh b/tools/testing/selftests/net/netfilter/nft_concat_range.sh
index ad97c6227f35..394166f224a4 100755
--- a/tools/testing/selftests/net/netfilter/nft_concat_range.sh
+++ b/tools/testing/selftests/net/netfilter/nft_concat_range.sh
@@ -29,7 +29,7 @@ TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto
net6_port_net6_port net_port_mac_proto_net"
# Reported bugs, also described by TYPE_ variables below
-BUGS="flush_remove_add reload net_port_proto_match avx2_mismatch doublecreate"
+BUGS="flush_remove_add reload net_port_proto_match avx2_mismatch doublecreate insert_overlap"
# List of possible paths to pktgen script from kernel tree for performance tests
PKTGEN_SCRIPT_PATHS="
@@ -420,6 +420,18 @@ race_repeat 0
perf_duration 0
"
+TYPE_insert_overlap="
+display reject overlapping range on add
+type_spec ipv4_addr . ipv4_addr
+chain_spec ip saddr . ip daddr
+dst addr4
+proto icmp
+
+race_repeat 0
+
+perf_duration 0
+"
+
# Set template for all tests, types and rules are filled in depending on test
set_template='
flush ruleset
@@ -1954,6 +1966,37 @@ EOF
return 0
}
+add_fail()
+{
+ if nft add element inet filter test "$1" 2>/dev/null ; then
+ err "Returned success for add ${1} given set:"
+ err "$(nft -a list set inet filter test )"
+ return 1
+ fi
+
+ return 0
+}
+
+test_bug_insert_overlap()
+{
+ local elements="1.2.3.4 . 1.2.4.1"
+
+ setup veth send_"${proto}" set || return ${ksft_skip}
+
+ add "{ $elements }" || return 1
+
+ elements="1.2.3.0-1.2.3.4 . 1.2.4.1"
+ add_fail "{ $elements }" || return 1
+
+ elements="1.2.3.0-1.2.3.4 . 1.2.4.2"
+ add "{ $elements }" || return 1
+
+ elements="1.2.3.4 . 1.2.4.1-1.2.4.2"
+ add_fail "{ $elements }" || return 1
+
+ return 0
+}
+
test_reported_issues() {
eval test_bug_"${subtest}"
}
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json b/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json
index da156feabcbf..b056eb966871 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json
@@ -1098,5 +1098,52 @@
"teardown": [
"$TC qdisc del dev $DUMMY root"
]
+ },
+ {
+ "id": "4ed9",
+ "name": "Try to redirect to self on egress with clsact",
+ "category": [
+ "filter",
+ "mirred"
+ ],
+ "plugins": {
+ "requires": [
+ "nsPlugin"
+ ]
+ },
+ "setup": [
+ "$IP link set dev $DUMMY up || true",
+ "$IP addr add 10.10.10.10/24 dev $DUMMY || true",
+ "$TC qdisc add dev $DUMMY clsact",
+ "$TC filter add dev $DUMMY egress protocol ip prio 10 matchall action mirred egress redirect dev $DUMMY index 1"
+ ],
+ "cmdUnderTest": "ping -c1 -W0.01 -I $DUMMY 10.10.10.1",
+ "expExitCode": "1",
+ "verifyCmd": "$TC -j -s actions get action mirred index 1",
+ "matchJSON": [
+ {
+ "total acts": 0
+ },
+ {
+ "actions": [
+ {
+ "order": 1,
+ "kind": "mirred",
+ "mirred_action": "redirect",
+ "direction": "egress",
+ "index": 1,
+ "stats": {
+ "packets": 1,
+ "overlimits": 1
+ },
+ "not_in_hw": true
+ }
+ ]
+ }
+ ],
+ "teardown": [
+ "$TC qdisc del dev $DUMMY clsact"
+ ]
}
+
]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/teql.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/teql.json
index e5cc31f265f8..0179c57104ad 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/teql.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/teql.json
@@ -81,5 +81,30 @@
"$TC qdisc del dev $DUMMY handle 1: root",
"$IP link del dev $DUMMY"
]
+ },
+ {
+ "id": "124e",
+ "name": "Try to add teql as a child qdisc",
+ "category": [
+ "qdisc",
+ "ets",
+ "tbf"
+ ],
+ "plugins": {
+ "requires": [
+ "nsPlugin"
+ ]
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: qfq",
+ "$TC class add dev $DUMMY parent 1: classid 1:1 qfq weight 15 maxpkt 16384"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:1 handle 2:1 teql0",
+ "expExitCode": "2",
+ "verifyCmd": "$TC -s -j qdisc ls dev $DUMMY parent 1:1",
+ "matchJSON": [],
+ "teardown": [
+ "$TC qdisc del dev $DUMMY root handle 1:"
+ ]
}
]
diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
index 185ba553686a..f197ad9cc262 100644
--- a/tools/testing/selftests/ublk/kublk.c
+++ b/tools/testing/selftests/ublk/kublk.c
@@ -753,7 +753,7 @@ static int ublk_thread_is_idle(struct ublk_thread *t)
static int ublk_thread_is_done(struct ublk_thread *t)
{
- return (t->state & UBLKS_T_STOPPING) && ublk_thread_is_idle(t);
+ return (t->state & UBLKS_T_STOPPING) && ublk_thread_is_idle(t) && !t->cmd_inflight;
}
static inline void ublksrv_handle_tgt_cqe(struct ublk_thread *t,
@@ -1054,7 +1054,9 @@ static int ublk_start_daemon(const struct dev_ctx *ctx, struct ublk_dev *dev)
}
if (ret < 0) {
ublk_err("%s: ublk_ctrl_start_dev failed: %d\n", __func__, ret);
- goto fail;
+ /* stop device so that inflight uring_cmd can be cancelled */
+ ublk_ctrl_stop_dev(dev);
+ goto fail_start;
}
ublk_ctrl_get_info(dev);
@@ -1062,7 +1064,7 @@ static int ublk_start_daemon(const struct dev_ctx *ctx, struct ublk_dev *dev)
ublk_ctrl_dump(dev);
else
ublk_send_dev_event(ctx, dev, dev->dev_info.dev_id);
-
+fail_start:
/* wait until we are terminated */
for (i = 0; i < dev->nthreads; i++)
pthread_join(tinfo[i].thread, &thread_ret);
@@ -1272,7 +1274,7 @@ static int __cmd_dev_add(const struct dev_ctx *ctx)
}
ret = ublk_start_daemon(ctx, dev);
- ublk_dbg(UBLK_DBG_DEV, "%s: daemon exit %d\b", ret);
+ ublk_dbg(UBLK_DBG_DEV, "%s: daemon exit %d\n", __func__, ret);
if (ret < 0)
ublk_ctrl_del_dev(dev);
@@ -1618,6 +1620,7 @@ int main(int argc, char *argv[])
int option_idx, opt;
const char *cmd = argv[1];
struct dev_ctx ctx = {
+ ._evtfd = -1,
.queue_depth = 128,
.nr_hw_queues = 2,
.dev_id = -1,
diff --git a/tools/testing/selftests/vDSO/vgetrandom-chacha.S b/tools/testing/selftests/vDSO/vgetrandom-chacha.S
index a4a82e1c28a9..8c3cbf4dfd6a 100644
--- a/tools/testing/selftests/vDSO/vgetrandom-chacha.S
+++ b/tools/testing/selftests/vDSO/vgetrandom-chacha.S
@@ -14,7 +14,7 @@
#elif defined(__riscv) && __riscv_xlen == 64
#include "../../../../arch/riscv/kernel/vdso/vgetrandom-chacha.S"
#elif defined(__s390x__)
-#include "../../../../arch/s390/kernel/vdso64/vgetrandom-chacha.S"
+#include "../../../../arch/s390/kernel/vdso/vgetrandom-chacha.S"
#elif defined(__x86_64__)
#include "../../../../arch/x86/entry/vdso/vgetrandom-chacha.S"
#endif
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index 83148875a12c..434065215d12 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -36,6 +36,7 @@ BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32))
BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64))
CFLAGS := -O2 -g -std=gnu99 -pthread -Wall $(KHDR_INCLUDES)
+CFLAGS += -I $(top_srcdir)/tools/testing/selftests/
# call32_from_64 in thunks.S uses absolute addresses.
ifeq ($(CAN_BUILD_WITH_NOPIE),1)
diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c
index d843643ced6b..9430ef5b8bc3 100644
--- a/tools/testing/vsock/util.c
+++ b/tools/testing/vsock/util.c
@@ -511,6 +511,18 @@ void run_tests(const struct test_case *test_cases,
printf("ok\n");
}
+
+ printf("All tests have been executed. Waiting other peer...");
+ fflush(stdout);
+
+ /*
+ * Final full barrier, to ensure that all tests have been run and
+ * that even the last one has been successful on both sides.
+ */
+ control_writeln("COMPLETED");
+ control_expectln("COMPLETED");
+
+ printf("ok\n");
}
void list_tests(const struct test_case *test_cases)
diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h
index 142c02a6834a..bf633cde82b0 100644
--- a/tools/testing/vsock/util.h
+++ b/tools/testing/vsock/util.h
@@ -25,7 +25,7 @@ enum transport {
};
static const char * const transport_ksyms[] = {
- #define x(name, symbol) "d " symbol "_transport",
+ #define x(name, symbol) " " symbol "_transport",
KNOWN_TRANSPORTS(x)
#undef x
};
diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
index 9e1250790f33..5bd20ccd9335 100644
--- a/tools/testing/vsock/vsock_test.c
+++ b/tools/testing/vsock/vsock_test.c
@@ -347,10 +347,12 @@ static void test_stream_msg_peek_server(const struct test_opts *opts)
}
#define SOCK_BUF_SIZE (2 * 1024 * 1024)
+#define SOCK_BUF_SIZE_SMALL (64 * 1024)
#define MAX_MSG_PAGES 4
static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
{
+ unsigned long long sock_buf_size;
unsigned long curr_hash;
size_t max_msg_size;
int page_size;
@@ -363,6 +365,16 @@ static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
exit(EXIT_FAILURE);
}
+ sock_buf_size = SOCK_BUF_SIZE;
+
+ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE,
+ sock_buf_size,
+ "setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)");
+
+ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
+ sock_buf_size,
+ "setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
+
/* Wait, until receiver sets buffer size. */
control_expectln("SRVREADY");
@@ -2192,6 +2204,128 @@ static void test_stream_nolinger_server(const struct test_opts *opts)
close(fd);
}
+static void test_stream_accepted_setsockopt_client(const struct test_opts *opts)
+{
+ int fd;
+
+ fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
+ if (fd < 0) {
+ perror("connect");
+ exit(EXIT_FAILURE);
+ }
+
+ close(fd);
+}
+
+static void test_stream_accepted_setsockopt_server(const struct test_opts *opts)
+{
+ int fd;
+
+ fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL);
+ if (fd < 0) {
+ perror("accept");
+ exit(EXIT_FAILURE);
+ }
+
+ enable_so_zerocopy_check(fd);
+ close(fd);
+}
+
+static void test_stream_tx_credit_bounds_client(const struct test_opts *opts)
+{
+ unsigned long long sock_buf_size;
+ size_t total = 0;
+ char buf[4096];
+ int fd;
+
+ memset(buf, 'A', sizeof(buf));
+
+ fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
+ if (fd < 0) {
+ perror("connect");
+ exit(EXIT_FAILURE);
+ }
+
+ sock_buf_size = SOCK_BUF_SIZE_SMALL;
+
+ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE,
+ sock_buf_size,
+ "setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)");
+
+ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
+ sock_buf_size,
+ "setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
+
+ if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) < 0) {
+ perror("fcntl(F_SETFL)");
+ exit(EXIT_FAILURE);
+ }
+
+ control_expectln("SRVREADY");
+
+ for (;;) {
+ ssize_t sent = send(fd, buf, sizeof(buf), 0);
+
+ if (sent == 0) {
+ fprintf(stderr, "unexpected EOF while sending bytes\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (sent < 0) {
+ if (errno == EINTR)
+ continue;
+
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ break;
+
+ perror("send");
+ exit(EXIT_FAILURE);
+ }
+
+ total += sent;
+ }
+
+ control_writeln("CLIDONE");
+ close(fd);
+
+ /* We should not be able to send more bytes than the value set as
+ * local buffer size.
+ */
+ if (total > sock_buf_size) {
+ fprintf(stderr,
+ "TX credit too large: queued %zu bytes (expected <= %llu)\n",
+ total, sock_buf_size);
+ exit(EXIT_FAILURE);
+ }
+}
+
+static void test_stream_tx_credit_bounds_server(const struct test_opts *opts)
+{
+ unsigned long long sock_buf_size;
+ int fd;
+
+ fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL);
+ if (fd < 0) {
+ perror("accept");
+ exit(EXIT_FAILURE);
+ }
+
+ sock_buf_size = SOCK_BUF_SIZE;
+
+ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE,
+ sock_buf_size,
+ "setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)");
+
+ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
+ sock_buf_size,
+ "setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
+
+ control_writeln("SRVREADY");
+ control_expectln("CLIDONE");
+
+ close(fd);
+}
+
static struct test_case test_cases[] = {
{
.name = "SOCK_STREAM connection reset",
@@ -2371,6 +2505,21 @@ static struct test_case test_cases[] = {
.run_client = test_seqpacket_unread_bytes_client,
.run_server = test_seqpacket_unread_bytes_server,
},
+ {
+ .name = "SOCK_STREAM accept()ed socket custom setsockopt()",
+ .run_client = test_stream_accepted_setsockopt_client,
+ .run_server = test_stream_accepted_setsockopt_server,
+ },
+ {
+ .name = "SOCK_STREAM virtio MSG_ZEROCOPY coalescence corruption",
+ .run_client = test_stream_msgzcopy_mangle_client,
+ .run_server = test_stream_msgzcopy_mangle_server,
+ },
+ {
+ .name = "SOCK_STREAM TX credit bounds",
+ .run_client = test_stream_tx_credit_bounds_client,
+ .run_server = test_stream_tx_credit_bounds_server,
+ },
{},
};
diff --git a/tools/testing/vsock/vsock_test_zerocopy.c b/tools/testing/vsock/vsock_test_zerocopy.c
index 9d9a6cb9614a..a31ddfc1cd0c 100644
--- a/tools/testing/vsock/vsock_test_zerocopy.c
+++ b/tools/testing/vsock/vsock_test_zerocopy.c
@@ -9,14 +9,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <poll.h>
#include <linux/errqueue.h>
#include <linux/kernel.h>
+#include <linux/sockios.h>
+#include <linux/time64.h>
#include <errno.h>
#include "control.h"
+#include "timeout.h"
#include "vsock_test_zerocopy.h"
#include "msg_zerocopy_common.h"
@@ -356,3 +360,73 @@ void test_stream_msgzcopy_empty_errq_server(const struct test_opts *opts)
control_expectln("DONE");
close(fd);
}
+
+#define GOOD_COPY_LEN 128 /* net/vmw_vsock/virtio_transport_common.c */
+
+void test_stream_msgzcopy_mangle_client(const struct test_opts *opts)
+{
+ char sbuf1[PAGE_SIZE + 1], sbuf2[GOOD_COPY_LEN];
+ unsigned long hash;
+ struct pollfd fds;
+ int fd, i;
+
+ fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
+ if (fd < 0) {
+ perror("connect");
+ exit(EXIT_FAILURE);
+ }
+
+ enable_so_zerocopy_check(fd);
+
+ memset(sbuf1, 'x', sizeof(sbuf1));
+ send_buf(fd, sbuf1, sizeof(sbuf1), 0, sizeof(sbuf1));
+
+ for (i = 0; i < sizeof(sbuf2); i++)
+ sbuf2[i] = rand() & 0xff;
+
+ send_buf(fd, sbuf2, sizeof(sbuf2), MSG_ZEROCOPY, sizeof(sbuf2));
+
+ hash = hash_djb2(sbuf2, sizeof(sbuf2));
+ control_writeulong(hash);
+
+ fds.fd = fd;
+ fds.events = 0;
+
+ if (poll(&fds, 1, TIMEOUT * MSEC_PER_SEC) != 1 ||
+ !(fds.revents & POLLERR)) {
+ perror("poll");
+ exit(EXIT_FAILURE);
+ }
+
+ close(fd);
+}
+
+void test_stream_msgzcopy_mangle_server(const struct test_opts *opts)
+{
+ unsigned long local_hash, remote_hash;
+ char rbuf[PAGE_SIZE + 1];
+ int fd;
+
+ fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL);
+ if (fd < 0) {
+ perror("accept");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Wait, don't race the (buggy) skbs coalescence. */
+ vsock_ioctl_int(fd, SIOCINQ, PAGE_SIZE + 1 + GOOD_COPY_LEN);
+
+ /* Discard the first packet. */
+ recv_buf(fd, rbuf, PAGE_SIZE + 1, 0, PAGE_SIZE + 1);
+
+ recv_buf(fd, rbuf, GOOD_COPY_LEN, 0, GOOD_COPY_LEN);
+ remote_hash = control_readulong();
+ local_hash = hash_djb2(rbuf, GOOD_COPY_LEN);
+
+ if (local_hash != remote_hash) {
+ fprintf(stderr, "Data received corrupted\n");
+ exit(EXIT_FAILURE);
+ }
+
+ close(fd);
+}
diff --git a/tools/testing/vsock/vsock_test_zerocopy.h b/tools/testing/vsock/vsock_test_zerocopy.h
index 3ef2579e024d..d46c91a69f16 100644
--- a/tools/testing/vsock/vsock_test_zerocopy.h
+++ b/tools/testing/vsock/vsock_test_zerocopy.h
@@ -12,4 +12,7 @@ void test_seqpacket_msgzcopy_server(const struct test_opts *opts);
void test_stream_msgzcopy_empty_errq_client(const struct test_opts *opts);
void test_stream_msgzcopy_empty_errq_server(const struct test_opts *opts);
+void test_stream_msgzcopy_mangle_client(const struct test_opts *opts);
+void test_stream_msgzcopy_mangle_server(const struct test_opts *opts);
+
#endif /* VSOCK_TEST_ZEROCOPY_H */