summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/arch/x86/include/asm/msr-index.h3
-rw-r--r--tools/include/uapi/linux/stddef.h26
-rw-r--r--tools/lib/bpf/gen_loader.c3
-rw-r--r--tools/net/ynl/Makefile.deps4
-rw-r--r--tools/net/ynl/pyynl/lib/ynl.py37
-rwxr-xr-xtools/net/ynl/pyynl/ynl_gen_c.py31
-rw-r--r--tools/perf/Makefile5
-rw-r--r--tools/perf/Makefile.perf9
-rw-r--r--tools/perf/builtin-trace.c9
-rw-r--r--tools/perf/trace/beauty/beauty.h3
-rwxr-xr-xtools/perf/trace/beauty/clone.sh4
-rw-r--r--tools/perf/trace/beauty/fsmount.c18
-rwxr-xr-xtools/perf/trace/beauty/fsmount.sh11
-rw-r--r--tools/perf/trace/beauty/fsmount_attr.sh22
-rw-r--r--tools/perf/trace/beauty/include/linux/socket.h2
-rw-r--r--tools/perf/trace/beauty/include/uapi/linux/fs.h12
-rw-r--r--tools/perf/trace/beauty/include/uapi/linux/mount.h1
-rw-r--r--tools/perf/trace/beauty/include/uapi/linux/sched.h17
-rw-r--r--tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/kfunc_dynptr_param.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/percpu_array_inner_map.c57
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c103
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sockopt_sk.c17
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tcp_hdr_options.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/verifier.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_cubic.c14
-rw-r--r--tools/testing/selftests/bpf/progs/exceptions_fail.c22
-rw-r--r--tools/testing/selftests/bpf/progs/sockopt_sk.c16
-rw-r--r--tools/testing/selftests/bpf/progs/test_misc_tcp_hdr_options.c15
-rw-r--r--tools/testing/selftests/bpf/progs/test_sockmap_ktls.c21
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_call_large_imm.c66
-rw-r--r--tools/testing/selftests/cgroup/lib/cgroup_util.c5
-rwxr-xr-xtools/testing/selftests/cgroup/test_cpuset_v1_base.sh2
-rw-r--r--tools/testing/selftests/cgroup/test_kmem.c10
-rwxr-xr-xtools/testing/selftests/drivers/net/shaper.py24
-rw-r--r--tools/testing/selftests/kvm/guest_memfd_test.c9
-rw-r--r--tools/testing/selftests/kvm/lib/elf.c2
-rw-r--r--tools/testing/selftests/kvm/steal_time.c2
-rw-r--r--tools/testing/selftests/kvm/x86/apic_bus_clock_test.c4
-rw-r--r--tools/testing/selftests/mm/hmm-tests.c50
-rwxr-xr-xtools/testing/selftests/mm/run_vmtests.sh2
-rwxr-xr-xtools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh30
-rw-r--r--tools/testing/selftests/net/lib/xdp_native.bpf.c55
-rwxr-xr-xtools/testing/selftests/net/mptcp/mptcp_connect.sh6
-rwxr-xr-xtools/testing/selftests/net/mptcp/mptcp_join.sh31
-rw-r--r--tools/testing/selftests/net/mptcp/mptcp_lib.sh10
-rwxr-xr-xtools/testing/selftests/net/ovpn/test-close-socket.sh2
-rwxr-xr-xtools/testing/selftests/net/ovpn/test-mark.sh6
-rwxr-xr-xtools/testing/selftests/net/ovpn/test.sh4
-rw-r--r--tools/testing/selftests/net/rds/config1
-rwxr-xr-xtools/testing/selftests/rdma/rxe_ipv6.sh6
-rwxr-xr-xtools/testing/selftests/rdma/rxe_rping_between_netns.sh7
-rwxr-xr-xtools/testing/selftests/rdma/rxe_socket_with_netns.sh6
-rwxr-xr-xtools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh6
-rw-r--r--tools/testing/selftests/sched_ext/dequeue.c1
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json41
-rw-r--r--tools/testing/selftests/ublk/kublk.c11
57 files changed, 802 insertions, 91 deletions
diff --git a/tools/arch/x86/include/asm/msr-index.h b/tools/arch/x86/include/asm/msr-index.h
index 6673601246b3..eff29645719b 100644
--- a/tools/arch/x86/include/asm/msr-index.h
+++ b/tools/arch/x86/include/asm/msr-index.h
@@ -793,9 +793,10 @@
#define MSR_AMD64_LBR_SELECT 0xc000010e
/* Zen4 */
-#define MSR_ZEN4_BP_CFG 0xc001102e
+#define MSR_ZEN4_BP_CFG 0xc001102e
#define MSR_ZEN4_BP_CFG_BP_SPEC_REDUCE_BIT 4
#define MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT 5
+#define MSR_ZEN2_BP_CFG_BUG_FIX_BIT 33
/* Fam 19h MSRs */
#define MSR_F19H_UMC_PERF_CTL 0xc0010800
diff --git a/tools/include/uapi/linux/stddef.h b/tools/include/uapi/linux/stddef.h
index c53cde425406..457498259494 100644
--- a/tools/include/uapi/linux/stddef.h
+++ b/tools/include/uapi/linux/stddef.h
@@ -3,7 +3,6 @@
#define _LINUX_STDDEF_H
-
#ifndef __always_inline
#define __always_inline __inline__
#endif
@@ -36,6 +35,11 @@
struct __struct_group_tag(TAG) { MEMBERS } ATTRS NAME; \
} ATTRS
+#ifdef __cplusplus
+/* sizeof(struct{}) is 1 in C++, not 0, can't use C version of the macro. */
+#define __DECLARE_FLEX_ARRAY(T, member) \
+ T member[0]
+#else
/**
* __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
*
@@ -52,3 +56,23 @@
TYPE NAME[]; \
}
#endif
+
+#ifndef __counted_by
+#define __counted_by(m)
+#endif
+
+#ifndef __counted_by_le
+#define __counted_by_le(m)
+#endif
+
+#ifndef __counted_by_be
+#define __counted_by_be(m)
+#endif
+
+#ifndef __counted_by_ptr
+#define __counted_by_ptr(m)
+#endif
+
+#define __kernel_nonstring
+
+#endif /* _LINUX_STDDEF_H */
diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c
index cd5c2543f54d..9478b8f78f26 100644
--- a/tools/lib/bpf/gen_loader.c
+++ b/tools/lib/bpf/gen_loader.c
@@ -592,13 +592,12 @@ static void emit_signature_match(struct bpf_gen *gen)
gen->hash_insn_offset[i] = gen->insn_cur - gen->insn_start;
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_3, 0, 0, 0, 0, 0));
- off = -(gen->insn_cur - gen->insn_start - gen->cleanup_label) / 8 - 1;
+ off = -(gen->insn_cur - gen->insn_start - gen->cleanup_label) / 8 - 2;
if (is_simm16(off)) {
emit(gen, BPF_MOV64_IMM(BPF_REG_7, -EINVAL));
emit(gen, BPF_JMP_REG(BPF_JNE, BPF_REG_2, BPF_REG_3, off));
} else {
gen->error = -ERANGE;
- emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, -1));
}
}
}
diff --git a/tools/net/ynl/Makefile.deps b/tools/net/ynl/Makefile.deps
index 08205f9fc525..cc53b2f21c44 100644
--- a/tools/net/ynl/Makefile.deps
+++ b/tools/net/ynl/Makefile.deps
@@ -15,9 +15,11 @@ UAPI_PATH:=../../../../include/uapi/
get_hdr_inc=-D$(1) -include $(UAPI_PATH)/linux/$(2)
get_hdr_inc2=-D$(1) -D$(2) -include $(UAPI_PATH)/linux/$(3)
+CFLAGS_dev-energymodel:=$(call get_hdr_inc,_LINUX_DEV_ENERGYMODEL_H,dev_energymodel.h)
CFLAGS_devlink:=$(call get_hdr_inc,_LINUX_DEVLINK_H_,devlink.h)
CFLAGS_dpll:=$(call get_hdr_inc,_LINUX_DPLL_H,dpll.h)
-CFLAGS_ethtool:=$(call get_hdr_inc,_LINUX_ETHTOOL_H,ethtool.h) \
+CFLAGS_ethtool:=$(call get_hdr_inc,_LINUX_TYPELIMITS_H,typelimits.h) \
+ $(call get_hdr_inc,_LINUX_ETHTOOL_H,ethtool.h) \
$(call get_hdr_inc,_LINUX_ETHTOOL_NETLINK_H_,ethtool_netlink.h) \
$(call get_hdr_inc,_LINUX_ETHTOOL_NETLINK_GENERATED_H,ethtool_netlink_generated.h)
CFLAGS_handshake:=$(call get_hdr_inc,_LINUX_HANDSHAKE_H,handshake.h)
diff --git a/tools/net/ynl/pyynl/lib/ynl.py b/tools/net/ynl/pyynl/lib/ynl.py
index f63c6f828735..010aac0c6c67 100644
--- a/tools/net/ynl/pyynl/lib/ynl.py
+++ b/tools/net/ynl/pyynl/lib/ynl.py
@@ -42,6 +42,7 @@ class Netlink:
SOL_NETLINK = 270
NETLINK_ADD_MEMBERSHIP = 1
+ NETLINK_LISTEN_ALL_NSID = 8
NETLINK_CAP_ACK = 10
NETLINK_EXT_ACK = 11
NETLINK_GET_STRICT_CHK = 12
@@ -680,6 +681,7 @@ class YnlFamily(SpecFamily):
Notification API:
ynl.ntf_subscribe(mcast_name) -- join a multicast group
+ ynl.ntf_listen_all_nsid() -- listen on all netns
ynl.check_ntf() -- drain pending notifications
ynl.poll_ntf(duration=None) -- yield notifications
@@ -748,6 +750,23 @@ class YnlFamily(SpecFamily):
self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_ADD_MEMBERSHIP,
mcast_id)
+ def ntf_listen_all_nsid(self):
+ """Enable NETLINK_LISTEN_ALL_NSID to receive notifications from all
+ namespaces that have an nsid mapped in the current one."""
+ self.sock.setsockopt(Netlink.SOL_NETLINK,
+ Netlink.NETLINK_LISTEN_ALL_NSID, 1)
+
+ @staticmethod
+ def _decode_nsid(ancdata):
+ for cmsg_level, cmsg_type, cmsg_data in ancdata:
+ if (cmsg_level == Netlink.SOL_NETLINK and
+ cmsg_type == Netlink.NETLINK_LISTEN_ALL_NSID):
+ nsid = struct.unpack('i', cmsg_data)[0]
+ if nsid >= 0:
+ return nsid
+ return None
+ return None
+
def set_recv_dbg(self, enabled):
self._recv_dbg = enabled
@@ -1235,7 +1254,7 @@ class YnlFamily(SpecFamily):
f" when parsing '{attr_spec['name']}'")
return raw
- def handle_ntf(self, decoded):
+ def handle_ntf(self, decoded, nsid=None):
msg = {}
if self.include_raw:
msg['raw'] = decoded
@@ -1246,15 +1265,22 @@ class YnlFamily(SpecFamily):
msg['name'] = op['name']
msg['msg'] = attrs
+ if nsid is not None:
+ msg['nsid'] = nsid
self.async_msg_queue.put(msg)
+ def _recvmsg(self, flags=0):
+ reply, ancdata, _, _ = self.sock.recvmsg(self._recv_size, 4096, flags)
+ return reply, ancdata
+
def check_ntf(self):
while True:
try:
- reply = self.sock.recv(self._recv_size, socket.MSG_DONTWAIT)
+ reply, ancdata = self._recvmsg(socket.MSG_DONTWAIT)
except BlockingIOError:
return
+ nsid = self._decode_nsid(ancdata)
nms = NlMsgs(reply)
self._recv_dbg_print(reply, nms)
for nl_msg in nms:
@@ -1271,7 +1297,7 @@ class YnlFamily(SpecFamily):
print("Unexpected msg id while checking for ntf", decoded)
continue
- self.handle_ntf(decoded)
+ self.handle_ntf(decoded, nsid)
def poll_ntf(self, duration=None):
start_time = time.time()
@@ -1335,7 +1361,8 @@ class YnlFamily(SpecFamily):
rsp = []
op_rsp = []
while not done:
- reply = self.sock.recv(self._recv_size)
+ reply, ancdata = self._recvmsg()
+ nsid = self._decode_nsid(ancdata)
nms = NlMsgs(reply)
self._recv_dbg_print(reply, nms)
for nl_msg in nms:
@@ -1374,7 +1401,7 @@ class YnlFamily(SpecFamily):
# Check if this is a reply to our request
if nl_msg.nl_seq not in reqs_by_seq or decoded.cmd() != op.rsp_value:
if decoded.cmd() in self.async_msg_ids:
- self.handle_ntf(decoded)
+ self.handle_ntf(decoded, nsid)
continue
print('Unexpected message: ' + repr(decoded))
continue
diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py
index 0e1e486c1185..cdc3646f2642 100755
--- a/tools/net/ynl/pyynl/ynl_gen_c.py
+++ b/tools/net/ynl/pyynl/ynl_gen_c.py
@@ -3212,6 +3212,8 @@ def render_uapi(family, cw):
for const in family['definitions']:
if const.get('header'):
continue
+ if const.get('scope', 'uapi') != 'uapi':
+ continue
if const['type'] != 'const':
cw.writes_defines(defines)
@@ -3339,6 +3341,25 @@ def render_uapi(family, cw):
cw.p(f'#endif /* {hdr_prot} */')
+def render_scoped_consts(family, cw, scope):
+ defines = []
+ for const in family['definitions']:
+ if const['type'] != 'const':
+ continue
+ if const.get('header'):
+ continue
+ if const.get('scope') != scope:
+ continue
+ name_pfx = const.get('name-prefix', f"{family.ident_name}-")
+ defines.append([
+ c_upper(family.get('c-define-name',
+ f"{name_pfx}{const['name']}")),
+ const['value']])
+ if defines:
+ cw.writes_defines(defines)
+ cw.nl()
+
+
def _render_user_ntf_entry(ri, op):
if not ri.family.is_classic():
ri.cw.block_start(line=f"[{op.enum_name}] = ")
@@ -3504,8 +3525,12 @@ def main():
cw.p('#include "ynl.h"')
headers = []
for definition in parsed['definitions'] + parsed['attribute-sets']:
- if 'header' in definition:
- headers.append(definition['header'])
+ if 'header' not in definition:
+ continue
+ scope = definition.get('scope', 'uapi')
+ if scope != 'uapi' and scope != args.mode:
+ continue
+ headers.append(definition['header'])
if args.mode == 'user':
headers.append(parsed.uapi_header)
seen_header = []
@@ -3522,6 +3547,7 @@ def main():
for one in args.user_header:
cw.p(f'#include "{one}"')
else:
+ render_scoped_consts(parsed, cw, 'user')
cw.p('struct ynl_sock;')
cw.nl()
render_user_family(parsed, cw, True)
@@ -3529,6 +3555,7 @@ def main():
if args.mode == "kernel":
if args.header:
+ render_scoped_consts(parsed, cw, 'kernel')
for _, struct in sorted(parsed.pure_nested_structs.items()):
if struct.request:
cw.p('/* Common nested types */')
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 816d5d84816b..5b713837eede 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -111,6 +111,9 @@ build-test:
build-test-tarball:
@$(MAKE) -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile SET_PARALLEL=1 --no-print-directory out
+check-headers:
+ @./check-headers.sh
+
#
# All other targets get passed through:
#
@@ -118,4 +121,4 @@ build-test-tarball:
$(print_msg)
$(make)
-.PHONY: tags TAGS FORCE Makefile
+.PHONY: tags TAGS FORCE Makefile build-test build-test-tarball check-headers
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index cee19c923c06..76b35ac19acb 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -285,7 +285,6 @@ goals := $(filter-out all sub-make, $(MAKECMDGOALS))
$(goals) all: sub-make
sub-make: fixdep
- @./check-headers.sh
$(Q)$(MAKE) FIXDEP_BUILT=1 -f Makefile.perf $(goals)
else # force_fixdep
@@ -565,6 +564,12 @@ fsmount_tbls := $(srctree)/tools/perf/trace/beauty/fsmount.sh
$(fsmount_arrays): $(beauty_uapi_linux_dir)/mount.h $(fsmount_tbls)
$(Q)$(SHELL) '$(fsmount_tbls)' $(beauty_uapi_linux_dir) > $@
+fsmount_attr_arrays := $(beauty_outdir)/fsmount_attr_arrays.c
+fsmount_attr_tbls := $(srctree)/tools/perf/trace/beauty/fsmount_attr.sh
+
+$(fsmount_attr_arrays): $(beauty_uapi_linux_dir)/mount.h $(fsmount_attr_tbls)
+ $(Q)$(SHELL) '$(fsmount_attr_tbls)' $(beauty_uapi_linux_dir) > $@
+
fspick_arrays := $(beauty_outdir)/fspick_arrays.c
fspick_tbls := $(srctree)/tools/perf/trace/beauty/fspick.sh
@@ -855,6 +860,7 @@ prepare: $(OUTPUT)PERF-VERSION-FILE archheaders \
$(fadvise_advice_array) \
$(fsconfig_arrays) \
$(fsmount_arrays) \
+ $(fsmount_attr_arrays) \
$(fspick_arrays) \
$(pkey_alloc_access_rights_array) \
$(sndrv_pcm_ioctl_array) \
@@ -1302,6 +1308,7 @@ clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $(
$(OUTPUT)$(fadvise_advice_array) \
$(OUTPUT)$(fsconfig_arrays) \
$(OUTPUT)$(fsmount_arrays) \
+ $(OUTPUT)$(fsmount_attr_arrays) \
$(OUTPUT)$(fspick_arrays) \
$(OUTPUT)$(madvise_behavior_array) \
$(OUTPUT)$(mmap_flags_array) \
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index e58c49d047a2..48615ddccd93 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -771,11 +771,6 @@ static const char *bpf_cmd[] = {
};
static DEFINE_STRARRAY(bpf_cmd, "BPF_");
-static const char *fsmount_flags[] = {
- [1] = "CLOEXEC",
-};
-static DEFINE_STRARRAY(fsmount_flags, "FSMOUNT_");
-
#include "trace/beauty/generated/fsconfig_arrays.c"
static DEFINE_STRARRAY(fsconfig_cmds, "FSCONFIG_");
@@ -1202,7 +1197,9 @@ static const struct syscall_fmt syscall_fmts[] = {
{ .name = "fsconfig",
.arg = { [1] = STRARRAY(cmd, fsconfig_cmds), }, },
{ .name = "fsmount",
- .arg = { [1] = STRARRAY_FLAGS(flags, fsmount_flags),
+ .arg = { [1] = { .scnprintf = SCA_FSMOUNT_FLAGS, /* fsmount_flags */
+ .strtoul = STUL_STRARRAYS,
+ .show_zero = true, },
[2] = { .scnprintf = SCA_FSMOUNT_ATTR_FLAGS, /* attr_flags */ }, }, },
{ .name = "fspick",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 0a07ad158f87..a90c35fa5c12 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -179,6 +179,9 @@ size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_ar
size_t syscall_arg__scnprintf_flock(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_FLOCK syscall_arg__scnprintf_flock
+size_t syscall_arg__scnprintf_fsmount_flags(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_FSMOUNT_FLAGS syscall_arg__scnprintf_fsmount_flags
+
size_t syscall_arg__scnprintf_fsmount_attr_flags(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_FSMOUNT_ATTR_FLAGS syscall_arg__scnprintf_fsmount_attr_flags
diff --git a/tools/perf/trace/beauty/clone.sh b/tools/perf/trace/beauty/clone.sh
index 18b6c0d75693..98cb1f8d4a6f 100755
--- a/tools/perf/trace/beauty/clone.sh
+++ b/tools/perf/trace/beauty/clone.sh
@@ -14,4 +14,8 @@ regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+CLONE_([^_]+[[:alnum:]_]+)[[:
grep -E $regex ${linux_sched} | \
sed -r "s/$regex/\2 \1/g" | \
xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n"
+regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+CLONE_([^_]+[[:alnum:]_]+)[[:space:]]+\(1ULL[[:space:]]*<<[[:space:]]*([[:digit:]]+)\)[[:space:]]*.*'
+grep -E $regex ${linux_sched} | \
+ sed -r "s/$regex/\2 \1/g" | \
+ xargs printf "\t[%s + 1] = \"%s\",\n"
printf "};\n"
diff --git a/tools/perf/trace/beauty/fsmount.c b/tools/perf/trace/beauty/fsmount.c
index 28c2c16fc1a8..179e649fc72a 100644
--- a/tools/perf/trace/beauty/fsmount.c
+++ b/tools/perf/trace/beauty/fsmount.c
@@ -16,9 +16,25 @@
#define MOUNT_ATTR_RELATIME 0x00000000 /* - Update atime relative to mtime/ctime. */
#endif
-static size_t fsmount__scnprintf_attr_flags(unsigned long flags, char *bf, size_t size, bool show_prefix)
+
+static size_t fsmount__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix)
{
#include "trace/beauty/generated/fsmount_arrays.c"
+ static DEFINE_STRARRAY(fsmount_flags, "FSMOUNT_");
+
+ return strarray__scnprintf_flags(&strarray__fsmount_flags, bf, size, show_prefix, flags);
+}
+
+size_t syscall_arg__scnprintf_fsmount_flags(char *bf, size_t size, struct syscall_arg *arg)
+{
+ unsigned long flags = arg->val;
+
+ return fsmount__scnprintf_flags(flags, bf, size, arg->show_string_prefix);
+}
+
+static size_t fsmount__scnprintf_attr_flags(unsigned long flags, char *bf, size_t size, bool show_prefix)
+{
+#include "trace/beauty/generated/fsmount_attr_arrays.c"
static DEFINE_STRARRAY(fsmount_attr_flags, "MOUNT_ATTR_");
size_t printed = 0;
diff --git a/tools/perf/trace/beauty/fsmount.sh b/tools/perf/trace/beauty/fsmount.sh
index 6b67a54cdeee..6d1e80bc15e4 100755
--- a/tools/perf/trace/beauty/fsmount.sh
+++ b/tools/perf/trace/beauty/fsmount.sh
@@ -9,14 +9,9 @@ fi
linux_mount=${beauty_uapi_linux_dir}/mount.h
-# Remove MOUNT_ATTR_RELATIME as it is zeros, handle it a special way in the beautifier
-# Only handle MOUNT_ATTR_ followed by a capital letter/num as __ is special case
-# for things like MOUNT_ATTR__ATIME that is a mask for the possible ATIME handling
-# bits. Special case it as well in the beautifier
-
-printf "static const char *fsmount_attr_flags[] = {\n"
-regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MOUNT_ATTR_([[:alnum:]][[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
-grep -E $regex ${linux_mount} | grep -v MOUNT_ATTR_RELATIME | \
+printf "static const char *fsmount_flags[] = {\n"
+regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+FSMOUNT_([[:alnum:]][[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
+grep -E $regex ${linux_mount} | \
sed -r "s/$regex/\2 \1/g" | \
xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n"
printf "};\n"
diff --git a/tools/perf/trace/beauty/fsmount_attr.sh b/tools/perf/trace/beauty/fsmount_attr.sh
new file mode 100644
index 000000000000..6b67a54cdeee
--- /dev/null
+++ b/tools/perf/trace/beauty/fsmount_attr.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1
+
+if [ $# -ne 1 ] ; then
+ beauty_uapi_linux_dir=tools/perf/trace/beauty/include/uapi/linux/
+else
+ beauty_uapi_linux_dir=$1
+fi
+
+linux_mount=${beauty_uapi_linux_dir}/mount.h
+
+# Remove MOUNT_ATTR_RELATIME as it is zeros, handle it a special way in the beautifier
+# Only handle MOUNT_ATTR_ followed by a capital letter/num as __ is special case
+# for things like MOUNT_ATTR__ATIME that is a mask for the possible ATIME handling
+# bits. Special case it as well in the beautifier
+
+printf "static const char *fsmount_attr_flags[] = {\n"
+regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MOUNT_ATTR_([[:alnum:]][[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
+grep -E $regex ${linux_mount} | grep -v MOUNT_ATTR_RELATIME | \
+ sed -r "s/$regex/\2 \1/g" | \
+ xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n"
+printf "};\n"
diff --git a/tools/perf/trace/beauty/include/linux/socket.h b/tools/perf/trace/beauty/include/linux/socket.h
index ec715ad4bf25..ec4a0a025793 100644
--- a/tools/perf/trace/beauty/include/linux/socket.h
+++ b/tools/perf/trace/beauty/include/linux/socket.h
@@ -415,7 +415,7 @@ struct __kernel_timespec;
struct old_timespec32;
struct scm_timestamping_internal {
- struct timespec64 ts[3];
+ ktime_t ts[3];
};
extern void put_cmsg_scm_timestamping64(struct msghdr *msg, struct scm_timestamping_internal *tss);
diff --git a/tools/perf/trace/beauty/include/uapi/linux/fs.h b/tools/perf/trace/beauty/include/uapi/linux/fs.h
index 70b2b661f42c..13f71202845e 100644
--- a/tools/perf/trace/beauty/include/uapi/linux/fs.h
+++ b/tools/perf/trace/beauty/include/uapi/linux/fs.h
@@ -657,4 +657,16 @@ struct procmap_query {
__u64 build_id_addr; /* in */
};
+/*
+ * Shutdown the filesystem.
+ */
+#define FS_IOC_SHUTDOWN _IOR('X', 125, __u32)
+
+/*
+ * Flags for FS_IOC_SHUTDOWN
+ */
+#define FS_SHUTDOWN_FLAGS_DEFAULT 0x0
+#define FS_SHUTDOWN_FLAGS_LOGFLUSH 0x1 /* flush log but not data*/
+#define FS_SHUTDOWN_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
+
#endif /* _UAPI_LINUX_FS_H */
diff --git a/tools/perf/trace/beauty/include/uapi/linux/mount.h b/tools/perf/trace/beauty/include/uapi/linux/mount.h
index d9d86598d100..2204708dbf7a 100644
--- a/tools/perf/trace/beauty/include/uapi/linux/mount.h
+++ b/tools/perf/trace/beauty/include/uapi/linux/mount.h
@@ -110,6 +110,7 @@ enum fsconfig_command {
* fsmount() flags.
*/
#define FSMOUNT_CLOEXEC 0x00000001
+#define FSMOUNT_NAMESPACE 0x00000002 /* Create the mount in a new mount namespace */
/*
* Mount attributes.
diff --git a/tools/perf/trace/beauty/include/uapi/linux/sched.h b/tools/perf/trace/beauty/include/uapi/linux/sched.h
index 359a14cc76a4..33a4624285cd 100644
--- a/tools/perf/trace/beauty/include/uapi/linux/sched.h
+++ b/tools/perf/trace/beauty/include/uapi/linux/sched.h
@@ -34,8 +34,12 @@
#define CLONE_IO 0x80000000 /* Clone io context */
/* Flags for the clone3() syscall. */
-#define CLONE_CLEAR_SIGHAND 0x100000000ULL /* Clear any signal handler and reset to SIG_DFL. */
-#define CLONE_INTO_CGROUP 0x200000000ULL /* Clone into a specific cgroup given the right permissions. */
+#define CLONE_CLEAR_SIGHAND (1ULL << 32) /* Clear any signal handler and reset to SIG_DFL. */
+#define CLONE_INTO_CGROUP (1ULL << 33) /* Clone into a specific cgroup given the right permissions. */
+#define CLONE_AUTOREAP (1ULL << 34) /* Auto-reap child on exit. */
+#define CLONE_NNP (1ULL << 35) /* Set no_new_privs on child. */
+#define CLONE_PIDFD_AUTOKILL (1ULL << 36) /* Kill child when clone pidfd closes. */
+#define CLONE_EMPTY_MNTNS (1ULL << 37) /* Create an empty mount namespace. */
/*
* cloning flags intersect with CSIGNAL so can be used with unshare and clone3
@@ -43,6 +47,12 @@
*/
#define CLONE_NEWTIME 0x00000080 /* New time namespace */
+/*
+ * unshare flags share the bit space with clone flags but only apply to the
+ * unshare syscall:
+ */
+#define UNSHARE_EMPTY_MNTNS 0x00100000 /* Unshare an empty mount namespace. */
+
#ifndef __ASSEMBLY__
/**
* struct clone_args - arguments for the clone3 syscall
@@ -146,4 +156,7 @@ struct clone_args {
SCHED_FLAG_KEEP_ALL | \
SCHED_FLAG_UTIL_CLAMP)
+/* Only for sched_getattr() own flag param, if task is SCHED_DEADLINE */
+#define SCHED_GETATTR_FLAG_DL_DYNAMIC 0x01
+
#endif /* _UAPI_LINUX_SCHED_H */
diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c
index f829b6f09bc9..fe30181e6336 100644
--- a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c
+++ b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c
@@ -112,6 +112,10 @@ static void test_cubic(void)
ASSERT_EQ(cubic_skel->bss->bpf_cubic_acked_called, 1, "pkts_acked called");
+ ASSERT_TRUE(cubic_skel->bss->nodelay_init_reject, "init reject nodelay option");
+ ASSERT_TRUE(cubic_skel->bss->nodelay_cwnd_event_tx_start_reject,
+ "cwnd_event_tx_start reject nodelay option");
+
bpf_link__destroy(link);
bpf_cubic__destroy(cubic_skel);
}
diff --git a/tools/testing/selftests/bpf/prog_tests/kfunc_dynptr_param.c b/tools/testing/selftests/bpf/prog_tests/kfunc_dynptr_param.c
index 8cd298b78e44..04aaf4c9cf5e 100644
--- a/tools/testing/selftests/bpf/prog_tests/kfunc_dynptr_param.c
+++ b/tools/testing/selftests/bpf/prog_tests/kfunc_dynptr_param.c
@@ -14,7 +14,7 @@ static struct {
const char *prog_name;
int expected_runtime_err;
} kfunc_dynptr_tests[] = {
- {"dynptr_data_null", -EBADMSG},
+ {"dynptr_data_null", -EINVAL},
};
static bool kfunc_not_supported;
diff --git a/tools/testing/selftests/bpf/prog_tests/percpu_array_inner_map.c b/tools/testing/selftests/bpf/prog_tests/percpu_array_inner_map.c
new file mode 100644
index 000000000000..2a8b2381306b
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/percpu_array_inner_map.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_progs.h>
+
+/*
+ * Test that replacing an inner percpu array map with one that has different
+ * max_entries is rejected. percpu_array_map_gen_lookup() inlines the
+ * template's index_mask, so allowing a smaller replacement would cause OOB.
+ */
+void test_percpu_array_inner_map(void)
+{
+ LIBBPF_OPTS(bpf_map_create_opts, opts);
+ int outer_fd, tmpl_fd, good_fd, bad_fd, err;
+ int zero = 0;
+
+ /* Create template: percpu array with 8 entries */
+ tmpl_fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, "tmpl",
+ sizeof(int), sizeof(long), 8, NULL);
+ if (!ASSERT_OK_FD(tmpl_fd, "create_tmpl"))
+ return;
+
+ /* Create outer array-of-maps using template */
+ opts.inner_map_fd = tmpl_fd;
+ outer_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS, "outer",
+ sizeof(int), sizeof(int), 1, &opts);
+ if (!ASSERT_OK_FD(outer_fd, "create_outer"))
+ goto close_tmpl;
+
+ /* Insert template as initial inner map */
+ err = bpf_map_update_elem(outer_fd, &zero, &tmpl_fd, 0);
+ if (!ASSERT_OK(err, "insert_tmpl"))
+ goto close_outer;
+
+ /* Replacement with same max_entries should succeed */
+ good_fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, "good",
+ sizeof(int), sizeof(long), 8, NULL);
+ if (!ASSERT_OK_FD(good_fd, "create_good"))
+ goto close_outer;
+
+ err = bpf_map_update_elem(outer_fd, &zero, &good_fd, 0);
+ ASSERT_OK(err, "replace_same_max_entries");
+ close(good_fd);
+
+ /* Replacement with fewer max_entries must fail */
+ bad_fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, "bad",
+ sizeof(int), sizeof(long), 2, NULL);
+ if (!ASSERT_OK_FD(bad_fd, "create_bad"))
+ goto close_outer;
+
+ err = bpf_map_update_elem(outer_fd, &zero, &bad_fd, 0);
+ ASSERT_ERR(err, "replace_smaller_max_entries");
+ close(bad_fd);
+
+close_outer:
+ close(outer_fd);
+close_tmpl:
+ close(tmpl_fd);
+}
diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c b/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c
index b87e7f39e15a..6ed8e149e3d5 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c
@@ -417,6 +417,107 @@ static void run_tests(int family, enum bpf_map_type map_type)
close(map);
}
+/*
+ * Regression test for the KTLS + sockmap (verdict) reverse-order UAF.
+ *
+ * Vulnerable sequence:
+ * 1. Insert receiver socket into sockmap with BPF_SK_SKB_VERDICT program.
+ * sk->sk_data_ready becomes sk_psock_verdict_data_ready.
+ * 2. Configure TLS RX: tls_sw_strparser_arm() saves
+ * sk_psock_verdict_data_ready as rx_ctx->saved_data_ready.
+ *
+ * When data arrives, tls_rx_msg_ready() calls saved_data_ready() =
+ * sk_psock_verdict_data_ready(), which calls tcp_read_skb() and drains
+ * sk_receive_queue via __skb_unlink() without advancing copied_seq.
+ * tls_strp_msg_load() then finds the queue empty while tcp_inq() is still
+ * non-zero, hits WARN_ON_ONCE(!first), and leaves a dangling frag_list
+ * pointer that tls_decrypt_sg() walks — a use-after-free.
+ *
+ * The fix adds a tls_sw_has_ctx_rx() check to sk_psock_verdict_data_ready(),
+ * mirroring what sk_psock_strp_data_ready() already does: when a TLS RX
+ * context is present, defer to psock->saved_data_ready (sock_def_readable)
+ * instead of calling tcp_read_skb(), so TLS retains sole ownership of the
+ * receive queue. Data is then decrypted and returned correctly by
+ * tls_sw_recvmsg().
+ */
+static void test_sockmap_ktls_verdict_with_tls_rx(int family, int sotype)
+{
+ struct tls12_crypto_info_aes_gcm_128 crypto_info = {};
+ char send_buf[] = "hello ktls sockmap reverse order";
+ char recv_buf[sizeof(send_buf)] = {};
+ struct test_sockmap_ktls *skel;
+ int c = -1, p = -1, zero = 0;
+ int prog_fd, map_fd;
+ ssize_t n;
+ int err;
+
+ skel = test_sockmap_ktls__open_and_load();
+ if (!ASSERT_TRUE(skel, "open_and_load"))
+ return;
+
+ err = create_pair(family, sotype, &c, &p);
+ if (!ASSERT_OK(err, "create_pair"))
+ goto out;
+
+ prog_fd = bpf_program__fd(skel->progs.prog_skb_verdict_pass);
+ map_fd = bpf_map__fd(skel->maps.sock_map_verdict);
+
+ err = bpf_prog_attach(prog_fd, map_fd, BPF_SK_SKB_VERDICT, 0);
+ if (!ASSERT_OK(err, "bpf_prog_attach sk_skb verdict"))
+ goto out;
+
+ /* Step 1: configure TLS TX on sender (no sockmap involvement) */
+ err = setsockopt(c, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls"));
+ if (!ASSERT_OK(err, "setsockopt(TCP_ULP) client"))
+ goto out;
+
+ crypto_info.info.version = TLS_1_2_VERSION;
+ crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;
+ memset(crypto_info.key, 0x01, sizeof(crypto_info.key));
+ memset(crypto_info.salt, 0x02, sizeof(crypto_info.salt));
+
+ err = setsockopt(c, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info));
+ if (!ASSERT_OK(err, "setsockopt(TLS_TX)"))
+ goto out;
+
+ /* Step 2: insert receiver into sockmap BEFORE TLS RX */
+ err = bpf_map_update_elem(map_fd, &zero, &p, BPF_NOEXIST);
+ if (!ASSERT_OK(err, "bpf_map_update_elem"))
+ goto out;
+
+ /* Step 3: configure TLS RX AFTER sockmap insertion */
+ err = setsockopt(p, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls"));
+ if (!ASSERT_OK(err, "setsockopt(TCP_ULP) server"))
+ goto out;
+
+ err = setsockopt(p, SOL_TLS, TLS_RX, &crypto_info, sizeof(crypto_info));
+ if (!ASSERT_OK(err, "setsockopt(TLS_RX)"))
+ goto out;
+
+ /*
+ * A buggy kernel hits WARN_ON_ONCE in tls_strp_load_anchor_with_queue
+ * and may UAF in tls_decrypt_sg here. With the fix,
+ * sk_psock_verdict_data_ready defers to sock_def_readable and TLS
+ * decrypts the record normally.
+ */
+ n = send(c, send_buf, sizeof(send_buf), 0);
+ if (!ASSERT_EQ(n, (ssize_t)sizeof(send_buf), "send"))
+ goto out;
+
+ n = recv_timeout(p, recv_buf, sizeof(recv_buf), 0, 5);
+ if (!ASSERT_EQ(n, (ssize_t)sizeof(send_buf), "recv"))
+ goto out;
+
+ ASSERT_OK(memcmp(send_buf, recv_buf, sizeof(send_buf)), "data integrity");
+
+out:
+ if (c != -1)
+ close(c);
+ if (p != -1)
+ close(p);
+ test_sockmap_ktls__destroy(skel);
+}
+
static void run_ktls_test(int family, int sotype)
{
if (test__start_subtest("tls simple offload"))
@@ -429,6 +530,8 @@ static void run_ktls_test(int family, int sotype)
test_sockmap_ktls_tx_no_buf(family, sotype, true);
if (test__start_subtest("tls tx with pop"))
test_sockmap_ktls_tx_pop(family, sotype);
+ if (test__start_subtest("tls verdict with tls rx"))
+ test_sockmap_ktls_verdict_with_tls_rx(family, sotype);
}
void test_sockmap_ktls(void)
diff --git a/tools/testing/selftests/bpf/prog_tests/sockopt_sk.c b/tools/testing/selftests/bpf/prog_tests/sockopt_sk.c
index 53637431ec5d..3a41c517b918 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockopt_sk.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockopt_sk.c
@@ -190,7 +190,7 @@ static int getsetsockopt(void)
fd = socket(AF_NETLINK, SOCK_RAW, 0);
if (fd < 0) {
log_err("Failed to create AF_NETLINK socket");
- return -1;
+ goto err;
}
buf.u32 = 1;
@@ -211,6 +211,21 @@ static int getsetsockopt(void)
}
ASSERT_EQ(optlen, 8, "Unexpected NETLINK_LIST_MEMBERSHIPS value");
+ /* Trick bpf_tcp_sock() with IPPROTO_TCP */
+ close(fd);
+ fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
+ if (!ASSERT_OK_FD(fd, "socket"))
+ goto err;
+
+ /* The BPF prog intercepts this before the kernel sees it, any
+ * optlen works. Go with 4 bytes for simplicity.
+ */
+ buf.u32 = 1;
+ optlen = sizeof(buf.u32);
+ err = setsockopt(fd, SOL_TCP, TCP_SAVED_SYN, &buf, optlen);
+ if (!ASSERT_ERR(err, "setsockopt(TCP_SAVED_SYN)"))
+ goto err;
+
free(big_buf);
close(fd);
return 0;
diff --git a/tools/testing/selftests/bpf/prog_tests/tcp_hdr_options.c b/tools/testing/selftests/bpf/prog_tests/tcp_hdr_options.c
index 56685fc03c7e..80e6315da2a5 100644
--- a/tools/testing/selftests/bpf/prog_tests/tcp_hdr_options.c
+++ b/tools/testing/selftests/bpf/prog_tests/tcp_hdr_options.c
@@ -507,6 +507,10 @@ static void misc(void)
ASSERT_EQ(misc_skel->bss->nr_hwtstamp, 0, "nr_hwtstamp");
+ ASSERT_TRUE(misc_skel->bss->nodelay_est_ok, "nodelay_est_ok");
+ ASSERT_TRUE(misc_skel->bss->nodelay_hdr_len_reject, "nodelay_hdr_len_reject");
+ ASSERT_TRUE(misc_skel->bss->nodelay_write_hdr_reject, "nodelay_write_hdr_reject");
+
check_linum:
ASSERT_FALSE(check_error_linum(&sk_fds), "check_error_linum");
sk_fds_close(&sk_fds);
diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c
index a96b25ebff23..06cd24e37b3f 100644
--- a/tools/testing/selftests/bpf/prog_tests/verifier.c
+++ b/tools/testing/selftests/bpf/prog_tests/verifier.c
@@ -22,6 +22,7 @@
#include "verifier_bswap.skel.h"
#include "verifier_btf_ctx_access.skel.h"
#include "verifier_btf_unreliable_prog.skel.h"
+#include "verifier_call_large_imm.skel.h"
#include "verifier_cfg.skel.h"
#include "verifier_cgroup_inv_retcode.skel.h"
#include "verifier_cgroup_skb.skel.h"
@@ -170,6 +171,7 @@ void test_verifier_bpf_trap(void) { RUN(verifier_bpf_trap); }
void test_verifier_bswap(void) { RUN(verifier_bswap); }
void test_verifier_btf_ctx_access(void) { RUN(verifier_btf_ctx_access); }
void test_verifier_btf_unreliable_prog(void) { RUN(verifier_btf_unreliable_prog); }
+void test_verifier_call_large_imm(void) { RUN(verifier_call_large_imm); }
void test_verifier_cfg(void) { RUN(verifier_cfg); }
void test_verifier_cgroup_inv_retcode(void) { RUN(verifier_cgroup_inv_retcode); }
void test_verifier_cgroup_skb(void) { RUN(verifier_cgroup_skb); }
diff --git a/tools/testing/selftests/bpf/progs/bpf_cubic.c b/tools/testing/selftests/bpf/progs/bpf_cubic.c
index ce18a4db813f..ebd5a1e69f56 100644
--- a/tools/testing/selftests/bpf/progs/bpf_cubic.c
+++ b/tools/testing/selftests/bpf/progs/bpf_cubic.c
@@ -16,6 +16,7 @@
#include "bpf_tracing_net.h"
#include <bpf/bpf_tracing.h>
+#include <errno.h>
char _license[] SEC("license") = "GPL";
@@ -170,10 +171,18 @@ static void bictcp_hystart_reset(struct sock *sk)
ca->sample_cnt = 0;
}
+bool nodelay_init_reject = false;
+bool nodelay_cwnd_event_tx_start_reject = false;
+
SEC("struct_ops")
void BPF_PROG(bpf_cubic_init, struct sock *sk)
{
struct bpf_bictcp *ca = inet_csk_ca(sk);
+ int true_val = 1, ret;
+
+ ret = bpf_setsockopt(sk, SOL_TCP, TCP_NODELAY, &true_val, sizeof(true_val));
+ if (ret == -EOPNOTSUPP)
+ nodelay_init_reject = true;
bictcp_reset(ca);
@@ -189,8 +198,13 @@ void BPF_PROG(bpf_cubic_cwnd_event_tx_start, struct sock *sk)
{
struct bpf_bictcp *ca = inet_csk_ca(sk);
__u32 now = tcp_jiffies32;
+ int true_val = 1, ret;
__s32 delta;
+ ret = bpf_setsockopt(sk, SOL_TCP, TCP_NODELAY, &true_val, sizeof(true_val));
+ if (ret == -EOPNOTSUPP)
+ nodelay_cwnd_event_tx_start_reject = true;
+
delta = now - tcp_sk(sk)->lsndtime;
/* We were application limited (idle) for a while.
diff --git a/tools/testing/selftests/bpf/progs/exceptions_fail.c b/tools/testing/selftests/bpf/progs/exceptions_fail.c
index 051e2b6f2694..ac44d60e5066 100644
--- a/tools/testing/selftests/bpf/progs/exceptions_fail.c
+++ b/tools/testing/selftests/bpf/progs/exceptions_fail.c
@@ -208,6 +208,28 @@ int reject_with_reference(void *ctx)
return 0;
}
+__noinline int global_subprog_may_throw(struct __sk_buff *ctx)
+{
+ if (ctx->len)
+ bpf_throw(0);
+ return 0;
+}
+
+SEC("?tc")
+__failure __msg("Unreleased reference")
+int reject_global_subprog_throw_with_reference(struct __sk_buff *ctx)
+{
+ struct foo *f;
+
+ f = bpf_obj_new(typeof(*f));
+ if (!f)
+ return 0;
+ if (ctx->protocol)
+ global_subprog_may_throw(ctx);
+ bpf_obj_drop(f);
+ return 0;
+}
+
__noinline static int subprog_ref(struct __sk_buff *ctx)
{
struct foo *f;
diff --git a/tools/testing/selftests/bpf/progs/sockopt_sk.c b/tools/testing/selftests/bpf/progs/sockopt_sk.c
index cb990a7d3d45..5e0b27e7855c 100644
--- a/tools/testing/selftests/bpf/progs/sockopt_sk.c
+++ b/tools/testing/selftests/bpf/progs/sockopt_sk.c
@@ -149,6 +149,20 @@ int _setsockopt(struct bpf_sockopt *ctx)
if (sk && sk->family == AF_NETLINK)
goto out;
+ if (sk && sk->family == AF_INET && sk->type == SOCK_RAW) {
+ struct bpf_tcp_sock *tp = bpf_tcp_sock(sk);
+
+ if (tp) {
+ char saved_syn[60];
+
+ bpf_getsockopt(sk, SOL_TCP, TCP_SAVED_SYN,
+ &saved_syn, sizeof(saved_syn));
+ goto consumed;
+ }
+
+ goto out;
+ }
+
/* Make sure bpf_get_netns_cookie is callable.
*/
if (bpf_get_netns_cookie(NULL) == 0)
@@ -224,6 +238,8 @@ int _setsockopt(struct bpf_sockopt *ctx)
return 0; /* couldn't get sk storage */
storage->val = optval[0];
+
+consumed:
ctx->optlen = -1; /* BPF has consumed this option, don't call kernel
* setsockopt handler.
*/
diff --git a/tools/testing/selftests/bpf/progs/test_misc_tcp_hdr_options.c b/tools/testing/selftests/bpf/progs/test_misc_tcp_hdr_options.c
index d487153a839d..ed5a0011b863 100644
--- a/tools/testing/selftests/bpf/progs/test_misc_tcp_hdr_options.c
+++ b/tools/testing/selftests/bpf/progs/test_misc_tcp_hdr_options.c
@@ -29,6 +29,10 @@ unsigned int nr_syn = 0;
unsigned int nr_fin = 0;
unsigned int nr_hwtstamp = 0;
+bool nodelay_est_ok = false;
+bool nodelay_hdr_len_reject = false;
+bool nodelay_write_hdr_reject = false;
+
/* Check the header received from the active side */
static int __check_active_hdr_in(struct bpf_sock_ops *skops, bool check_syn)
{
@@ -300,7 +304,7 @@ static int handle_passive_estab(struct bpf_sock_ops *skops)
SEC("sockops")
int misc_estab(struct bpf_sock_ops *skops)
{
- int true_val = 1;
+ int true_val = 1, false_val = 0, ret;
switch (skops->op) {
case BPF_SOCK_OPS_TCP_LISTEN_CB:
@@ -316,10 +320,19 @@ int misc_estab(struct bpf_sock_ops *skops)
case BPF_SOCK_OPS_PARSE_HDR_OPT_CB:
return handle_parse_hdr(skops);
case BPF_SOCK_OPS_HDR_OPT_LEN_CB:
+ ret = bpf_setsockopt(skops, SOL_TCP, TCP_NODELAY, &true_val, sizeof(true_val));
+ if (ret == -EOPNOTSUPP)
+ nodelay_hdr_len_reject = true;
return handle_hdr_opt_len(skops);
case BPF_SOCK_OPS_WRITE_HDR_OPT_CB:
+ ret = bpf_setsockopt(skops, SOL_TCP, TCP_NODELAY, &true_val, sizeof(true_val));
+ if (ret == -EOPNOTSUPP)
+ nodelay_write_hdr_reject = true;
return handle_write_hdr_opt(skops);
case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
+ ret = bpf_setsockopt(skops, SOL_TCP, TCP_NODELAY, &false_val, sizeof(false_val));
+ if (!ret)
+ nodelay_est_ok = true;
return handle_passive_estab(skops);
}
diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_ktls.c b/tools/testing/selftests/bpf/progs/test_sockmap_ktls.c
index 83df4919c224..facafeaf4620 100644
--- a/tools/testing/selftests/bpf/progs/test_sockmap_ktls.c
+++ b/tools/testing/selftests/bpf/progs/test_sockmap_ktls.c
@@ -17,6 +17,13 @@ struct {
__type(value, int);
} sock_map SEC(".maps");
+struct {
+ __uint(type, BPF_MAP_TYPE_SOCKMAP);
+ __uint(max_entries, 2);
+ __type(key, int);
+ __type(value, int);
+} sock_map_verdict SEC(".maps");
+
SEC("sk_msg")
int prog_sk_policy(struct sk_msg_md *msg)
{
@@ -38,3 +45,17 @@ int prog_sk_policy_redir(struct sk_msg_md *msg)
bpf_msg_apply_bytes(msg, apply_bytes);
return bpf_msg_redirect_map(msg, &sock_map, two, 0);
}
+
+/*
+ * Verdict program for the reverse-order TLS/sockmap regression test.
+ * Returns SK_PASS so tcp_read_skb() drains the receive queue via
+ * sk_psock_verdict_recv() without calling tcp_eat_skb(), which is
+ * the precondition for the KTLS strparser frag_list UAF.
+ */
+SEC("sk_skb/verdict")
+int prog_skb_verdict_pass(struct __sk_buff *skb)
+{
+ return SK_PASS;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_call_large_imm.c b/tools/testing/selftests/bpf/progs/verifier_call_large_imm.c
new file mode 100644
index 000000000000..7998df07f6a6
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/verifier_call_large_imm.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+int call_happened = 0;
+
+/*
+ * 32765 is the exact minimum number of padding instructions needed to
+ * trigger the verifier failure, because:
+ * 1. Counting the wrapper instructions around the padding block (one
+ * "r0=0" and two "exit" instructions), the actual jump distance
+ * evaluates to N + 3.
+ * 2. To overflow the s16 max bound (32767), we need N + 3 > 32767.
+ * Thus, N = 32765 is the exact minimum padding size required.
+ */
+static __attribute__((noinline)) void padding_subprog(void)
+{
+ asm volatile (
+ "r0 = 0;"
+ ".rept 32765;"
+ "r0 += 0;"
+ ".endr;"
+ ::: __clobber_all);
+}
+
+static __attribute__((noinline)) int target_subprog(void)
+{
+ /* Use volatile variable here to prevent optimization. */
+ volatile int magic_ret = 3;
+ return magic_ret;
+}
+
+SEC("syscall")
+__success __retval(3)
+int call_large_imm_test(void *ctx)
+{
+ /*
+ * Landing pad to handle call error on kernel without the fix,
+ * preventing kernel panic.
+ */
+ asm volatile (
+ "r0 = 0;"
+ ".rept 32768;"
+ "r0 += 0;"
+ ".endr;"
+ ::: __clobber_all);
+
+ /*
+ * The call_happened variable is 1 only when the call insn wrongly
+ * go back to the landing pad above.
+ */
+ if (call_happened == 1) {
+ /* Use volatile variable here to prevent optimization. */
+ volatile int flag = -1;
+ return flag;
+ }
+
+ call_happened = 1;
+
+ padding_subprog();
+
+ return target_subprog();
+}
+
+char LICENSE[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/cgroup/lib/cgroup_util.c b/tools/testing/selftests/cgroup/lib/cgroup_util.c
index 6a7295347e90..42f54936f4bb 100644
--- a/tools/testing/selftests/cgroup/lib/cgroup_util.c
+++ b/tools/testing/selftests/cgroup/lib/cgroup_util.c
@@ -106,8 +106,9 @@ int cg_read_strcmp(const char *cgroup, const char *control,
/* Handle the case of comparing against empty string */
if (!expected)
return -1;
- else
- size = strlen(expected) + 1;
+
+ /* needs size > 1, otherwise cg_read() reads 0 bytes */
+ size = (expected[0] == '\0') ? 2 : strlen(expected) + 1;
buf = malloc(size);
if (!buf)
diff --git a/tools/testing/selftests/cgroup/test_cpuset_v1_base.sh b/tools/testing/selftests/cgroup/test_cpuset_v1_base.sh
index 42a6628fb8bc..1c0444729e70 100755
--- a/tools/testing/selftests/cgroup/test_cpuset_v1_base.sh
+++ b/tools/testing/selftests/cgroup/test_cpuset_v1_base.sh
@@ -18,7 +18,7 @@ write_test() {
echo "testing $interface $value"
echo $value > $dir/$interface
new=$(cat $dir/$interface)
- [[ $value -ne $(cat $dir/$interface) ]] && {
+ [[ "$value" != "$new" ]] && {
echo "$interface write $value failed: new:$new"
exit 1
}
diff --git a/tools/testing/selftests/cgroup/test_kmem.c b/tools/testing/selftests/cgroup/test_kmem.c
index eeabd34bf083..12f59925500b 100644
--- a/tools/testing/selftests/cgroup/test_kmem.c
+++ b/tools/testing/selftests/cgroup/test_kmem.c
@@ -368,11 +368,15 @@ static int test_percpu_basic(const char *root)
for (i = 0; i < 1000; i++) {
child = cg_name_indexed(parent, "child", i);
- if (!child)
- return -1;
+ if (!child) {
+ ret = -1;
+ goto cleanup_children;
+ }
- if (cg_create(child))
+ if (cg_create(child)) {
+ free(child);
goto cleanup_children;
+ }
free(child);
}
diff --git a/tools/testing/selftests/drivers/net/shaper.py b/tools/testing/selftests/drivers/net/shaper.py
index 11310f19bfa0..e39d270e688d 100755
--- a/tools/testing/selftests/drivers/net/shaper.py
+++ b/tools/testing/selftests/drivers/net/shaper.py
@@ -1,7 +1,10 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
-from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_true, KsftSkipEx
+import errno
+
+from lib.py import ksft_run, ksft_exit
+from lib.py import ksft_eq, ksft_raises, ksft_true, KsftSkipEx
from lib.py import EthtoolFamily, NetshaperFamily
from lib.py import NetDrvEnv
from lib.py import NlError
@@ -438,6 +441,21 @@ def queue_update(cfg, nl_shaper) -> None:
nl_shaper.delete({'ifindex': cfg.ifindex,
'handle': {'scope': 'queue', 'id': i}})
+def dup_leaves(cfg, nl_shaper) -> None:
+ """ Ensure that the kernel rejects duplicate leaves. """
+ if not cfg.groups:
+ raise KsftSkipEx("device does not support node scope")
+
+ with ksft_raises(NlError) as cm:
+ nl_shaper.group({
+ 'ifindex': cfg.ifindex,
+ 'leaves':[{'handle': {'scope': 'queue', 'id': 0}},
+ {'handle': {'scope': 'queue', 'id': 0}}],
+ 'handle': {'scope':'node'},
+ 'metric': 'bps',
+ 'bw-max': 10000})
+ ksft_eq(cm.exception.error, errno.EINVAL)
+
def main() -> None:
with NetDrvEnv(__file__, queue_count=4) as cfg:
cfg.queues = False
@@ -453,7 +471,9 @@ def main() -> None:
basic_groups,
qgroups,
delegation,
- queue_update], args=(cfg, NetshaperFamily()))
+ dup_leaves,
+ queue_update],
+ args=(cfg, NetshaperFamily()))
ksft_exit()
diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c
index d6528c6f5e03..253e748c1d4a 100644
--- a/tools/testing/selftests/kvm/guest_memfd_test.c
+++ b/tools/testing/selftests/kvm/guest_memfd_test.c
@@ -510,7 +510,12 @@ static void test_guest_memfd_guest(void)
"Default VM type should support INIT_SHARED, supported flags = 0x%x",
vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS));
- size = vm->page_size;
+ /*
+ * Use the max of the host or guest page size for all operations, as
+ * KVM requires guest_memfd files and memslots to be sized to multiples
+ * of the host page size.
+ */
+ size = max_t(size_t, vm->page_size, page_size);
fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP |
GUEST_MEMFD_FLAG_INIT_SHARED);
vm_set_user_memory_region2(vm, slot, KVM_MEM_GUEST_MEMFD, gpa, size, NULL, fd, 0);
@@ -519,7 +524,7 @@ static void test_guest_memfd_guest(void)
memset(mem, 0xaa, size);
kvm_munmap(mem, size);
- virt_pg_map(vm, gpa, gpa);
+ virt_map(vm, gpa, gpa, size / vm->page_size);
vcpu_args_set(vcpu, 2, gpa, size);
vcpu_run(vcpu);
diff --git a/tools/testing/selftests/kvm/lib/elf.c b/tools/testing/selftests/kvm/lib/elf.c
index b689c4df4a01..1924a9895834 100644
--- a/tools/testing/selftests/kvm/lib/elf.c
+++ b/tools/testing/selftests/kvm/lib/elf.c
@@ -7,7 +7,7 @@
#include "test_util.h"
-#include <bits/endian.h>
+#include <endian.h>
#include <linux/elf.h>
#include "kvm_util.h"
diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
index 7df2bc8eec02..76fcdd1fd3cb 100644
--- a/tools/testing/selftests/kvm/steal_time.c
+++ b/tools/testing/selftests/kvm/steal_time.c
@@ -220,6 +220,8 @@ static void check_steal_time_uapi(void)
};
vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &dev);
+ vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, ST_GPA_BASE, 1, 1, 0);
+ virt_map(vm, ST_GPA_BASE, ST_GPA_BASE, 1);
st_ipa = (ulong)ST_GPA_BASE | 1;
ret = __vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &dev);
diff --git a/tools/testing/selftests/kvm/x86/apic_bus_clock_test.c b/tools/testing/selftests/kvm/x86/apic_bus_clock_test.c
index 404f0028e110..0c84c27ea584 100644
--- a/tools/testing/selftests/kvm/x86/apic_bus_clock_test.c
+++ b/tools/testing/selftests/kvm/x86/apic_bus_clock_test.c
@@ -137,6 +137,10 @@ static void run_apic_bus_clock_test(u64 apic_hz, u64 delay_ms,
vm_enable_cap(vm, KVM_CAP_X86_APIC_BUS_CYCLES_NS,
NSEC_PER_SEC / apic_hz);
+ TEST_ASSERT_EQ(kvm_check_cap(KVM_CAP_X86_APIC_BUS_CYCLES_NS), 1);
+ TEST_ASSERT_EQ(vm_check_cap(vm, KVM_CAP_X86_APIC_BUS_CYCLES_NS),
+ NSEC_PER_SEC / apic_hz);
+
vcpu = vm_vcpu_add(vm, 0, apic_guest_code);
vcpu_args_set(vcpu, 2, apic_hz, delay_ms);
diff --git a/tools/testing/selftests/mm/hmm-tests.c b/tools/testing/selftests/mm/hmm-tests.c
index 788689497e92..77fb4c5d871b 100644
--- a/tools/testing/selftests/mm/hmm-tests.c
+++ b/tools/testing/selftests/mm/hmm-tests.c
@@ -986,6 +986,56 @@ TEST_F(hmm, migrate)
}
/*
+ * Migrate private file memory to device private memory.
+ */
+TEST_F(hmm, migrate_file_private)
+{
+ struct hmm_buffer *buffer;
+ unsigned long npages;
+ unsigned long size;
+ unsigned long i;
+ int *ptr;
+ int ret;
+ int fd;
+
+ npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
+ ASSERT_NE(npages, 0);
+ size = npages << self->page_shift;
+
+ fd = hmm_create_file(size);
+ ASSERT_GE(fd, 0);
+
+ buffer = malloc(sizeof(*buffer));
+ ASSERT_NE(buffer, NULL);
+
+ buffer->fd = fd;
+ buffer->size = size;
+ buffer->mirror = malloc(size);
+ ASSERT_NE(buffer->mirror, NULL);
+
+ buffer->ptr = mmap(NULL, size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE,
+ buffer->fd, 0);
+ ASSERT_NE(buffer->ptr, MAP_FAILED);
+
+ /* Initialize buffer in system memory. */
+ for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
+ ptr[i] = i;
+
+ /* Migrate memory to device. */
+ ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(buffer->cpages, npages);
+
+ /* Check what the device read. */
+ for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
+ ASSERT_EQ(ptr[i], i);
+
+ hmm_buffer_free(buffer);
+}
+
+/*
* Migrate anonymous memory to device private memory and fault some of it back
* to system memory, then try migrating the resulting mix of system and device
* private memory to the device.
diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh
index d8468451b3a3..c17b133a81d2 100755
--- a/tools/testing/selftests/mm/run_vmtests.sh
+++ b/tools/testing/selftests/mm/run_vmtests.sh
@@ -103,7 +103,7 @@ RUN_ALL=false
RUN_DESTRUCTIVE=false
TAP_PREFIX="# "
-while getopts "aht:n" OPT; do
+while getopts "aht:nd" OPT; do
case ${OPT} in
"a") RUN_ALL=true ;;
"h") usage ;;
diff --git a/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh b/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh
index e8031f68200a..ebdb4c790a5d 100755
--- a/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh
+++ b/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh
@@ -4,7 +4,7 @@
ALL_TESTS="vlmc_control_test vlmc_querier_test vlmc_igmp_mld_version_test \
vlmc_last_member_test vlmc_startup_query_test vlmc_membership_test \
vlmc_querier_intvl_test vlmc_query_intvl_test vlmc_query_response_intvl_test \
- vlmc_router_port_test vlmc_filtering_test"
+ vlmc_router_port_test vlmc_filtering_test vlmc_mcast_toggle_test"
NUM_NETIFS=4
CHECK_TC="yes"
TEST_GROUP="239.10.10.10"
@@ -537,6 +537,34 @@ vlmc_filtering_test()
log_test "Disable multicast vlan snooping when vlan filtering is disabled"
}
+vlmc_mcast_toggle_test()
+{
+ RET=0
+
+ ip link add name br1-mcast up type bridge mcast_snooping 1 mcast_querier 1 vlan_filtering 1
+ ip link add name dummy1-mcast up master br1-mcast type dummy
+
+ # Enabling per-VLAN multicast snooping should disable the per-port
+ # multicast context on "dummy1-mcast".
+ ip link set dev br1-mcast type bridge mcast_vlan_snooping 1
+
+ # Toggling multicast snooping on the bridge should not affect the
+ # per-port multicast context on "dummy1-mcast" given that per-VLAN
+ # multicast snooping is enabled.
+ ip link set dev br1-mcast type bridge mcast_snooping 0
+ ip link set dev br1-mcast type bridge mcast_snooping 1
+
+ # If both the per-port and per-{port, VLAN} multicast contexts are
+ # enabled on "dummy1-mcast", removing it from the bridge will result
+ # in a splat.
+ ip link set dev dummy1-mcast nomaster
+
+ log_test "Toggling mcast snooping with per-VLAN mcast snooping enabled"
+
+ ip link del dev dummy1-mcast
+ ip link del dev br1-mcast
+}
+
trap cleanup EXIT
setup_prepare
diff --git a/tools/testing/selftests/net/lib/xdp_native.bpf.c b/tools/testing/selftests/net/lib/xdp_native.bpf.c
index 64f05229ab24..ded3f896e622 100644
--- a/tools/testing/selftests/net/lib/xdp_native.bpf.c
+++ b/tools/testing/selftests/net/lib/xdp_native.bpf.c
@@ -268,6 +268,17 @@ static int xdp_mode_tx_handler(struct xdp_md *ctx, __u16 port)
return XDP_PASS;
}
+static __always_inline __u16 csum_fold_helper(__u32 csum)
+{
+ csum = (csum & 0xffff) + (csum >> 16);
+ return ~((csum & 0xffff) + (csum >> 16));
+}
+
+static __always_inline __u16 csum_fold_udp_helper(__u32 csum)
+{
+ return csum_fold_helper(csum) ? : 0xffff;
+}
+
static void *update_pkt(struct xdp_md *ctx, __s16 offset, __u32 *udp_csum)
{
void *data_end = (void *)(long)ctx->data_end;
@@ -281,21 +292,22 @@ static void *update_pkt(struct xdp_md *ctx, __s16 offset, __u32 *udp_csum)
if (eth->h_proto == bpf_htons(ETH_P_IP)) {
struct iphdr *iph = data + sizeof(*eth);
- __u16 total_len;
if (iph + 1 > (struct iphdr *)data_end)
return NULL;
- iph->tot_len = bpf_htons(bpf_ntohs(iph->tot_len) + offset);
-
udph = (void *)eth + sizeof(*iph) + sizeof(*eth);
if (!udph || udph + 1 > (struct udphdr *)data_end)
return NULL;
- len_new = bpf_htons(bpf_ntohs(udph->len) + offset);
+ len = iph->tot_len;
+ len_new = bpf_htons(bpf_ntohs(len) + offset);
+ iph->tot_len = len_new;
+ iph->check = csum_fold_helper(
+ bpf_csum_diff(&len, sizeof(len), &len_new,
+ sizeof(len_new), ~((__u32)iph->check)));
} else if (eth->h_proto == bpf_htons(ETH_P_IPV6)) {
struct ipv6hdr *ipv6h = data + sizeof(*eth);
- __u16 payload_len;
if (ipv6h + 1 > (struct ipv6hdr *)data_end)
return NULL;
@@ -304,33 +316,27 @@ static void *update_pkt(struct xdp_md *ctx, __s16 offset, __u32 *udp_csum)
if (!udph || udph + 1 > (struct udphdr *)data_end)
return NULL;
- *udp_csum = ~((__u32)udph->check);
-
len = ipv6h->payload_len;
len_new = bpf_htons(bpf_ntohs(len) + offset);
ipv6h->payload_len = len_new;
-
- *udp_csum = bpf_csum_diff(&len, sizeof(len), &len_new,
- sizeof(len_new), *udp_csum);
-
- len = udph->len;
- len_new = bpf_htons(bpf_ntohs(udph->len) + offset);
- *udp_csum = bpf_csum_diff(&len, sizeof(len), &len_new,
- sizeof(len_new), *udp_csum);
} else {
return NULL;
}
+ len = udph->len;
+ len_new = bpf_htons(bpf_ntohs(len) + offset);
+
+ *udp_csum = ~((__u32)udph->check);
+ *udp_csum = bpf_csum_diff(&len, sizeof(len), &len_new,
+ sizeof(len_new), *udp_csum);
+ *udp_csum = bpf_csum_diff(&len, sizeof(len), &len_new,
+ sizeof(len_new), *udp_csum);
+
udph->len = len_new;
return udph;
}
-static __u16 csum_fold_helper(__u32 csum)
-{
- return ~((csum & 0xffff) + (csum >> 16)) ? : 0xffff;
-}
-
static int xdp_adjst_tail_shrnk_data(struct xdp_md *ctx, __u16 offset,
unsigned long hdr_len)
{
@@ -359,7 +365,7 @@ static int xdp_adjst_tail_shrnk_data(struct xdp_md *ctx, __u16 offset,
return -1;
udp_csum = bpf_csum_diff((__be32 *)tmp_buff, offset, 0, 0, udp_csum);
- udph->check = (__u16)csum_fold_helper(udp_csum);
+ udph->check = (__u16)csum_fold_udp_helper(udp_csum);
if (bpf_xdp_adjust_tail(ctx, 0 - offset) < 0)
return -1;
@@ -403,7 +409,7 @@ static int xdp_adjst_tail_grow_data(struct xdp_md *ctx, __u16 offset)
return -1;
udp_csum = bpf_csum_diff(0, 0, (__be32 *)tmp_buff, offset, udp_csum);
- udph->check = (__u16)csum_fold_helper(udp_csum);
+ udph->check = (__u16)csum_fold_udp_helper(udp_csum);
buff_len = bpf_xdp_get_buff_len(ctx);
@@ -484,8 +490,7 @@ static int xdp_adjst_head_shrnk_data(struct xdp_md *ctx, __u64 hdr_len,
return -1;
udp_csum = bpf_csum_diff((__be32 *)tmp_buff, offset, 0, 0, udp_csum);
-
- udph->check = (__u16)csum_fold_helper(udp_csum);
+ udph->check = (__u16)csum_fold_udp_helper(udp_csum);
if (bpf_xdp_load_bytes(ctx, 0, tmp_buff, MAX_ADJST_OFFSET) < 0)
return -1;
@@ -542,7 +547,7 @@ static int xdp_adjst_head_grow_data(struct xdp_md *ctx, __u64 hdr_len,
return -1;
udp_csum = bpf_csum_diff(0, 0, (__be32 *)data_buff, offset, udp_csum);
- udph->check = (__u16)csum_fold_helper(udp_csum);
+ udph->check = (__u16)csum_fold_udp_helper(udp_csum);
if (hdr_len > MAX_ADJST_OFFSET || hdr_len == 0)
return -1;
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
index a6447f7a31fe..d158678fa6ab 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
@@ -401,7 +401,7 @@ do_transfer()
mptcp_lib_wait_local_port_listen "${listener_ns}" "${port}"
local start
- start=$(date +%s%3N)
+ start=$(date +%s%N)
ip netns exec ${connector_ns} \
./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
$extra_args $connect_addr < "$cin" > "$cout" &
@@ -423,7 +423,7 @@ do_transfer()
fi
local stop
- stop=$(date +%s%3N)
+ stop=$(date +%s%N)
if $capture; then
sleep 1
@@ -439,7 +439,7 @@ do_transfer()
fi
local duration
- duration=$((stop-start))
+ duration=$(((stop-start) / 1000000))
printf "(duration %05sms) " "${duration}"
if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ] || [ ${timeout_pid} -ne 0 ]; then
mptcp_lib_pr_fail "client exit code $retc, server $rets"
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index beec41f6662a..5acd12021e6e 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -1828,6 +1828,22 @@ chk_add_tx_nr()
fi
}
+chk_add_drop_tx_nr()
+{
+ local drop_tx_nr=$1
+ local count
+
+ print_check "add addr tx drop"
+ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtAddAddrTxDrop")
+ if [ -z "$count" ]; then
+ print_skip
+ elif [ "$count" != "$drop_tx_nr" ]; then
+ fail_test "got $count ADD_ADDR drop[s] TX, expected $drop_tx_nr"
+ else
+ print_ok
+ fi
+}
+
chk_rm_nr()
{
local rm_addr_nr=$1
@@ -3278,6 +3294,21 @@ add_addr_ports_tests()
chk_mpc_endp_attempt ${retl} 1
fi
+
+ # first signal address drops, second one still progresses
+ if reset "signal addr list progresses after tx drop"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 1 0
+ ip netns exec $ns1 sysctl -q net.ipv4.tcp_timestamps=1
+ ip netns exec $ns2 sysctl -q net.ipv4.tcp_timestamps=1
+
+ pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal port 10100
+ pm_nl_add_endpoint $ns1 dead:beef:3::1 flags signal
+ run_tests $ns1 $ns2 dead:beef:1::1
+ chk_add_drop_tx_nr 1
+ chk_add_tx_nr 1 1
+ chk_add_nr 1 1 0
+ fi
}
bind_tests()
diff --git a/tools/testing/selftests/net/mptcp/mptcp_lib.sh b/tools/testing/selftests/net/mptcp/mptcp_lib.sh
index 989a5975dcea..5ef6033775c8 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_lib.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_lib.sh
@@ -28,7 +28,7 @@ declare -rx MPTCP_LIB_AF_INET6=10
MPTCP_LIB_SUBTESTS=()
MPTCP_LIB_SUBTESTS_DUPLICATED=0
MPTCP_LIB_SUBTEST_FLAKY=0
-MPTCP_LIB_SUBTESTS_LAST_TS_MS=
+MPTCP_LIB_SUBTESTS_LAST_TS_NS=
MPTCP_LIB_TEST_COUNTER=0
MPTCP_LIB_TEST_FORMAT="%02u %-50s"
MPTCP_LIB_IP_MPTCP=0
@@ -236,7 +236,7 @@ mptcp_lib_kversion_ge() {
}
mptcp_lib_subtests_last_ts_reset() {
- MPTCP_LIB_SUBTESTS_LAST_TS_MS="$(date +%s%3N)"
+ MPTCP_LIB_SUBTESTS_LAST_TS_NS="$(date +%s%N)"
}
mptcp_lib_subtests_last_ts_reset
@@ -255,7 +255,7 @@ __mptcp_lib_result_check_duplicated() {
__mptcp_lib_result_add() {
local result="${1}"
local time="time="
- local ts_prev_ms
+ local ts_prev_ns
shift
local id=$((${#MPTCP_LIB_SUBTESTS[@]} + 1))
@@ -265,9 +265,9 @@ __mptcp_lib_result_add() {
# not to add two '#'
[[ "${*}" != *"#"* ]] && time="# ${time}"
- ts_prev_ms="${MPTCP_LIB_SUBTESTS_LAST_TS_MS}"
+ ts_prev_ns="${MPTCP_LIB_SUBTESTS_LAST_TS_NS}"
mptcp_lib_subtests_last_ts_reset
- time+="$((MPTCP_LIB_SUBTESTS_LAST_TS_MS - ts_prev_ms))ms"
+ time+="$(((MPTCP_LIB_SUBTESTS_LAST_TS_NS - ts_prev_ns) / 1000000))ms"
MPTCP_LIB_SUBTESTS+=("${result} ${id} - ${KSFT_TEST}: ${*} ${time}")
}
diff --git a/tools/testing/selftests/net/ovpn/test-close-socket.sh b/tools/testing/selftests/net/ovpn/test-close-socket.sh
index af1532b4d2da..ec9a51bbf3c9 100755
--- a/tools/testing/selftests/net/ovpn/test-close-socket.sh
+++ b/tools/testing/selftests/net/ovpn/test-close-socket.sh
@@ -53,7 +53,7 @@ ovpn_run_ping_traffic() {
for p in $(seq 1 ${OVPN_NUM_PEERS}); do
ovpn_cmd_ok "send ping traffic to peer ${p}" \
- ip netns exec ovpn_peer0 ping -qfc 500 -w 3 \
+ ip netns exec ovpn_peer0 ping -qfc 100 -w 3 \
5.5.5.$((p + 1))
done
}
diff --git a/tools/testing/selftests/net/ovpn/test-mark.sh b/tools/testing/selftests/net/ovpn/test-mark.sh
index 5a8f47554286..7c1d56e9c525 100755
--- a/tools/testing/selftests/net/ovpn/test-mark.sh
+++ b/tools/testing/selftests/net/ovpn/test-mark.sh
@@ -66,7 +66,7 @@ ovpn_mark_run_baseline_traffic() {
for p in $(seq 1 3); do
ovpn_cmd_ok "send baseline traffic to peer ${p}" \
- ip netns exec ovpn_peer0 ping -qfc 500 -w 3 \
+ ip netns exec ovpn_peer0 ping -qfc 100 -w 3 \
5.5.5.$((p + 1))
done
}
@@ -101,7 +101,7 @@ ovpn_mark_verify_drop_traffic() {
local total_count
for p in $(seq 1 3); do
- if ping_output=$(ip netns exec ovpn_peer0 ping -qfc 500 -w 1 \
+ if ping_output=$(ip netns exec ovpn_peer0 ping -qfc 100 -w 1 \
5.5.5.$((p + 1)) 2>&1); then
printf '%s\n' "expected ping to peer ${p} to fail \
after nft drop rule"
@@ -144,7 +144,7 @@ ovpn_mark_verify_traffic_recovery() {
sleep 1
for p in $(seq 1 3); do
ovpn_cmd_ok "send recovery traffic to peer ${p}" \
- ip netns exec ovpn_peer0 ping -qfc 500 -w 3 \
+ ip netns exec ovpn_peer0 ping -qfc 100 -w 3 \
5.5.5.$((p + 1))
done
}
diff --git a/tools/testing/selftests/net/ovpn/test.sh b/tools/testing/selftests/net/ovpn/test.sh
index c06e3135fbef..9b5610837032 100755
--- a/tools/testing/selftests/net/ovpn/test.sh
+++ b/tools/testing/selftests/net/ovpn/test.sh
@@ -110,7 +110,7 @@ ovpn_run_basic_traffic() {
ovpn_run_lan_traffic() {
ovpn_cmd_ok "ping LAN behind peer1" \
- ip netns exec ovpn_peer0 ping -qfc 500 -w 3 "${OVPN_LAN_IP}"
+ ip netns exec ovpn_peer0 ping -qfc 100 -w 3 "${OVPN_LAN_IP}"
}
ovpn_run_float_mode() {
@@ -127,7 +127,7 @@ ovpn_run_float_mode() {
for p in $(seq 1 ${OVPN_NUM_PEERS}); do
peer_ns="ovpn_peer${p}"
ovpn_cmd_ok "ping tunnel after float peer ${p}" \
- ip netns exec "${peer_ns}" ping -qfc 500 -w 3 5.5.5.1
+ ip netns exec "${peer_ns}" ping -qfc 100 -w 3 5.5.5.1
done
}
diff --git a/tools/testing/selftests/net/rds/config b/tools/testing/selftests/net/rds/config
index 97db7ecb892a..3d62d0c750a8 100644
--- a/tools/testing/selftests/net/rds/config
+++ b/tools/testing/selftests/net/rds/config
@@ -1,3 +1,4 @@
+CONFIG_MODULES=n
CONFIG_NET_NS=y
CONFIG_NET_SCH_NETEM=y
CONFIG_RDS=y
diff --git a/tools/testing/selftests/rdma/rxe_ipv6.sh b/tools/testing/selftests/rdma/rxe_ipv6.sh
index b7059bfd6d7c..32dad687a044 100755
--- a/tools/testing/selftests/rdma/rxe_ipv6.sh
+++ b/tools/testing/selftests/rdma/rxe_ipv6.sh
@@ -8,6 +8,8 @@ RXE_NAME="rxe6"
PORT=4791
IP6_ADDR="2001:db8::1/64"
+source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
+
exec > /dev/null
# Cleanup function to run on exit (even on failure)
@@ -21,8 +23,8 @@ trap cleanup EXIT
# 1. Prerequisites check
for mod in tun veth rdma_rxe; do
if ! modinfo "$mod" >/dev/null 2>&1; then
- echo "Error: Kernel module '$mod' not found."
- exit 1
+ echo "SKIP: Kernel module '$mod' not found." >&2
+ exit $KSFT_SKIP
fi
done
diff --git a/tools/testing/selftests/rdma/rxe_rping_between_netns.sh b/tools/testing/selftests/rdma/rxe_rping_between_netns.sh
index e5b876f58c6e..e7554fbb8951 100755
--- a/tools/testing/selftests/rdma/rxe_rping_between_netns.sh
+++ b/tools/testing/selftests/rdma/rxe_rping_between_netns.sh
@@ -8,6 +8,8 @@ IP_A="1.1.1.1"
IP_B="1.1.1.2"
PORT=4791
+source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
+
exec > /dev/null
# --- Cleanup Routine ---
@@ -27,6 +29,11 @@ if [[ $EUID -ne 0 ]]; then
exit 1
fi
+if ! modinfo rdma_rxe >/dev/null 2>&1; then
+ echo "SKIP: Kernel module 'rdma_rxe' not found." >&2
+ exit $KSFT_SKIP
+fi
+
modprobe rdma_rxe || { echo "Failed to load rdma_rxe"; exit 1; }
# --- Setup Network Topology ---
diff --git a/tools/testing/selftests/rdma/rxe_socket_with_netns.sh b/tools/testing/selftests/rdma/rxe_socket_with_netns.sh
index 002e5098f751..9478657c02c1 100755
--- a/tools/testing/selftests/rdma/rxe_socket_with_netns.sh
+++ b/tools/testing/selftests/rdma/rxe_socket_with_netns.sh
@@ -4,6 +4,8 @@
PORT=4791
MODS=("tun" "rdma_rxe")
+source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
+
exec > /dev/null
# --- Helper: Cleanup Routine ---
@@ -26,6 +28,10 @@ if [[ $EUID -ne 0 ]]; then
fi
for m in "${MODS[@]}"; do
+ if ! modinfo "$m" >/dev/null 2>&1; then
+ echo "SKIP: Kernel module '$m' not found." >&2
+ exit $KSFT_SKIP
+ fi
modprobe "$m" || { echo "Error: Failed to load $m"; exit 1; }
done
diff --git a/tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh b/tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh
index 021ca451499d..8c18cea7535c 100755
--- a/tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh
+++ b/tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh
@@ -5,6 +5,8 @@ DEV_NAME="tun0"
RXE_NAME="rxe0"
RDMA_PORT=4791
+source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
+
exec > /dev/null
# --- Cleanup Routine ---
@@ -19,8 +21,8 @@ trap cleanup EXIT
# 1. Dependency Check
if ! modinfo rdma_rxe >/dev/null 2>&1; then
- echo "Error: rdma_rxe module not found."
- exit 1
+ echo "SKIP: rdma_rxe module not found." >&2
+ exit $KSFT_SKIP
fi
modprobe rdma_rxe
diff --git a/tools/testing/selftests/sched_ext/dequeue.c b/tools/testing/selftests/sched_ext/dequeue.c
index 4e93262703ca..383d06e972a4 100644
--- a/tools/testing/selftests/sched_ext/dequeue.c
+++ b/tools/testing/selftests/sched_ext/dequeue.c
@@ -33,6 +33,7 @@ static void worker_fn(int id)
/* Do some work to trigger scheduling events */
for (j = 0; j < 10000; j++)
sum += j;
+ asm volatile("" : : "r"(sum));
/* Sleep to trigger dequeue */
usleep(1000 + (id * 100));
diff --git a/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json b/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
index b1f856cf62c1..848696c373fc 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
@@ -1284,5 +1284,46 @@
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
+ },
+ {
+ "id": "3a62",
+ "name": "Try to create a qlen underflow with QFQ/CBS",
+ "category": [
+ "qdisc",
+ "qfq",
+ "cbs"
+ ],
+ "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 root handle 1: qfq",
+ "$TC class add dev $DUMMY classid 1:1 parent 1: qfq",
+ "$TC class add dev $DUMMY classid 1:2 parent 1: qfq",
+ "$TC qdisc add dev $DUMMY handle 2: parent 1:1 cbs",
+ "$TC qdisc add dev $DUMMY handle 3: parent 2: netem delay 5000000000",
+ "$TC filter add dev $DUMMY parent 1: prio 1 u32 match ip dst 10.10.10.1 classid 1:1 action ok",
+ "$TC filter add dev $DUMMY parent 1: prio 2 u32 match ip dst 10.10.10.2 classid 1:2 action ok",
+ "ping -c 1 10.10.10.1 -W0.01 -I$DUMMY || true",
+ "$IP l set $DUMMY down",
+ "$IP l set $DUMMY up",
+ "$TC qdisc replace dev $DUMMY handle 4: parent 2: pfifo"
+ ],
+ "cmdUnderTest": "ping -c 1 10.10.10.2 -W0.01 -I$DUMMY",
+ "expExitCode": "1",
+ "verifyCmd": "$TC -s -j qdisc ls dev $DUMMY parent 1:1",
+ "matchJSON": [
+ {
+ "kind": "cbs",
+ "handle": "2:",
+ "bytes": 0,
+ "packets": 0
+ }
+ ],
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
}
]
diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
index fbd9b1e7342a..0b23c09daea5 100644
--- a/tools/testing/selftests/ublk/kublk.c
+++ b/tools/testing/selftests/ublk/kublk.c
@@ -1735,6 +1735,17 @@ static int __cmd_dev_add(const struct dev_ctx *ctx)
goto fail;
}
+ /*
+ * The kernel may reduce nr_hw_queues (e.g. capped to nr_cpu_ids).
+ * Cap nthreads to the actual queue count to avoid creating extra
+ * handler threads that will hang during device removal.
+ *
+ * per_io_tasks mode is excluded: threads interleave across all
+ * queues so nthreads > nr_hw_queues is valid and intentional.
+ */
+ if (!ctx->per_io_tasks && dev->nthreads > info->nr_hw_queues)
+ dev->nthreads = info->nr_hw_queues;
+
ret = ublk_start_daemon(ctx, dev);
ublk_dbg(UBLK_DBG_DEV, "%s: daemon exit %d\n", __func__, ret);
if (ret < 0)