]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests/proc: add PROCMAP_QUERY ioctl tests
authorAndrii Nakryiko <andrii@kernel.org>
Thu, 27 Jun 2024 17:08:58 +0000 (10:08 -0700)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 12 Jul 2024 22:52:12 +0000 (15:52 -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
tools/testing/selftests/proc/proc-pid-vm.c

index 25c34cc9238e98fd12b4a929740c36622d679fca..4d57f2a875103bc0d00e7dded359c8020083d5c4 100644 (file)
@@ -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 :=
index cacbd2a4aec9120b06285a47688cf4b4decc6a2d..d04685771952a68b2ac304f83dccdeee3b8c4e6b 100644 (file)
@@ -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