[{"id":3676619,"web_url":"http://patchwork.ozlabs.org/comment/3676619/","msgid":"<20260413095540.GA112666@pevik>","list_archive_url":null,"date":"2026-04-13T09:55:40","subject":"Re: [LTP] [PATCH] futex: Add error coverage tests for wait,\n wake and cmp_requeue","submitter":{"id":70792,"url":"http://patchwork.ozlabs.org/api/people/70792/","name":"Petr Vorel","email":"pvorel@suse.cz"},"content":"Hi Michael,\n\n> Improve error handling coverage for futex syscalls by adding tests\n> for missing error conditions that were previously untested.\n\n> futex_wait06 verifies EFAULT is returned when uaddr or timeout\n> points to unmapped memory.\n\n> futex_wait07 verifies EINTR is returned when futex_wait() is\n> interrupted by a signal.\n\n> futex_wake05 verifies EFAULT is returned when uaddr points to\n> unmapped or PROT_NONE memory.\n\nThanks for sending this on ML (instead of continuing in GitHub PR).\nIt would help if you looked into some recently converted tests to new LTP API to\navoid common errors.\n\nYou should add your SOB:\nSigned-off-by: Michael Menasherov <mmenashe@redhat.com>\n(or whatever email address you prefer)\nhttps://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin\n(That is even in .github/pull_request_template.md, which content you have seen\nwhen opening your previous effort https://github.com/linux-test-project/ltp/pull/1301.)\n\n> futex_cmp_requeue03 verifies EFAULT is returned when uaddr or\n> uaddr2 points to unmapped memory, and EACCES or EFAULT when uaddr\n> points to memory without read permission (PROT_NONE). The EACCES\n> behavior was introduced in kernel 5.9.\n> ---\n>  runtest/syscalls                              |   4 +\n>  testcases/kernel/syscalls/futex/.gitignore    |   4 +\n>  .../syscalls/futex/futex_cmp_requeue03.c      | 102 ++++++++++++++++\n>  .../kernel/syscalls/futex/futex_wait06.c      |  81 +++++++++++++\n>  .../kernel/syscalls/futex/futex_wait07.c      | 114 ++++++++++++++++++\n>  .../kernel/syscalls/futex/futex_wake05.c      |  85 +++++++++++++\n>  6 files changed, 390 insertions(+)\n>  create mode 100644 testcases/kernel/syscalls/futex/futex_cmp_requeue03.c\n>  create mode 100644 testcases/kernel/syscalls/futex/futex_wait06.c\n>  create mode 100644 testcases/kernel/syscalls/futex/futex_wait07.c\n>  create mode 100644 testcases/kernel/syscalls/futex/futex_wake05.c\n\n...\n> diff --git a/testcases/kernel/syscalls/futex/futex_cmp_requeue03.c b/testcases/kernel/syscalls/futex/futex_cmp_requeue03.c\n> new file mode 100644\n> index 000000000..66b18614d\n> --- /dev/null\n> +++ b/testcases/kernel/syscalls/futex/futex_cmp_requeue03.c\n> @@ -0,0 +1,102 @@\n> +// SPDX-License-Identifier: GPL-2.0-or-later\n> +/*\n> + * Copyright (C) 2024 Red Hat, Inc.\nnit: Not sure why 2024, maybe you base it on older code. But there should be\n2026 as it's also new code, right?\n\n> + *\nPlease use this to start comment:\n\n/*\\\n\nThat helps to add the test in test catalog.\nhttps://linux-test-project.readthedocs.io/en/latest/users/test_catalog.html\n\n> + * Check that futex(FUTEX_CMP_REQUEUE) returns EFAULT when uaddr or\n> + * uaddr2 points to unmapped memory, and EACCES when uaddr points to\n> + * memory without read permission (PROT_NONE).\nNOTE: we always want to match error to exact errno, even on a different kernel\nversion.\n\n> + */\n> +\n> +#include <errno.h>\n> +#include <sys/mman.h>\n> +\n> +#include \"futextest.h\"\n> +\n> +static futex_t futex = FUTEX_INITIALIZER;\n> +static void *unmapped_addr;\n> +static void *prot_none_addr;\n> +\n> +static struct futex_test_variants variants[] = {\n> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)\n> +\t{ .fntype = FUTEX_FN_FUTEX, .desc = \"syscall with old kernel spec\"},\n> +#endif\n> +\n> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)\n> +\t{ .fntype = FUTEX_FN_FUTEX64, .desc = \"syscall time64 with kernel spec\"},\n> +#endif\n> +};\n> +\n> +static struct testcase {\n> +\tconst char *desc;\n> +\t/* 1 = uaddr is bad, 0 = uaddr2 is bad */\n> +\tint bad_uaddr;\n> +\t/* 1 = PROT_NONE address, 0 = unmapped address */\n> +\tint use_prot_none;\nWhy don't define directly pointers to futex_t andd assign static address to it?\n\nstatic struct testcase {\n\tconst char *desc;\n\tfutex_t *uaddr;\n\tfutex_t *uaddr2;\n\tint exp_errno;\n} testcases[] = {\n\t{ .desc = \"uaddr unmapped\", .uaddr = (futex_t *)&unmapped_addr, .uaddr2 = &futex, .exp_errno = EFAULT },\n\t{ .desc = \"uaddr2 unmapped\", .uaddr = &futex, .uaddr2 = (futex_t *)&unmapped_addr, .exp_errno = EFAULT },\n\t{ .desc = \"uaddr PROT_NONE\", .uaddr = (futex_t *)&prot_none_addr, .uaddr2 = &futex, .exp_errno = EACCES },\n}\n\nYou specify in the commit message that EACCES behavior changed for kernel 5.9\nfrom EFAULT to EACCES. Therefore in setup() you should check for a kernel\nversions, have look at testcases/kernel/syscalls/listmount/listmount04.c.\n\n> +} testcases[] = {\n> +\t{ \"uaddr unmapped\", 1, 0 },\n> +\t{ \"uaddr2 unmapped\", 0, 0 },\n> +\t{ \"uaddr PROT_NONE\", 1, 1 },\n\nPlease use designated initializers, that allows avoid having to specify 0 or NULL.\n\n\n> +};\n> +\n> +static void run(unsigned int n)\n> +{\n> +\tstruct futex_test_variants *tv = &variants[tst_variant];\n> +\tstruct testcase *tc = &testcases[n];\n> +\tfutex_t *bad;\n> +\tfutex_t *uaddr, *uaddr2;\n> +\tint res;\n> +\n> +\tif (tc->use_prot_none)\n> +\t\tbad = (futex_t *)prot_none_addr;\n> +\telse\n> +\t\tbad = (futex_t *)unmapped_addr;\n> +\n> +\t/* Assign bad address to uaddr or uaddr2, keep the other valid. */\n> +\tif (tc->bad_uaddr) {\n> +\t\tuaddr = bad;\n> +\t\tuaddr2 = &futex;\n> +\t} else {\n> +\t\tuaddr = &futex;\n> +\t\tuaddr2 = bad;\n> +\t}\nAll this will not be needed once you just pass the pointers in test struct.\n> +\n> +\tres = futex_cmp_requeue(tv->fntype, uaddr, futex, uaddr2, 1, 1, 0);\n> +\tif (res != -1) {\n> +\t\ttst_res(TFAIL, \"futex_cmp_requeue() succeeded unexpectedly for '%s'\", tc->desc);\n> +\t\treturn;\n> +\t}\n> +\tif (errno != EFAULT && errno != EACCES) {\n> +\t\ttst_res(TFAIL | TERRNO, \"futex_cmp_requeue() failed with unexpected error for '%s', expected EFAULT or EACCES\",tc->desc);\n> +\t\treturn;\n> +\t}\n> +\ttst_res(TPASS | TERRNO, \"futex_cmp_requeue() failed as expected for '%s'\", tc->desc);\nThis should be shortened by using TST_EXP_FAIL().\nhttps://linux-test-project.readthedocs.io/en/latest/developers/api_c_tests.html#macro-tst-exp-fail\n\nWe want to specify single errno, but FYI we have also TST_EXP_FAIL_ARR().\nhttps://linux-test-project.readthedocs.io/en/latest/developers/api_c_tests.html#macro-tst-exp-fail-arr\n\n> +}\n> +\n> +static void setup(void)\n> +{\n> +\tstruct futex_test_variants *tv = &variants[tst_variant];\n> +\tsize_t pagesize = getpagesize();\n> +\n> +\ttst_res(TINFO, \"Testing variant: %s\", tv->desc);\n> +\tfutex_supported_by_kernel(tv->fntype);\n> +\n> +\tunmapped_addr = SAFE_MMAP(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n> +\tSAFE_MUNMAP(unmapped_addr, pagesize);\n> +\t/* PROT_NONE = mapped but no read permission, triggers EACCES or EFAULT */\n> +\tprot_none_addr = SAFE_MMAP(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n> +}\n> +\n> +static void cleanup(void)\n> +{\n> +\tif (prot_none_addr) {\n> +\t\tSAFE_MUNMAP(prot_none_addr, getpagesize());\n> +\t}\nYou probably used make check for errors.\nPlease run it on rebased master, it will ask you to remove { }.\n\n> +}\n> +\n> +static struct tst_test test = {\n> +\t.setup = setup,\n> +\t.cleanup = cleanup,\n> +\t.test = run,\n> +\t.tcnt = ARRAY_SIZE(testcases),\n> +\t.test_variants = ARRAY_SIZE(variants),\n> +};\n> diff --git a/testcases/kernel/syscalls/futex/futex_wait06.c b/testcases/kernel/syscalls/futex/futex_wait06.c\n> new file mode 100644\n> index 000000000..1b9db0241\n> --- /dev/null\n> +++ b/testcases/kernel/syscalls/futex/futex_wait06.c\n\nMost of previous comments apply to other tests as well.\n\n> @@ -0,0 +1,81 @@\n> +// SPDX-License-Identifier: GPL-2.0-or-later\n> +/*\n> + * Copyright (C) 2024 Red Hat, Inc.\n> + *\n> + * Check that futex(FUTEX_WAIT) returns EFAULT when:\nYou need to add blank space here to fix formatting of the doc.\n\nTo test generated doc you can:\n$ make -C doc/ setup # creates doc/.venv/\n$ make -C doc/\n=> see doc/html/users/test_catalog.html\n\nUnfortunately we don't any CI check for it (yet).\n\n> + * 1) uaddr points to unmapped memory\n> + * 2) timeout points to unmapped memory\n> + */\n\n> +#include <errno.h>\n> +#include <sys/mman.h>\n> +\n> +#include \"futextest.h\"\n> +\n> +static futex_t futex = FUTEX_INITIALIZER;\n> +static void *bad_addr;\n> +\n> +static struct futex_test_variants variants[] = {\n> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)\n> +\t{ .fntype = FUTEX_FN_FUTEX, .tstype = TST_KERN_OLD_TIMESPEC, .desc = \"syscall with old kernel spec\"},\n> +#endif\n> +\n> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)\n> +\t{ .fntype = FUTEX_FN_FUTEX64, .tstype = TST_KERN_TIMESPEC, .desc = \"syscall time64 with kernel spec\"},\n> +#endif\n> +};\n> +\n> +static struct testcase {\n> +\tconst char *desc;\n> +} testcases[] = {\n> +\t{ \"uaddr points to unmapped memory\" },\n> +\t{ \"timeout points to unmapped memory\" },\n\nIf only desc was needed, it could be printed directly (no need for struct).\n\nKind regards,\nPetr","headers":{"Return-Path":"<ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it>","X-Original-To":["incoming@patchwork.ozlabs.org","ltp@lists.linux.it"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","ltp@picard.linux.it"],"Authentication-Results":["legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.linux.it\n (client-ip=2001:1418:10:5::2; helo=picard.linux.it;\n envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it;\n receiver=patchwork.ozlabs.org)","smtp-out2.suse.de;\n\tnone"],"Received":["from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fvN893D7Bz1y2d\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 13 Apr 2026 19:55:51 +1000 (AEST)","from picard.linux.it (localhost [IPv6:::1])\n\tby picard.linux.it (Postfix) with ESMTP id 9D2993E2942\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 13 Apr 2026 11:55:48 +0200 (CEST)","from in-2.smtp.seeweb.it (in-2.smtp.seeweb.it [217.194.8.2])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature ECDSA (secp384r1))\n (No client certificate requested)\n by picard.linux.it (Postfix) with ESMTPS id 167653CD98D\n for <ltp@lists.linux.it>; Mon, 13 Apr 2026 11:55:43 +0200 (CEST)","from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by in-2.smtp.seeweb.it (Postfix) with ESMTPS id 424556002C4\n for <ltp@lists.linux.it>; Mon, 13 Apr 2026 11:55:43 +0200 (CEST)","from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org\n [IPv6:2a07:de40:b281:104:10:150:64:97])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n (No client certificate requested)\n by smtp-out2.suse.de (Postfix) with ESMTPS id A16775BD32;\n Mon, 13 Apr 2026 09:55:42 +0000 (UTC)","from imap1.dmz-prg2.suse.org (localhost [127.0.0.1])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n (No client certificate requested)\n by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id CBF194AE10;\n Mon, 13 Apr 2026 09:55:41 +0000 (UTC)","from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167])\n by imap1.dmz-prg2.suse.org with ESMTPSA id FYMxL5293GlzagAAD6G6ig\n (envelope-from <pvorel@suse.cz>); Mon, 13 Apr 2026 09:55:41 +0000"],"Date":"Mon, 13 Apr 2026 11:55:40 +0200","From":"Petr Vorel <pvorel@suse.cz>","To":"Michael Menasherov <mmenashe@redhat.com>","Message-ID":"<20260413095540.GA112666@pevik>","References":"<20260412134046.31161-1-mmenashe@redhat.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20260412134046.31161-1-mmenashe@redhat.com>","X-Rspamd-Pre-Result":["action=no action; module=replies;\n Message is reply to one we originated","action=no action; module=replies;\n Message is reply to one we originated"],"X-Rspamd-Server":"rspamd2.dmz-prg2.suse.org","X-Spamd-Result":"default: False [-4.00 / 50.00];\n\tREPLY(-4.00)[]","X-Rspamd-Queue-Id":"A16775BD32","X-Rspamd-Action":"no action","X-Spam-Score":"-4.00","X-Spam-Level":"","X-Spam-Status":"No, score=0.0 required=7.0 tests=DMARC_MISSING,SPF_HELO_NONE,\n SPF_PASS shortcircuit=no autolearn=disabled version=4.0.1","X-Spam-Checker-Version":"SpamAssassin 4.0.1 (2024-03-25) on in-2.smtp.seeweb.it","X-Virus-Scanned":"clamav-milter 1.0.9 at in-2.smtp.seeweb.it","X-Virus-Status":"Clean","Subject":"Re: [LTP] [PATCH] futex: Add error coverage tests for wait,\n wake and cmp_requeue","X-BeenThere":"ltp@lists.linux.it","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"Linux Test Project <ltp.lists.linux.it>","List-Unsubscribe":"<https://lists.linux.it/options/ltp>,\n <mailto:ltp-request@lists.linux.it?subject=unsubscribe>","List-Archive":"<http://lists.linux.it/pipermail/ltp/>","List-Post":"<mailto:ltp@lists.linux.it>","List-Help":"<mailto:ltp-request@lists.linux.it?subject=help>","List-Subscribe":"<https://lists.linux.it/listinfo/ltp>,\n <mailto:ltp-request@lists.linux.it?subject=subscribe>","Reply-To":"Petr Vorel <pvorel@suse.cz>","Cc":"ltp@lists.linux.it","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it","Sender":"\"ltp\" <ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it>"}}]