Linux Test Project
 help / color / mirror / Atom feed
* [LTP] [PATCH v17 0/2] futex: Add EFAULT error coverage tests
@ 2026-07-16 13:31 Michael Menasherov via ltp
  2026-07-16 13:31 ` [LTP] [PATCH v17 1/2] futex_wake05: Add EFAULT error coverage test Michael Menasherov via ltp
  2026-07-16 13:31 ` [LTP] [PATCH v17 2/2] futex_cmp_requeue03: " Michael Menasherov via ltp
  0 siblings, 2 replies; 7+ messages in thread
From: Michael Menasherov via ltp @ 2026-07-16 13:31 UTC (permalink / raw)
  To: ltp

Hi Petr,

Thanks for the review. Here is v17 addressing your feedback.

futex_wait06 and futex_wait07 were already merged. This series contains
the remaining two patches.

futex_cmp_requeue03:
  Applied your nit — removed the exp_errno field from the testcase struct
  and used EFAULT directly in TST_EXP_FAIL().

futex_wake05:
  Applied both nits (list comment format, EFAULT directly). For the
  kernel-space address case: you were right to question it. I couldn't
  confirm consistent EFAULT across kernels, so I looked for a better
  replacement.

  I used AI assistance to research the kernel's get_user_pages() code
  paths and cross-referenced existing LTP mmap tests to verify the
  approach. The replacement I landed on is a shared file-backed mapping
  where the file is truncated to 0 after mmap().

  The three cases now exercise genuinely different code paths:

  - unmapped memory fails at find_vma() (no VMA exists)
  - PROT_NONE memory fails at get_user_pages_fast() (VMA exists but
    page is inaccessible)
  - the truncated file mapping triggers VM_FAULT_SIGBUS inside the page
    fault handler (filemap_fault() sees offset beyond EOF), which
    get_user_pages() propagates as EFAULT

  The SIGBUS is never delivered to user space — get_user_pages() converts
  VM_FAULT_SIGBUS to -EFAULT internally. This behavior has been stable
  since before kernel 2.6 and works reliably on all architectures and
  both 32/64-bit. The test uses .needs_tmpdir = 1.

Changes since v16:
- futex_wake05: replace kernel-space address case with truncated
  file-backed mapping, fix comment to list format, use EFAULT directly
  in TST_EXP_FAIL(), add .needs_tmpdir
- futex_cmp_requeue03: use EFAULT directly in TST_EXP_FAIL()

Michael Menasherov (2):
  futex_wake05: Add EFAULT error coverage test
  futex_cmp_requeue03: Add EFAULT error coverage test

 runtest/syscalls                              |   2 +
 testcases/kernel/syscalls/futex/.gitignore    |   2 +
 .../syscalls/futex/futex_cmp_requeue03.c      | 103 ++++++++++++++++
 .../kernel/syscalls/futex/futex_wake05.c      | 113 ++++++++++++++++++
 4 files changed, 220 insertions(+)
 create mode 100644 testcases/kernel/syscalls/futex/futex_cmp_requeue03.c
 create mode 100644 testcases/kernel/syscalls/futex/futex_wake05.c

-- 
2.55.0


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

^ permalink raw reply	[flat|nested] 7+ messages in thread
* [LTP] [PATCH v16 1/2] futex_wake05: Add EFAULT error coverage test
@ 2026-06-21 15:09 Michael Menasherov via ltp
  2026-06-22  9:44 ` [LTP] " linuxtestproject.agent
  0 siblings, 1 reply; 7+ messages in thread
From: Michael Menasherov via ltp @ 2026-06-21 15:09 UTC (permalink / raw)
  To: ltp

futex(FUTEX_WAKE) has no existing test for EFAULT. Add coverage for
unmapped, PROT_NONE, and kernel-space uaddr, each exercising a
different code path in the kernel's address validation.

Signed-off-by: Michael Menasherov <mmenashe@redhat.com>
---
 runtest/syscalls                              |   1 +
 testcases/kernel/syscalls/futex/.gitignore    |   1 +
 .../kernel/syscalls/futex/futex_wake05.c      | 100 ++++++++++++++++++
 3 files changed, 102 insertions(+)
 create mode 100644 testcases/kernel/syscalls/futex/futex_wake05.c

diff --git a/runtest/syscalls b/runtest/syscalls
index a021c79da..67509826f 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1878,6 +1878,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 74ac9a926..c11546e07 100644
--- a/testcases/kernel/syscalls/futex/.gitignore
+++ b/testcases/kernel/syscalls/futex/.gitignore
@@ -15,3 +15,4 @@
 /futex_waitv03
 /futex_wait06
 /futex_wait07
+/futex_wake05
diff --git a/testcases/kernel/syscalls/futex/futex_wake05.c b/testcases/kernel/syscalls/futex/futex_wake05.c
new file mode 100644
index 000000000..597426f0a
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_wake05.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Red Hat, Inc.
+ * Copyright (C) 2026 Michael Menasherov <mmenashe@redhat.com>
+ */
+
+/*\
+ * Check that futex(FUTEX_WAKE) returns EFAULT when uaddr points to
+ * unmapped, PROT_NONE, or kernel-space memory.
+ *
+ * For opflags=0 (no FUTEX_PRIVATE_FLAG) futex_wake() takes the
+ * shared-futex path in get_futex_key() which must resolve the physical
+ * page.
+ *
+ * The three cases exercise different code paths: a kernel-space address
+ * is rejected by the kernel's user-space address check before physical
+ * page resolution; unmapped memory fails at find_vma() (no VMA exists);
+ * PROT_NONE memory fails at get_user_pages_fast() (VMA exists but page
+ * is inaccessible).
+ */
+
+#include <errno.h>
+#include <sys/mman.h>
+
+#include "futextest.h"
+
+static futex_t *unmapped_addr;
+static futex_t *prot_none_addr;
+static futex_t *kernel_addr = (futex_t *)-1L;
+
+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[] = {
+	{
+		.desc = "uaddr unmapped",
+		.addr = &unmapped_addr,
+		.exp_errno = EFAULT,
+	},
+	{
+		.desc = "uaddr PROT_NONE",
+		.addr = &prot_none_addr,
+		.exp_errno = EFAULT,
+	},
+	{
+		.desc = "uaddr kernel address",
+		.addr = &kernel_addr,
+		.exp_errno = EFAULT,
+	},
+};
+
+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();
+
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	futex_supported_by_kernel(tv->fntype);
+
+	unmapped_addr = SAFE_MMAP(NULL, pagesize, PROT_READ | PROT_WRITE,
+				  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	SAFE_MUNMAP((void *)unmapped_addr, pagesize);
+
+	prot_none_addr = SAFE_MMAP(NULL, pagesize, PROT_NONE,
+				   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
+static void cleanup(void)
+{
+	if (prot_none_addr)
+		SAFE_MUNMAP((void *)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.54.0


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

^ permalink raw reply related	[flat|nested] 7+ messages in thread
* [LTP] [PATCH v15 1/2] futex_wake05: Add EFAULT error coverage test
@ 2026-06-16 18:30 Michael Menasherov via ltp
  2026-06-16 19:47 ` [LTP] " linuxtestproject.agent
  0 siblings, 1 reply; 7+ messages in thread
From: Michael Menasherov via ltp @ 2026-06-16 18:30 UTC (permalink / raw)
  To: ltp

futex(FUTEX_WAKE) has no existing test for EFAULT. Add coverage for
unmapped, PROT_NONE, and kernel-space uaddr, each exercising a
different code path in the kernel's address validation.

Signed-off-by: Michael Menasherov <mmenashe@redhat.com>
---
 runtest/syscalls                              |   1 +
 testcases/kernel/syscalls/futex/.gitignore    |   1 +
 .../kernel/syscalls/futex/futex_wake05.c      | 101 ++++++++++++++++++
 3 files changed, 103 insertions(+)
 create mode 100644 testcases/kernel/syscalls/futex/futex_wake05.c

