From: Petr Vorel <pvorel@suse.cz>
To: Wei Gao <wegao@suse.com>
Cc: ltp@lists.linux.it
Subject: Re: [LTP] [PATCH v1] iocl11.c: New case check PROCMAP_QUERY ioctl() errnos
Date: Thu, 7 Aug 2025 10:36:49 +0200 [thread overview]
Message-ID: <20250807083649.GA358446@pevik> (raw)
In-Reply-To: <20250807134900.517339-1-wegao@suse.com>
Hi Wei,
Thanks for writing new test. Generally LGTM.
Also, FYI upstream developer enhanced existing tools/testing/selftests/proc/proc-pid-vm.c
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=81510a0eaa6916c2fbb0b2639f3e617a296979a3
That might be a good source for real PROCMAP_QUERY testing.
Few common errors:
1) git commit subject contains typo:
iocl11 => ioctl11
Please remember to fix it.
2) Warning
$ make check-ioctl11
CHECK testcases/kernel/syscalls/ioctl/ioctl11.c
ioctl11.c:32:22: warning: Symbol 'q' has no prototype or library ('tst_') prefix. Should it be static?
3) EMFILE (Too many open files)
=> missing SAFE_FCLOSE(fp) before return start_addr;
# ./ioctl11 -i1200
ioctl11.c:149: TPASS: ioctl(fd, PROCMAP_QUERY, q) : E2BIG (7)
ioctl11.c:149: TPASS: ioctl(fd, PROCMAP_QUERY, q) : EINVAL (22)
ioctl11.c:101: TBROK: fopen(/proc/self/maps,r) failed: EMFILE (24)
ioctl11.c: In function ‘get_vm_start’:
ioctl11.c:113:1: warning: control reaches end of non-void function [-Wreturn-type]
113 | }
| ^
Other notes below.
...
> diff --git a/testcases/kernel/syscalls/ioctl/ioctl11.c b/testcases/kernel/syscalls/ioctl/ioctl11.c
> new file mode 100644
> index 000000000..aef2105cc
> --- /dev/null
> +++ b/testcases/kernel/syscalls/ioctl/ioctl11.c
> @@ -0,0 +1,183 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2024 Wei Gao <wegao@suse.com>
Maybe update to 2025?
> + */
> +
> +/*\
> + * [Description]
> + *
> + * Test PROCMAP_QUERY ioctl() errnos:
> + *
> + * - EINVAL if q->size is too small
> + * - E2BIG if q->size is larger than page size
> + * - EINVAL on invalid q->flags
> + * - EINVAL if only one of q->vma_name_size and q->vma_name_addr is set
> + * - EINVAL if only one of q->build_id_size and q->build_id_addr is set
> + * - ENAMETOOLONG if build_id_size or name_buf_size is too small
What is name_buf_size? Do you mean vma_name_size?
I wonder whether pointing out in doc some of the relevant commits (6 commits
mentioned in "(FEATURED) ioctl()-based API to query VMAs from /proc/<pid>"
section in [1]) or just put [2] (or [3] would make sense.
[1] https://kernelnewbies.org/Linux_6.11#Memory_management
[2] https://kernelnewbies.org/Linux_6.11#Binary_interface_for_.2Fproc.2F.3Cpid.3E.2Fmaps
[3] https://lore.kernel.org/all/20240627170900.1672542-1-andrii@kernel.org/
ed5d583a88a9 ("fs/procfs: implement efficient VMA querying API for /proc/<pid>/maps")
> + */
> +
> +#include "config.h"
> +#include <stdlib.h>
Either <stdlib.h> is not needed or some of LTP headers probably adds it as it
builds without it.
> +#include <sys/ioctl.h>
<sys/ioctl.h> is not needed (loaded as part of lapi/ioctl.h.
https://github.com/linux-test-project/ltp/blob/master/doc/old/C-Test-API.asciidoc#lapi-headers
> +#include <errno.h>
> +#include <fnmatch.h>
Why this header? IMHO not needed.
> +#include "tst_test.h"
> +#include "tst_safe_stdio.h"
> +#include <sys/sysmacros.h>
Why this header? IMHO not needed.
very nit: Also I would first add system headers (these with <>) and then LTP
headers. i.e. not mixing them.
> +#include <linux/fs.h>
> +#include "lapi/ioctl.h"
> +
#include "config.h"
#include <errno.h>
#include <linux/fs.h>
#include "tst_test.h"
#include "tst_safe_stdio.h"
#include "lapi/ioctl.h"
> +#define PROC_MAP_PATH "/proc/self/maps"
> +
> +struct procmap_query *q;
This should be static.
> +static int fd = -1;
> +static char buf[PATH_MAX];
> +static char small_buf[1];
> +
> +static void setup_normal(void);
> +static void setup_big_size(void);
> +
> +static struct tcase {
> + uint64_t size;
> + uint64_t query_addr;
> + uint64_t query_flags;
> + uint64_t vma_name_addr;
> + uint32_t vma_name_size;
> + uint64_t build_id_addr;
> + uint32_t build_id_size;
> + int exp_errno;
> + void (*setup)(void);
> +} tcases[] = {
> + {
> + .size = 1,
> + .exp_errno = EINVAL,
> + .setup = setup_normal
> + },
> + {
> + .exp_errno = E2BIG,
> + .setup = setup_big_size
> + },
> + {
> + .query_flags = -1,
> + .exp_errno = EINVAL,
> + .setup = setup_normal
> + },
> + {
> + .vma_name_size = sizeof(buf),
> + .exp_errno = EINVAL,
> + .setup = setup_normal
> + },
> + {
> + .vma_name_addr = (uint64_t)(unsigned long)buf,
> + .exp_errno = EINVAL,
> + .setup = setup_normal
> + },
> + {
> + .build_id_size = sizeof(buf),
> + .exp_errno = EINVAL,
> + .setup = setup_normal
> + },
> + {
> + .build_id_addr = (uint64_t)(unsigned long)buf,
> + .exp_errno = EINVAL,
> + .setup = setup_normal
> + },
> + {
> + .vma_name_addr = (uint64_t)(unsigned long)small_buf,
> + .vma_name_size = sizeof(small_buf),
> + .exp_errno = ENAMETOOLONG,
> + .setup = setup_normal
> + },
> + {
> + .build_id_addr = (uint64_t)(unsigned long)small_buf,
> + .build_id_size = sizeof(small_buf),
> + .exp_errno = ENAMETOOLONG,
> + .setup = setup_normal
> + },
> +};
> +
> +static unsigned long get_vm_start(void)
> +{
> + FILE *fp = SAFE_FOPEN(PROC_MAP_PATH, "r");
> + char line[1024];
> + unsigned long start_addr = 0;
> +
> + if (fgets(line, sizeof(line), fp) != NULL) {
> + if (sscanf(line, "%lx-", &start_addr) != 1)
> + tst_brk(TFAIL, "parse maps file /proc/self/maps failed");
nit: Maybe "map not found in /proc/self/maps"?
Also, PROC_MAP_PATH will never change from /proc/self/maps, so it's probably safe
to use it hardcoded. But using just "map not found" would avoid hardcoded file.
Here you needs to also close fp.
> + return start_addr;
> + }
> +
> + SAFE_FCLOSE(fp);
> + tst_brk(TFAIL, "parse maps file /proc/self/maps failed");
> +}
> +
> +static void setup_normal(void)
> +{
> + q->size = sizeof(*q);
> + q->query_addr = (uint64_t)get_vm_start();
> + q->query_flags = 0;
> +}
> +
> +static void setup_big_size(void)
> +{
> + setup_normal();
IMHO content of setup_normal() should be moved to run(), before tc->setup().
Then all ".setup = setup_normal" could be removed.
> + q->size = getpagesize() + 1;
> +}
> +
> +static void run(unsigned int n)
> +{
> + struct tcase *tc = &tcases[n];
> +
> + memset(q, 0, sizeof(*q));
> +
> + tc->setup();
> +
> + if (tc->size != 0)
> + q->size = tc->size;
Spaces between each if would make code for me more readable.
> + if (tc->query_flags != 0)
> + q->query_flags = tc->query_flags;
> + if (tc->vma_name_addr != 0)
> + q->vma_name_addr = tc->vma_name_addr;
> + if (tc->vma_name_size != 0)
> + q->vma_name_size = tc->vma_name_size;
> + if (tc->build_id_addr != 0)
> + q->build_id_addr = tc->build_id_addr;
> + if (tc->build_id_size != 0)
> + q->build_id_size = tc->build_id_size;
> +
> + TST_EXP_FAIL(ioctl(fd, PROCMAP_QUERY, q), tc->exp_errno);
> +}
> +
> +static void setup(void)
> +{
> + struct procmap_query q = {};
> +
> + fd = SAFE_OPEN(PROC_MAP_PATH, O_RDONLY);
> +
> + if (tst_kvercmp(6, 11, 0) < 0) {
If you reverse the condition code is more compact.
> + TEST(ioctl(fd, PROCMAP_QUERY, q));
> +
> + if ((TST_RET == -1) && (TST_ERR == ENOTTY))
Brackets between && are not needed.
> + tst_brk(TCONF,
> + "This system does not provide support for ioctl(PROCMAP_QUERY)");
if (tst_kvercmp(6, 11, 0) >= 0)
return;
TEST(ioctl(fd, PROCMAP_QUERY, q));
if (TST_RET == -1 && TST_ERR == ENOTTY) {
tst_brk(TCONF,
"This system does not provide support for ioctl(PROCMAP_QUERY)");
}
> + }
> +
Please remove this blank line ^.
> +}
Kind regards,
Petr
--
Mailing list info: https://lists.linux.it/listinfo/ltp
next prev parent reply other threads:[~2025-08-07 8:37 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-07 13:48 [LTP] [PATCH v1] iocl11.c: New case check PROCMAP_QUERY ioctl() errnos Wei Gao via ltp
2025-08-07 8:36 ` Petr Vorel [this message]
2025-08-08 16:30 ` [LTP] [PATCH v2] ioctl11.c: " Wei Gao via ltp
2025-08-12 6:14 ` [LTP] [PATCH v3] " Wei Gao via ltp
2025-08-12 14:07 ` Petr Vorel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250807083649.GA358446@pevik \
--to=pvorel@suse.cz \
--cc=ltp@lists.linux.it \
--cc=wegao@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.