[LTP] [PATCH v16 1/2] futex_wake05: Add EFAULT error coverage test

Petr Vorel pvorel@suse.cz
Fri Jul 3 10:32:15 CEST 2026


Hi Michael,

> 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.

Generally LGTM, few comments below.

> 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).
nit: It'd be more readable using list:

 * 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,
nit: If all errors are EFAULT why not use it directly in TST_EXP_FAIL?

But more important is that I got a different errno (EINVAL) on 7.0.x kernel on
old kernel spec:

futex_wake05.c:77: TINFO: Testing variant: syscall with old kernel spec
futex_wake05.c:68: TFAIL: uaddr kernel address expected EFAULT: EINVAL (22)

When compiling 32 bit, I get error on both specs:

PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig CFLAGS=-m32 LDFLAGS=-m32 ./configure
...
futex_wake05.c:77: TINFO: Testing variant: syscall with old kernel spec
futex_wake05.c:68: TPASS: uaddr unmapped : EFAULT (14)
futex_wake05.c:68: TPASS: uaddr PROT_NONE : EFAULT (14)
futex_wake05.c:68: TFAIL: uaddr kernel address expected EFAULT: EINVAL (22)
futex_wake05.c:77: TINFO: Testing variant: syscall time64 with kernel spec
futex_wake05.c:68: TPASS: uaddr unmapped : EFAULT (14)
futex_wake05.c:68: TPASS: uaddr PROT_NONE : EFAULT (14)
futex_wake05.c:68: TFAIL: uaddr kernel address expected EFAULT: EINVAL (22)

I tested very old kernel 4.4 (SLE12-SP3 we still support) and it behaves the
same. Do you really get EFAULT?

Kind regards,
Petr


More information about the ltp mailing list