diff --git a/runtest/syscalls b/runtest/syscalls
index a021c79da..67509826f 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1878,6 +1878,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 74ac9a926..c11546e07 100644
--- a/testcases/kernel/syscalls/futex/.gitignore
+++ b/testcases/kernel/syscalls/futex/.gitignore
@@ -15,3 +15,4 @@
 /futex_waitv03
 /futex_wait06
 /futex_wait07
+/futex_wake05
diff --git a/testcases/kernel/syscalls/futex/futex_wake05.c b/testcases/kernel/syscalls/futex/futex_wake05.c
new file mode 100644
index 000000000..162bc4e04
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_wake05.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Red Hat, Inc.
+ * Copyright (C) 2026 Michael Menasherov <mmenashe@redhat.com>
+ */
+
+/*\
+ * Check that futex(FUTEX_WAKE) returns EFAULT when uaddr points to
+ * unmapped, PROT_NONE, or kernel-space memory.
+ *
+ * For the unmapped and PROT_NONE cases, opflags=0 (no FUTEX_PRIVATE_FLAG)
+ * ensures futex_wake() takes the shared-futex path in get_futex_key()
+ * which must resolve the physical page. For PROT_NONE memory this page
+ * lookup fails with EFAULT, even though futex_wake() never reads *uaddr.
+ *
+ * The three cases exercise different code paths: a kernel-space address
+ * is rejected by the kernel's user-space address check before physical
+ * page resolution; unmapped memory fails at find_vma() (no VMA exists);
+ * PROT_NONE memory fails at get_user_pages_fast() (VMA exists but page
+ * is inaccessible).
+ */
+
+#include <errno.h>
+#include <sys/mman.h>
+
+#include "futextest.h"
+
+static futex_t *unmapped_addr;
+static futex_t *prot_none_addr;
+static futex_t *kernel_addr = (futex_t *)-1L;
+
+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[] = {
+	{
+		.desc = "uaddr unmapped",
+		.addr = &unmapped_addr,
+		.exp_errno = EFAULT,
+	},
+	{
+		.desc = "uaddr PROT_NONE",
+		.addr = &prot_none_addr,
+		.exp_errno = EFAULT,
+	},
+	{
+		.desc = "uaddr kernel address",
+		.addr = &kernel_addr,
+		.exp_errno = EFAULT,
+	},
+};
+
+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();
+
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	futex_supported_by_kernel(tv->fntype);
+
+	unmapped_addr = SAFE_MMAP(NULL, pagesize, PROT_READ | PROT_WRITE,
+				  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	SAFE_MUNMAP((void *)unmapped_addr, pagesize);
+
+	prot_none_addr = SAFE_MMAP(NULL, pagesize, PROT_NONE,
+				   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
+static void cleanup(void)
+{
+	if (prot_none_addr)
+		SAFE_MUNMAP((void *)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.54.0


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

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

end of thread, other threads:[~2026-07-17 10:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-16 13:31 [LTP] [PATCH v17 0/2] futex: Add EFAULT error coverage tests Michael Menasherov via ltp
2026-07-16 13:31 ` [LTP] [PATCH v17 1/2] futex_wake05: Add EFAULT error coverage test Michael Menasherov via ltp
2026-07-16 15:15   ` [LTP] " linuxtestproject.agent
2026-07-17 10:01     ` Cyril Hrubis
2026-07-16 13:31 ` [LTP] [PATCH v17 2/2] futex_cmp_requeue03: " Michael Menasherov via ltp
  -- strict thread matches above, loose matches on Subject: below --
2026-06-21 15:09 [LTP] [PATCH v16 1/2] futex_wake05: " Michael Menasherov via ltp
2026-06-22  9:44 ` [LTP] " linuxtestproject.agent
2026-06-16 18:30 [LTP] [PATCH v15 1/2] " Michael Menasherov via ltp
2026-06-16 19:47 ` [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