* Re: [LTP] futex: Add error coverage tests for wait, wake and cmp_requeue
2026-04-13 13:40 [LTP] [PATCH v2] " Michael Menasherov via ltp
@ 2026-04-13 14:56 ` linuxtestproject.agent
0 siblings, 0 replies; 3+ messages in thread
From: linuxtestproject.agent @ 2026-04-13 14:56 UTC (permalink / raw)
To: Michael Menasherov; +Cc: ltp
Hi Michael,
our agent completed the review of the patch.
On Mon, 13 Apr 2026, Michael Menasherov via ltp wrote:
> [PATCH] futex: Add error coverage tests for wait, wake and cmp_requeue
[...]
> futex_cmp_requeue03 verifies EFAULT is returned when uaddr or
> uaddr2 points to unmapped memory, and EACCES or EFAULT when uaddr
> points to memory without read permission (PROT_NONE). The EACCES
> behavior was introduced in kernel 5.9.
The commit message is missing the Signed-off-by tag. Please add:
Signed-off-by: Michael Menasherov <your@email.com>
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 3+ messages in thread
* [LTP] [PATCH v3] futex: Add error coverage tests for wait, wake and cmp_requeue
@ 2026-04-19 13:00 Michael Menasherov via ltp
2026-04-19 14:46 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 3+ messages in thread
From: Michael Menasherov via ltp @ 2026-04-19 13:00 UTC (permalink / raw)
To: ltp
Improve error handling coverage for futex syscalls by adding tests
for missing error conditions that were previously untested.
futex_wait06 verifies EFAULT is returned when uaddr or timeout
points to unmapped memory.
futex_wait07 verifies EINTR is returned when futex_wait() is
interrupted by a signal.
futex_wake05 verifies EFAULT is returned when uaddr points to
unmapped or PROT_NONE memory.
futex_cmp_requeue03 verifies EFAULT is returned when uaddr or
uaddr2 points to unmapped memory, and EACCES or EFAULT when uaddr
points to memory without read permission (PROT_NONE). The EACCES
behavior was introduced in kernel 5.9.
Signed-off-by: Michael Menasherov <mmenashe@redhat.com>
---
v3:
- Fix copyright year 2024 -> 2026
- Use /*\ comment format for test catalog
- Use TST_EXP_FAIL instead of manual error checks
- Add kernel version check for EACCES in futex_cmp_requeue03
- Restructure testcases to use direct pointers instead of flag fields
- Remove obvious comments in futex_wait07
- Remove manual SAFE_WAITPID, let library collect child
- Remove curly braces around single-line if bodies
- Replace raw mmap() with SAFE_MMAP() in futex_wait06
runtest/syscalls | 4 +
testcases/kernel/syscalls/futex/.gitignore | 4 +
.../syscalls/futex/futex_cmp_requeue03.c | 96 +++++++++++++++++++
.../kernel/syscalls/futex/futex_wait06.c | 73 ++++++++++++++
.../kernel/syscalls/futex/futex_wait07.c | 91 ++++++++++++++++++
.../kernel/syscalls/futex/futex_wake05.c | 86 +++++++++++++++++
6 files changed, 354 insertions(+)
create mode 100644 testcases/kernel/syscalls/futex/futex_cmp_requeue03.c
create mode 100644 testcases/kernel/syscalls/futex/futex_wait06.c
create mode 100644 testcases/kernel/syscalls/futex/futex_wait07.c
create mode 100644 testcases/kernel/syscalls/futex/futex_wake05.c
diff --git a/runtest/syscalls b/runtest/syscalls
index 6ba0227a8..6c12dc225 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1859,11 +1859,14 @@ perf_event_open02 perf_event_open02
futex_cmp_requeue01 futex_cmp_requeue01
futex_cmp_requeue02 futex_cmp_requeue02
+futex_cmp_requeue03 futex_cmp_requeue03
futex_wait01 futex_wait01
futex_wait02 futex_wait02
futex_wait03 futex_wait03
futex_wait04 futex_wait04
futex_wait05 futex_wait05
+futex_wait06 futex_wait06
+futex_wait07 futex_wait07
futex_waitv01 futex_waitv01
futex_waitv02 futex_waitv02
futex_waitv03 futex_waitv03
@@ -1871,6 +1874,7 @@ futex_wake01 futex_wake01
futex_wake02 futex_wake02
futex_wake03 futex_wake03
futex_wake04 futex_wake04
+futex_wake05 futex_wake05
futex_wait_bitset01 futex_wait_bitset01
memfd_create01 memfd_create01
diff --git a/testcases/kernel/syscalls/futex/.gitignore b/testcases/kernel/syscalls/futex/.gitignore
index 9d08ba7d3..c47d39b5b 100644
--- a/testcases/kernel/syscalls/futex/.gitignore
+++ b/testcases/kernel/syscalls/futex/.gitignore
@@ -1,15 +1,19 @@
/futex_cmp_requeue01
/futex_cmp_requeue02
+/futex_cmp_requeue03
/futex_wait01
/futex_wait02
/futex_wait03
/futex_wait04
/futex_wait05
+/futex_wait06
+/futex_wait07
/futex_wait_bitset01
/futex_wake01
/futex_wake02
/futex_wake03
/futex_wake04
+/futex_wake05
/futex_waitv01
/futex_waitv02
/futex_waitv03
diff --git a/testcases/kernel/syscalls/futex/futex_cmp_requeue03.c b/testcases/kernel/syscalls/futex/futex_cmp_requeue03.c
new file mode 100644
index 000000000..099d5e35c
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_cmp_requeue03.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Red Hat, Inc.
+ */
+
+/*\
+ * Check that futex(FUTEX_CMP_REQUEUE) returns EFAULT when uaddr or
+ * uaddr2 points to unmapped memory, and EACCES (or EFAULT on older kernels)
+ * when uaddr points to memory without read permission (PROT_NONE).
+ *
+ * The EACCES behavior for PROT_NONE was introduced in kernel 5.9.
+ */
+
+#include <errno.h>
+#include <sys/mman.h>
+
+#include "futextest.h"
+
+static futex_t futex_var = FUTEX_INITIALIZER;
+static futex_t *prot_none_addr;
+
+static struct futex_test_variants variants[] = {
+#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
+ { .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
+ { .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+static struct testcase {
+ const char *desc;
+ futex_t *uaddr;
+ futex_t *uaddr2;
+ int exp_errno;
+} testcases[3];
+
+static void run(unsigned int n)
+{
+ struct futex_test_variants *tv = &variants[tst_variant];
+ struct testcase *tc = &testcases[n];
+
+ TST_EXP_FAIL(futex_cmp_requeue(tv->fntype, tc->uaddr, futex_var,
+ tc->uaddr2, 1, 1, 0), tc->exp_errno, "%s", tc->desc);
+}
+
+static void setup(void)
+{
+ struct futex_test_variants *tv = &variants[tst_variant];
+ size_t pagesize = getpagesize();
+ futex_t *unmapped;
+
+ tst_res(TINFO, "Testing variant: %s", tv->desc);
+ futex_supported_by_kernel(tv->fntype);
+
+ unmapped = SAFE_MMAP(NULL, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ SAFE_MUNMAP(unmapped, pagesize);
+
+ prot_none_addr = SAFE_MMAP(NULL, pagesize, PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ testcases[0] = (struct testcase){
+ .desc = "uaddr unmapped",
+ .uaddr = unmapped,
+ .uaddr2 = &futex_var,
+ .exp_errno = EFAULT,
+ };
+ testcases[1] = (struct testcase){
+ .desc = "uaddr2 unmapped",
+ .uaddr = &futex_var,
+ .uaddr2 = unmapped,
+ .exp_errno = EFAULT,
+ };
+ testcases[2] = (struct testcase){
+ .desc = "uaddr PROT_NONE",
+ .uaddr = prot_none_addr,
+ .uaddr2 = &futex_var,
+ .exp_errno = tst_kvercmp(5, 9, 0) >= 0 ? EACCES : EFAULT,
+ };
+}
+
+static void cleanup(void)
+{
+ if (prot_none_addr)
+ SAFE_MUNMAP(prot_none_addr, getpagesize());
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test = run,
+ .tcnt = ARRAY_SIZE(testcases),
+ .test_variants = ARRAY_SIZE(variants),
+};
diff --git a/testcases/kernel/syscalls/futex/futex_wait06.c b/testcases/kernel/syscalls/futex/futex_wait06.c
new file mode 100644
index 000000000..8bb563fb2
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_wait06.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Red Hat, Inc.
+ */
+
+/*\
+ * Check that futex(FUTEX_WAIT) returns EFAULT when:
+ *
+ * 1) uaddr points to unmapped memory
+ * 2) timeout points to unmapped memory
+ */
+#include <errno.h>
+#include <sys/mman.h>
+
+#include "futextest.h"
+
+static futex_t futex = FUTEX_INITIALIZER;
+
+static struct futex_test_variants variants[] = {
+#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
+ { .fntype = FUTEX_FN_FUTEX, .tstype = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
+ { .fntype = FUTEX_FN_FUTEX64, .tstype = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+static struct testcase {
+ const char *desc;
+ futex_t *uaddr;
+ void *timeout;
+} testcases[2];
+
+static void run(unsigned int n)
+{
+ struct futex_test_variants *tv = &variants[tst_variant];
+ struct testcase *tc = &testcases[n];
+
+ TST_EXP_FAIL(futex_syscall(tv->fntype, tc->uaddr, FUTEX_WAIT, futex,
+ tc->timeout, NULL, 0, 0), EFAULT, "%s", tc->desc);
+}
+
+static void setup(void)
+{
+ struct futex_test_variants *tv = &variants[tst_variant];
+ void *bad;
+
+ tst_res(TINFO, "Testing variant: %s", tv->desc);
+ futex_supported_by_kernel(tv->fntype);
+
+ bad = SAFE_MMAP(NULL, getpagesize(), PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ SAFE_MUNMAP(bad, getpagesize());
+
+ testcases[0] = (struct testcase){
+ .desc = "uaddr points to unmapped memory",
+ .uaddr = bad,
+ .timeout = NULL,
+ };
+ testcases[1] = (struct testcase){
+ .desc = "timeout points to unmapped memory",
+ .uaddr = &futex,
+ .timeout = bad,
+ };
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test = run,
+ .tcnt = ARRAY_SIZE(testcases),
+ .test_variants = ARRAY_SIZE(variants),
+};
diff --git a/testcases/kernel/syscalls/futex/futex_wait07.c b/testcases/kernel/syscalls/futex/futex_wait07.c
new file mode 100644
index 000000000..c3063389a
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_wait07.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Red Hat, Inc.
+ */
+
+/*\
+ * Check that futex(FUTEX_WAIT) returns EINTR when interrupted by a signal.
+ * A child process blocks on futex_wait() with a long timeout. The parent
+ * waits for the child to enter sleep state, then sends SIGUSR1 to it.
+ * The child verifies it received EINTR and exits accordingly.
+ */
+
+#include <errno.h>
+#include <signal.h>
+
+#include "futextest.h"
+
+static futex_t *futex;
+
+static struct futex_test_variants variants[] = {
+#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
+ { .fntype = FUTEX_FN_FUTEX, .tstype = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
+ { .fntype = FUTEX_FN_FUTEX64, .tstype = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+/* We need a handler so SIGUSR1 is caught instead of killing the process.
+ * The empty body is needed, just receiving the signal is enough to
+ * interrupt futex_wait() and make it return into EINTR -1 status.
+ */
+static void sigusr1_handler(int sig LTP_ATTRIBUTE_UNUSED)
+{
+}
+
+static void do_child(void)
+{
+ struct futex_test_variants *tv = &variants[tst_variant];
+ struct sigaction sa;
+ struct tst_ts timeout;
+
+ sa.sa_handler = sigusr1_handler;
+ sa.sa_flags = 0;
+ SAFE_SIGEMPTYSET(&sa.sa_mask);
+ SAFE_SIGACTION(SIGUSR1, &sa, NULL);
+
+ timeout = tst_ts_from_ms(tv->tstype, 5000);
+ TST_EXP_FAIL(futex_wait(tv->fntype, futex, *futex, &timeout, 0), EINTR);
+ exit(0);
+}
+
+static void run(void)
+{
+ pid_t child;
+
+ child = SAFE_FORK();
+
+ if (child == 0)
+ do_child();
+
+ TST_PROCESS_STATE_WAIT(child, 'S', 0);
+ SAFE_KILL(child, SIGUSR1);
+}
+
+static void setup(void)
+{
+ struct futex_test_variants *tv = &variants[tst_variant];
+
+ tst_res(TINFO, "Testing variant: %s", tv->desc);
+ futex_supported_by_kernel(tv->fntype);
+
+ futex = SAFE_MMAP(NULL, sizeof(*futex), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+ *futex = FUTEX_INITIALIZER;
+}
+
+static void cleanup(void)
+{
+ if (futex) {
+ SAFE_MUNMAP((void *)futex, sizeof(*futex));
+ }
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .test_variants = ARRAY_SIZE(variants),
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/syscalls/futex/futex_wake05.c b/testcases/kernel/syscalls/futex/futex_wake05.c
new file mode 100644
index 000000000..1e9bd6435
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_wake05.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Red Hat, Inc.
+ */
+
+/*\
+ * Check that futex(FUTEX_WAKE) returns EFAULT when uaddr points to
+ * unmapped or PROT_NONE memory.
+ *
+ * Note: FUTEX_WAKE never reads *uaddr, so PROT_NONE triggers EFAULT
+ * (not EACCES). The EACCES behavior only applies to syscalls that read
+ * *uaddr (e.g. FUTEX_WAIT, FUTEX_CMP_REQUEUE).
+ */
+
+#include <errno.h>
+#include <sys/mman.h>
+#include "futextest.h"
+
+static futex_t *prot_none_addr;
+
+static struct futex_test_variants variants[] = {
+#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
+ { .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
+ { .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+static struct testcase {
+ const char *desc;
+ futex_t *addr;
+ int exp_errno;
+} testcases[2];
+
+static void run(unsigned int n)
+{
+ struct futex_test_variants *tv = &variants[tst_variant];
+ struct testcase *tc = &testcases[n];
+
+ TST_EXP_FAIL(futex_wake(tv->fntype, tc->addr, 1, 0),
+ tc->exp_errno, "%s", tc->desc);
+}
+
+static void setup(void)
+{
+ struct futex_test_variants *tv = &variants[tst_variant];
+ size_t pagesize = getpagesize();
+ futex_t *unmapped;
+
+ tst_res(TINFO, "Testing variant: %s", tv->desc);
+ futex_supported_by_kernel(tv->fntype);
+
+ unmapped = SAFE_MMAP(NULL, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ SAFE_MUNMAP(unmapped, pagesize);
+
+ prot_none_addr = SAFE_MMAP(NULL, pagesize, PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ testcases[0] = (struct testcase){
+ .desc = "uaddr unmapped",
+ .addr = unmapped,
+ .exp_errno = EFAULT,
+ };
+ testcases[1] = (struct testcase){
+ .desc = "uaddr PROT_NONE",
+ .addr = prot_none_addr,
+ .exp_errno = EFAULT,
+ };
+}
+
+static void cleanup(void)
+{
+ if (prot_none_addr)
+ SAFE_MUNMAP(prot_none_addr, getpagesize());
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test = run,
+ .tcnt = ARRAY_SIZE(testcases),
+ .test_variants = ARRAY_SIZE(variants),
+};
--
2.53.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [LTP] futex: Add error coverage tests for wait, wake and cmp_requeue
2026-04-19 13:00 [LTP] [PATCH v3] futex: Add error coverage tests for wait, wake and cmp_requeue Michael Menasherov via ltp
@ 2026-04-19 14:46 ` linuxtestproject.agent
0 siblings, 0 replies; 3+ messages in thread
From: linuxtestproject.agent @ 2026-04-19 14:46 UTC (permalink / raw)
To: Michael Menasherov; +Cc: ltp
Hi Michael,
On Sun, 19 Apr 2026, Michael Menasherov wrote:
> futex: Add error coverage tests for wait, wake and cmp_requeue
> +++ b/testcases/kernel/syscalls/futex/futex_cmp_requeue03.c (new)
> +++ b/testcases/kernel/syscalls/futex/futex_wait06.c (new)
> +++ b/testcases/kernel/syscalls/futex/futex_wait07.c (new)
> +++ b/testcases/kernel/syscalls/futex/futex_wake05.c (new)
Each of these is an independent test case. LTP policy requires at most
one new test case per commit — please split into four separate patches.
---
Note:
Our agent completed the review of the patch. The full review can be
found at: https://github.com/linux-test-project/ltp-agent/actions/runs/24631582275
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] 3+ messages in thread
end of thread, other threads:[~2026-04-19 14:46 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-19 13:00 [LTP] [PATCH v3] futex: Add error coverage tests for wait, wake and cmp_requeue Michael Menasherov via ltp
2026-04-19 14:46 ` [LTP] " linuxtestproject.agent
-- strict thread matches above, loose matches on Subject: below --
2026-04-13 13:40 [LTP] [PATCH v2] " Michael Menasherov via ltp
2026-04-13 14:56 ` [LTP] " linuxtestproject.agent
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox