| From: Andrii Nakryiko <andrii@kernel.org> |
| Subject: selftests/proc: add PROCMAP_QUERY ioctl tests |
| Date: Thu, 27 Jun 2024 10:08:58 -0700 |
| |
| Extend existing proc-pid-vm.c tests with PROCMAP_QUERY ioctl() API. Test |
| a few successful and negative cases, validating querying filtering and |
| exact vs next VMA logic works as expected. |
| |
| Link: https://lkml.kernel.org/r/20240627170900.1672542-7-andrii@kernel.org |
| Signed-off-by: Andrii Nakryiko <andrii@kernel.org> |
| Acked-by: Liam R. Howlett <Liam.Howlett@Oracle.com> |
| Cc: Alexey Dobriyan <adobriyan@gmail.com> |
| Cc: Al Viro <viro@zeniv.linux.org.uk> |
| Cc: Christian Brauner <brauner@kernel.org> |
| Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Cc: Mike Rapoport (IBM) <rppt@kernel.org> |
| Cc: Suren Baghdasaryan <surenb@google.com> |
| Cc: Andi Kleen <ak@linux.intel.com> |
| Cc: Arnd Bergmann <arnd@arndb.de> |
| Cc: Stephen Rothwell <sfr@canb.auug.org.au> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| tools/testing/selftests/proc/Makefile | 1 |
| tools/testing/selftests/proc/proc-pid-vm.c | 86 +++++++++++++++++++ |
| 2 files changed, 87 insertions(+) |
| |
| --- a/tools/testing/selftests/proc/Makefile~selftests-proc-add-procmap_query-ioctl-tests |
| +++ a/tools/testing/selftests/proc/Makefile |
| @@ -1,5 +1,6 @@ |
| # SPDX-License-Identifier: GPL-2.0-only |
| CFLAGS += -Wall -O2 -Wno-unused-function |
| +CFLAGS += $(TOOLS_INCLUDES) |
| LDFLAGS += -pthread |
| |
| TEST_GEN_PROGS := |
| --- a/tools/testing/selftests/proc/proc-pid-vm.c~selftests-proc-add-procmap_query-ioctl-tests |
| +++ a/tools/testing/selftests/proc/proc-pid-vm.c |
| @@ -45,6 +45,7 @@ |
| #include <linux/kdev_t.h> |
| #include <sys/time.h> |
| #include <sys/resource.h> |
| +#include <linux/fs.h> |
| |
| #include "../kselftest.h" |
| |
| @@ -492,6 +493,91 @@ int main(void) |
| assert(buf[13] == '\n'); |
| } |
| |
| + /* Test PROCMAP_QUERY ioctl() for /proc/$PID/maps */ |
| + { |
| + char path_buf[256], exp_path_buf[256]; |
| + struct procmap_query q; |
| + int fd, err; |
| + |
| + snprintf(path_buf, sizeof(path_buf), "/proc/%u/maps", pid); |
| + fd = open(path_buf, O_RDONLY); |
| + if (fd == -1) |
| + return 1; |
| + |
| + /* CASE 1: exact MATCH at VADDR */ |
| + memset(&q, 0, sizeof(q)); |
| + q.size = sizeof(q); |
| + q.query_addr = VADDR; |
| + q.query_flags = 0; |
| + q.vma_name_addr = (__u64)(unsigned long)path_buf; |
| + q.vma_name_size = sizeof(path_buf); |
| + |
| + err = ioctl(fd, PROCMAP_QUERY, &q); |
| + assert(err == 0); |
| + |
| + assert(q.query_addr == VADDR); |
| + assert(q.query_flags == 0); |
| + |
| + assert(q.vma_flags == (PROCMAP_QUERY_VMA_READABLE | PROCMAP_QUERY_VMA_EXECUTABLE)); |
| + assert(q.vma_start == VADDR); |
| + assert(q.vma_end == VADDR + PAGE_SIZE); |
| + assert(q.vma_page_size == PAGE_SIZE); |
| + |
| + assert(q.vma_offset == 0); |
| + assert(q.inode == st.st_ino); |
| + assert(q.dev_major == MAJOR(st.st_dev)); |
| + assert(q.dev_minor == MINOR(st.st_dev)); |
| + |
| + snprintf(exp_path_buf, sizeof(exp_path_buf), |
| + "/tmp/#%llu (deleted)", (unsigned long long)st.st_ino); |
| + assert(q.vma_name_size == strlen(exp_path_buf) + 1); |
| + assert(strcmp(path_buf, exp_path_buf) == 0); |
| + |
| + /* CASE 2: NO MATCH at VADDR-1 */ |
| + memset(&q, 0, sizeof(q)); |
| + q.size = sizeof(q); |
| + q.query_addr = VADDR - 1; |
| + q.query_flags = 0; /* exact match */ |
| + |
| + err = ioctl(fd, PROCMAP_QUERY, &q); |
| + err = err < 0 ? -errno : 0; |
| + assert(err == -ENOENT); |
| + |
| + /* CASE 3: MATCH COVERING_OR_NEXT_VMA at VADDR - 1 */ |
| + memset(&q, 0, sizeof(q)); |
| + q.size = sizeof(q); |
| + q.query_addr = VADDR - 1; |
| + q.query_flags = PROCMAP_QUERY_COVERING_OR_NEXT_VMA; |
| + |
| + err = ioctl(fd, PROCMAP_QUERY, &q); |
| + assert(err == 0); |
| + |
| + assert(q.query_addr == VADDR - 1); |
| + assert(q.query_flags == PROCMAP_QUERY_COVERING_OR_NEXT_VMA); |
| + assert(q.vma_start == VADDR); |
| + assert(q.vma_end == VADDR + PAGE_SIZE); |
| + |
| + /* CASE 4: NO MATCH at VADDR + PAGE_SIZE */ |
| + memset(&q, 0, sizeof(q)); |
| + q.size = sizeof(q); |
| + q.query_addr = VADDR + PAGE_SIZE; /* point right after the VMA */ |
| + q.query_flags = PROCMAP_QUERY_COVERING_OR_NEXT_VMA; |
| + |
| + err = ioctl(fd, PROCMAP_QUERY, &q); |
| + err = err < 0 ? -errno : 0; |
| + assert(err == -ENOENT); |
| + |
| + /* CASE 5: NO MATCH WRITABLE at VADDR */ |
| + memset(&q, 0, sizeof(q)); |
| + q.size = sizeof(q); |
| + q.query_addr = VADDR; |
| + q.query_flags = PROCMAP_QUERY_VMA_WRITABLE; |
| + |
| + err = ioctl(fd, PROCMAP_QUERY, &q); |
| + err = err < 0 ? -errno : 0; |
| + assert(err == -ENOENT); |
| + } |
| + |
| return 0; |
| } |
| #else |
| _ |