[PATCH v17 2/2] futex_cmp_requeue03: Add EFAULT error coverage test
Michael Menasherov via ltp <[email protected]>
| Newsgroups | gmane.linux.ltp |
|---|---|
| Message-ID | <[email protected]> |
futex(FUTEX_CMP_REQUEUE) has no existing test for EFAULT. Add coverage for the cases where uaddr or uaddr2 points to unmapped or inaccessible (PROT_NONE) memory. Signed-off-by: Michael Menasherov <[email protected]> --- runtest/syscalls | 1 + testcases/kernel/syscalls/futex/.gitignore | 1 + .../syscalls/futex/futex_cmp_requeue03.c | 103 ++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 testcases/kernel/syscalls/futex/futex_cmp_requeue03.c diff --git a/runtest/syscalls b/runtest/syscalls index 67509826f..0cb4e3dba 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -1864,6 +1864,7 @@ 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 diff --git a/testcases/kernel/syscalls/futex/.gitignore b/testcases/kernel/syscalls/futex/.gitignore index c11546e07..231b6bd25 100644 --- a/testcases/kernel/syscalls/futex/.gitignore +++ b/testcases/kernel/syscalls/futex/.gitignore @@ -16,3 +16,4 @@ /futex_wait06 /futex_wait07 /futex_wake05 +/futex_cmp_requeue03 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..43311bd9b --- /dev/null +++ b/testcases/kernel/syscalls/futex/futex_cmp_requeue03.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 Red Hat, Inc. + * Copyright (C) 2026 Michael Menasherov <[email protected]> + */ + +/*\ + * Check that futex(FUTEX_CMP_REQUEUE) returns EFAULT when uaddr or + * uaddr2 points to unmapped memory, or when uaddr or uaddr2 points to + * memory without read permission (PROT_NONE). + * + * The test uses opflags=0 (no FUTEX_PRIVATE_FLAG) so get_futex_key() + * takes the shared-futex path and resolves the physical page; this + * lookup fails with EFAULT for unmapped and PROT_NONE addresses. + * get_futex_key() is called for both uaddr and uaddr2 before the + * *uaddr == val check; futex_var and val are both FUTEX_INITIALIZER. + */ + +#include <errno.h> +#include <sys/mman.h> + +#include "futextest.h" + +static futex_t futex_var = FUTEX_INITIALIZER; +static futex_t *futex_ptr = &futex_var; +static futex_t *unmapped_addr; +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; +} testcases[] = { + { + .desc = "uaddr unmapped", + .uaddr = &unmapped_addr, + .uaddr2 = &futex_ptr, + }, + { + .desc = "uaddr2 unmapped", + .uaddr = &futex_ptr, + .uaddr2 = &unmapped_addr, + }, + { + .desc = "uaddr PROT_NONE", + .uaddr = &prot_none_addr, + .uaddr2 = &futex_ptr, + }, + { + .desc = "uaddr2 PROT_NONE", + .uaddr = &futex_ptr, + .uaddr2 = &prot_none_addr, + }, +}; + +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), EFAULT, "%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.55.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp