* [LTP] [PATCH] Add test for CVE 2026-53362
@ 2026-07-21 15:39 Martin Doucha
2026-07-21 19:28 ` [LTP] " linuxtestproject.agent
2026-07-23 12:24 ` [LTP] [PATCH] " Andrea Cervesato via ltp
0 siblings, 2 replies; 6+ messages in thread
From: Martin Doucha @ 2026-07-21 15:39 UTC (permalink / raw)
To: ltp
Add test for memory corruption due to miscalculation of socket buffer
size for fragmented packets with gaps.
Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
Bug reproducibility verified on affected kernels v6.4 and v6.12.
runtest/cve | 1 +
runtest/syscalls | 1 +
.../kernel/syscalls/setsockopt/.gitignore | 1 +
.../kernel/syscalls/setsockopt/setsockopt11.c | 171 ++++++++++++++++++
4 files changed, 174 insertions(+)
create mode 100644 testcases/kernel/syscalls/setsockopt/setsockopt11.c
diff --git a/runtest/cve b/runtest/cve
index 3bbcfd6a2..99d84270b 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -88,6 +88,7 @@ cve-2023-1829 tcindex01
cve-2023-0461 setsockopt10
cve-2023-31248 nft02
cve-2023-52879 fanotify25
+cve-2026-53362 setsockopt11
# Tests below may cause kernel memory leak
cve-2020-25704 perf_event_open03
cve-2022-0185 fsconfig03
diff --git a/runtest/syscalls b/runtest/syscalls
index c84c32a6f..949ad7622 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1524,6 +1524,7 @@ setsockopt07 setsockopt07
setsockopt08 setsockopt08
setsockopt09 setsockopt09
setsockopt10 setsockopt10
+setsockopt11 setsockopt11
settimeofday01 settimeofday01
settimeofday02 settimeofday02
diff --git a/testcases/kernel/syscalls/setsockopt/.gitignore b/testcases/kernel/syscalls/setsockopt/.gitignore
index 5c05290a5..58cc82d9c 100644
--- a/testcases/kernel/syscalls/setsockopt/.gitignore
+++ b/testcases/kernel/syscalls/setsockopt/.gitignore
@@ -8,3 +8,4 @@
/setsockopt08
/setsockopt09
/setsockopt10
+/setsockopt11
diff --git a/testcases/kernel/syscalls/setsockopt/setsockopt11.c b/testcases/kernel/syscalls/setsockopt/setsockopt11.c
new file mode 100644
index 000000000..5f09291b3
--- /dev/null
+++ b/testcases/kernel/syscalls/setsockopt/setsockopt11.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 SUSE LLC
+ * Original reproducer by Massimiliano Oldani
+ * Simplified LTP port: Martin Doucha <mdoucha@suse.com>
+ */
+
+/*
+ * CVE 2026-53362
+ *
+ * Test for vulnerability in socket buffer size calculation for fragmented
+ * UDP packets with gaps. Reproducer based on:
+ * https://github.com/sgkdev/ipv6_frag_escape
+ *
+ * Memory corruption fixed in kernel v7.2:
+ * 736b380e28d0 ("ipv6: account for fraggap on the paged allocation path")
+ */
+
+#define _GNU_SOURCE
+#include <netinet/in.h>
+#include <netinet/udp.h>
+
+#include "tst_test.h"
+#include "tst_net.h"
+#include "lapi/splice.h"
+
+#define PIPE_COUNT 2
+#define PIPE_BUF_SIZE (1 << 20)
+
+#define BUFSIZE 4096
+#define PATTERN_SIZE 256
+#define PATTERN_CHAR 0x42
+
+#define TEST_HDRSIZE 640
+#define TEST_MTU 1280
+#define TEST_PORT 12345
+#define TEST_MSGSIZE (1232 - TEST_HDRSIZE)
+
+static int pipefds[PIPE_COUNT][2];
+static int sockfd = -1;
+static unsigned char buf[BUFSIZE];
+static struct sockaddr_in6 addr;
+
+static void setup(void)
+{
+ int i;
+
+ for (i = 0; i < PIPE_COUNT; i++)
+ pipefds[i][0] = pipefds[i][1] = -1;
+
+ tst_init_sockaddr_inet6_bin(&addr, &in6addr_loopback, TEST_PORT);
+}
+
+static int leak_pipe(void)
+{
+ int i, padding, segcount = (TEST_HDRSIZE - 8) / 16;
+
+ /* Create input pipe and fill it with test data */
+ memset(buf, PATTERN_CHAR, PATTERN_SIZE);
+
+ for (i = 0; i < PIPE_COUNT; i++) {
+ SAFE_PIPE(pipefds[i]);
+ SAFE_FCNTL(pipefds[i][1], F_SETPIPE_SZ, PIPE_BUF_SIZE);
+ }
+
+ SAFE_WRITE(SAFE_WRITE_ALL, pipefds[0][1], buf, PATTERN_SIZE);
+
+ /* Create socket and set packet header with frag gap */
+ sockfd = SAFE_SOCKET(AF_INET6, SOCK_DGRAM, 0);
+ padding = TEST_HDRSIZE - 8 - 16 * segcount;
+ memset(buf, 0, TEST_HDRSIZE);
+ buf[1] = (TEST_HDRSIZE - 8) / 8;
+ buf[2] = 4;
+ buf[3] = (unsigned char)(segcount - 1);
+ buf[4] = buf[3];
+
+ for (i = 0; i < segcount; i++) {
+ memcpy(buf + 8 + 16 * i, &in6addr_loopback,
+ sizeof(in6addr_loopback));
+ }
+
+ if (padding)
+ buf[9 + 16 * segcount] = (unsigned char)(padding - 2);
+
+ TEST(setsockopt(sockfd, IPPROTO_IPV6, IPV6_RTHDR, buf, TEST_HDRSIZE));
+
+ if (TST_RET == -1 && TST_ERR == EINVAL)
+ tst_brk(TCONF, "IPV6_RTHDR type 4 is not supported");
+ else if (TST_RET)
+ tst_brk(TBROK | TTERRNO, "setsockopt(IPV6_RTHDR) failed");
+
+ SAFE_SETSOCKOPT_INT(sockfd, IPPROTO_IPV6, IPV6_MTU, TEST_MTU);
+ SAFE_CONNECT(sockfd, (struct sockaddr *)&addr, sizeof(addr));
+ SAFE_SETSOCKOPT_INT(sockfd, IPPROTO_UDP, UDP_CORK, 1);
+
+ /* Splice input pipe buffer page into socket */
+ memset(buf, 0, TEST_MSGSIZE);
+ buf[TEST_MSGSIZE - 6] = 1;
+ SAFE_WRITE(SAFE_WRITE_ALL, pipefds[1][1], buf, TEST_MSGSIZE);
+ splice(pipefds[1][0], NULL, sockfd, NULL, TEST_MSGSIZE, SPLICE_F_MORE);
+ tee(pipefds[0][0], pipefds[1][1], PATTERN_SIZE, 0);
+ splice(pipefds[1][0], NULL, sockfd, NULL, PATTERN_SIZE, SPLICE_F_MORE);
+ SAFE_CLOSE(sockfd);
+
+ /* Check whether pipe buffer got reused while still allocated */
+ tst_pollute_memory(0, ~(unsigned char)PATTERN_CHAR);
+ SAFE_READ(SAFE_READ_ALL, pipefds[0][0], buf, PATTERN_SIZE);
+
+ for (i = 0; i < PIPE_COUNT; i++) {
+ SAFE_CLOSE(pipefds[i][0]);
+ SAFE_CLOSE(pipefds[i][1]);
+ }
+
+ for (i = 0; i < PATTERN_SIZE; i++) {
+ if (buf[i] != PATTERN_CHAR)
+ return 1;
+ }
+
+ return 0;
+}
+
+static void run(void)
+{
+ int i, leaked = 0;
+
+ for (i = 0; i < 64; i++) {
+ if (tst_remaining_runtime() <= 0)
+ break;
+
+ leaked = leak_pipe();
+
+ if (leaked)
+ break;
+ }
+
+ if (leaked) {
+ tst_res(TFAIL, "Pipe buffer was corrupted");
+ return;
+ }
+
+ tst_res(TPASS, "Nothing bad happened (yet)");
+}
+
+static void cleanup(void)
+{
+ int i;
+
+ for (i = 0; i < PIPE_COUNT; i++) {
+ if (pipefds[i][0] >= 0) {
+ SAFE_CLOSE(pipefds[i][0]);
+ SAFE_CLOSE(pipefds[i][1]);
+ }
+ }
+
+ if (sockfd >= 0)
+ SAFE_CLOSE(sockfd);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .runtime = 300,
+ .min_runtime = 30,
+ .taint_check = TST_TAINT_W | TST_TAINT_D,
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "736b380e28d0480c7bc3e022f1950f31fe53a7c5"},
+ {"CVE", "2026-53362"},
+ {}
+ },
+};
--
2.54.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [LTP] Add test for CVE 2026-53362
2026-07-21 15:39 [LTP] [PATCH] Add test for CVE 2026-53362 Martin Doucha
@ 2026-07-21 19:28 ` linuxtestproject.agent
2026-07-22 7:36 ` Andrea Cervesato via ltp
2026-07-23 12:24 ` [LTP] [PATCH] " Andrea Cervesato via ltp
1 sibling, 1 reply; 6+ messages in thread
From: linuxtestproject.agent @ 2026-07-21 19:28 UTC (permalink / raw)
To: Martin Doucha; +Cc: ltp
Hi Martin,
On Tue, 21 Jul 2026, Martin Doucha wrote:
> Add test for CVE 2026-53362
> +/*
> + * CVE 2026-53362
> + *
> + * Test for vulnerability in socket buffer size calculation for fragmented
> + * UDP packets with gaps. Reproducer based on:
> + * https://github.com/sgkdev/ipv6_frag_escape
> + *
> + * Memory corruption fixed in kernel v7.2:
> + * 736b380e28d0 ("ipv6: account for fraggap on the paged allocation path")
> + */
This high-level description block opens with a plain `/*` instead of
`/*\`. setsockopt10.c (and the rest of the test suite) uses `/*\` for
this block, since it gets exported into the RST-based test catalog.
As written, this stays a regular comment and will not show up in the
generated documentation. Could this be changed to `/*\`?
> + /* Splice input pipe buffer page into socket */
> + memset(buf, 0, TEST_MSGSIZE);
> + buf[TEST_MSGSIZE - 6] = 1;
> + SAFE_WRITE(SAFE_WRITE_ALL, pipefds[1][1], buf, TEST_MSGSIZE);
> + splice(pipefds[1][0], NULL, sockfd, NULL, TEST_MSGSIZE, SPLICE_F_MORE);
> + tee(pipefds[0][0], pipefds[1][1], PATTERN_SIZE, 0);
> + splice(pipefds[1][0], NULL, sockfd, NULL, PATTERN_SIZE, SPLICE_F_MORE);
The file already includes "lapi/splice.h", which provides
`SAFE_SPLICE()`. Both splice() calls here use the bare syscall
instead, so their return value is discarded. If either call fails or
returns short, the reproduction sequence silently doesn't happen and
the iteration would just report TPASS without having exercised
anything. Would SAFE_SPLICE() be preferable here?
> + for (i = 0; i < PIPE_COUNT; i++) {
> + SAFE_CLOSE(pipefds[i][0]);
> + SAFE_CLOSE(pipefds[i][1]);
> + }
pipefds[][] (and sockfd, closed a few lines above) are not reset to -1
after being closed here; only setup() initializes them to -1, once.
cleanup() decides whether a descriptor needs closing with a `>= 0`
check.
Since leak_pipe() runs in a loop (up to 64 times), if SAFE_PIPE() or
SAFE_SOCKET() at the start of a later iteration fails (pipe(2)/
socket(2) can fail with EMFILE/ENFILE/ENOMEM) before refreshing a
given slot, cleanup() would see the stale, already-closed descriptor
number from the previous iteration as still open and try to close it
again. Would it make sense to reset the relevant slot to -1 right
after each close?
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] 6+ messages in thread* Re: [LTP] Add test for CVE 2026-53362
2026-07-21 19:28 ` [LTP] " linuxtestproject.agent
@ 2026-07-22 7:36 ` Andrea Cervesato via ltp
2026-07-22 14:51 ` Martin Doucha
0 siblings, 1 reply; 6+ messages in thread
From: Andrea Cervesato via ltp @ 2026-07-22 7:36 UTC (permalink / raw)
To: linuxtestproject.agent; +Cc: ltp
Hi Martin,
> This high-level description block opens with a plain `/*` instead of
> `/*\`. setsockopt10.c (and the rest of the test suite) uses `/*\` for
> this block, since it gets exported into the RST-based test catalog.
>
> As written, this stays a regular comment and will not show up in the
> generated documentation. Could this be changed to `/*\`?
This is correct.
>
> > + /* Splice input pipe buffer page into socket */
> > + memset(buf, 0, TEST_MSGSIZE);
> > + buf[TEST_MSGSIZE - 6] = 1;
> > + SAFE_WRITE(SAFE_WRITE_ALL, pipefds[1][1], buf, TEST_MSGSIZE);
> > + splice(pipefds[1][0], NULL, sockfd, NULL, TEST_MSGSIZE, SPLICE_F_MORE);
> > + tee(pipefds[0][0], pipefds[1][1], PATTERN_SIZE, 0);
> > + splice(pipefds[1][0], NULL, sockfd, NULL, PATTERN_SIZE, SPLICE_F_MORE);
>
> The file already includes "lapi/splice.h", which provides
> `SAFE_SPLICE()`. Both splice() calls here use the bare syscall
> instead, so their return value is discarded. If either call fails or
> returns short, the reproduction sequence silently doesn't happen and
> the iteration would just report TPASS without having exercised
> anything. Would SAFE_SPLICE() be preferable here?
mmmh is this the case where splice() is supposed to fail but triggering
the CVE into the kernel? if so, we probably need to add a short comment
so we know that SAFE_SPLICE() is not a good choice.
>
> > + for (i = 0; i < PIPE_COUNT; i++) {
> > + SAFE_CLOSE(pipefds[i][0]);
> > + SAFE_CLOSE(pipefds[i][1]);
> > + }
>
> pipefds[][] (and sockfd, closed a few lines above) are not reset to -1
> after being closed here; only setup() initializes them to -1, once.
> cleanup() decides whether a descriptor needs closing with a `>= 0`
> check.
>
> Since leak_pipe() runs in a loop (up to 64 times), if SAFE_PIPE() or
> SAFE_SOCKET() at the start of a later iteration fails (pipe(2)/
> socket(2) can fail with EMFILE/ENFILE/ENOMEM) before refreshing a
> given slot, cleanup() would see the stale, already-closed descriptor
> number from the previous iteration as still open and try to close it
> again. Would it make sense to reset the relevant slot to -1 right
> after each close?
Again, I updated the agent but it's still asking for this. Please ignore
it, I will need to update the agent in a proper way. There's probably
some logic flaw in the rules at the moment.
Thanks,
--
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] 6+ messages in thread* Re: [LTP] Add test for CVE 2026-53362
2026-07-22 7:36 ` Andrea Cervesato via ltp
@ 2026-07-22 14:51 ` Martin Doucha
0 siblings, 0 replies; 6+ messages in thread
From: Martin Doucha @ 2026-07-22 14:51 UTC (permalink / raw)
To: Andrea Cervesato; +Cc: ltp
On 7/22/26 09:36, Andrea Cervesato wrote:
>>> + /* Splice input pipe buffer page into socket */
>>> + memset(buf, 0, TEST_MSGSIZE);
>>> + buf[TEST_MSGSIZE - 6] = 1;
>>> + SAFE_WRITE(SAFE_WRITE_ALL, pipefds[1][1], buf, TEST_MSGSIZE);
>>> + splice(pipefds[1][0], NULL, sockfd, NULL, TEST_MSGSIZE, SPLICE_F_MORE);
>>> + tee(pipefds[0][0], pipefds[1][1], PATTERN_SIZE, 0);
>>> + splice(pipefds[1][0], NULL, sockfd, NULL, PATTERN_SIZE, SPLICE_F_MORE);
>>
>> The file already includes "lapi/splice.h", which provides
>> `SAFE_SPLICE()`. Both splice() calls here use the bare syscall
>> instead, so their return value is discarded. If either call fails or
>> returns short, the reproduction sequence silently doesn't happen and
>> the iteration would just report TPASS without having exercised
>> anything. Would SAFE_SPLICE() be preferable here?
>
> mmmh is this the case where splice() is supposed to fail but triggering
> the CVE into the kernel? if so, we probably need to add a short comment
> so we know that SAFE_SPLICE() is not a good choice.
Both splice() calls are supposed to succeed but it doesn't really matter
if they fail a few times during the test run. Yes, if they fail all the
time, the bug will not get triggered. So if you want to be extra
careful, feel free to change the splice()s to SAFE_SPLICE() during merge.
--
Martin Doucha mdoucha@suse.cz
SW Quality Engineer
SUSE LINUX, s.r.o.
CORSO IIa
Krizikova 148/34
186 00 Prague 8
Czech Republic
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [LTP] [PATCH] Add test for CVE 2026-53362
2026-07-21 15:39 [LTP] [PATCH] Add test for CVE 2026-53362 Martin Doucha
2026-07-21 19:28 ` [LTP] " linuxtestproject.agent
@ 2026-07-23 12:24 ` Andrea Cervesato via ltp
2026-07-28 7:17 ` Andrea Cervesato via ltp
1 sibling, 1 reply; 6+ messages in thread
From: Andrea Cervesato via ltp @ 2026-07-23 12:24 UTC (permalink / raw)
To: Martin Doucha; +Cc: ltp
> Add test for memory corruption due to miscalculation of socket buffer
> size for fragmented packets with gaps.
>
> Signed-off-by: Martin Doucha <mdoucha@suse.cz>
> ---
>
> Bug reproducibility verified on affected kernels v6.4 and v6.12.
>
> runtest/cve | 1 +
> runtest/syscalls | 1 +
> .../kernel/syscalls/setsockopt/.gitignore | 1 +
> .../kernel/syscalls/setsockopt/setsockopt11.c | 171 ++++++++++++++++++
> 4 files changed, 174 insertions(+)
> create mode 100644 testcases/kernel/syscalls/setsockopt/setsockopt11.c
>
> diff --git a/runtest/cve b/runtest/cve
> index 3bbcfd6a2..99d84270b 100644
> --- a/runtest/cve
> +++ b/runtest/cve
> @@ -88,6 +88,7 @@ cve-2023-1829 tcindex01
> cve-2023-0461 setsockopt10
> cve-2023-31248 nft02
> cve-2023-52879 fanotify25
> +cve-2026-53362 setsockopt11
> # Tests below may cause kernel memory leak
> cve-2020-25704 perf_event_open03
> cve-2022-0185 fsconfig03
> diff --git a/runtest/syscalls b/runtest/syscalls
> index c84c32a6f..949ad7622 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -1524,6 +1524,7 @@ setsockopt07 setsockopt07
> setsockopt08 setsockopt08
> setsockopt09 setsockopt09
> setsockopt10 setsockopt10
> +setsockopt11 setsockopt11
>
> settimeofday01 settimeofday01
> settimeofday02 settimeofday02
> diff --git a/testcases/kernel/syscalls/setsockopt/.gitignore b/testcases/kernel/syscalls/setsockopt/.gitignore
> index 5c05290a5..58cc82d9c 100644
> --- a/testcases/kernel/syscalls/setsockopt/.gitignore
> +++ b/testcases/kernel/syscalls/setsockopt/.gitignore
> @@ -8,3 +8,4 @@
> /setsockopt08
> /setsockopt09
> /setsockopt10
> +/setsockopt11
> diff --git a/testcases/kernel/syscalls/setsockopt/setsockopt11.c b/testcases/kernel/syscalls/setsockopt/setsockopt11.c
> new file mode 100644
> index 000000000..5f09291b3
> --- /dev/null
> +++ b/testcases/kernel/syscalls/setsockopt/setsockopt11.c
> @@ -0,0 +1,171 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2026 SUSE LLC
> + * Original reproducer by Massimiliano Oldani
> + * Simplified LTP port: Martin Doucha <mdoucha@suse.com>
> + */
> +
> +/*
> + * CVE 2026-53362
> + *
> + * Test for vulnerability in socket buffer size calculation for fragmented
> + * UDP packets with gaps. Reproducer based on:
> + * https://github.com/sgkdev/ipv6_frag_escape
> + *
> + * Memory corruption fixed in kernel v7.2:
> + * 736b380e28d0 ("ipv6: account for fraggap on the paged allocation path")
We can add an Algorithm section to make the test easier to read.
* [Algorithm]
*
* - Fill pipe[0] with a known pattern (0x42) ("canary" page).
* - Splice pages into a corked socket so the skb references pipe[0]'s page.
* - Close the socket -> the corruption causes the page refcount to drop
* too low -> the page appears free while pipe[0] still owns it.
* - Pollute all free memory with 0xBD (inverse of 0x42).
* - Read pipe[0] back. If any byte changed, the page was reallocated
* while the pipe still held it -> the bug is confirmed.
> + /* Splice input pipe buffer page into socket */
> + memset(buf, 0, TEST_MSGSIZE);
> + buf[TEST_MSGSIZE - 6] = 1;
> + SAFE_WRITE(SAFE_WRITE_ALL, pipefds[1][1], buf, TEST_MSGSIZE);
> + splice(pipefds[1][0], NULL, sockfd, NULL, TEST_MSGSIZE, SPLICE_F_MORE);
SAFE_SPLICE() here.
> +static void cleanup(void)
> +{
> + int i;
> +
> + for (i = 0; i < PIPE_COUNT; i++) {
> + if (pipefds[i][0] >= 0) {
This should be != -1 according to static definition and the SAFE_CLOSE()
bahavior in the test (it sets to -1).
> + SAFE_CLOSE(pipefds[i][0]);
> + SAFE_CLOSE(pipefds[i][1]);
> + }
> + }
> +
> + if (sockfd >= 0)
And here as well.
The rest looks good to me.
--
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] 6+ messages in thread
end of thread, other threads:[~2026-07-28 7:17 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-21 15:39 [LTP] [PATCH] Add test for CVE 2026-53362 Martin Doucha
2026-07-21 19:28 ` [LTP] " linuxtestproject.agent
2026-07-22 7:36 ` Andrea Cervesato via ltp
2026-07-22 14:51 ` Martin Doucha
2026-07-23 12:24 ` [LTP] [PATCH] " Andrea Cervesato via ltp
2026-07-28 7:17 ` Andrea Cervesato via ltp
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.