Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tests: add close_range() tests

This adds basic tests for the new close_range() syscall.
- test that no invalid flags can be passed
- test that a range of file descriptors is correctly closed
- test that a range of file descriptors is correctly closed if there there
are already closed file descriptors in the range
- test that max_fd is correctly capped to the current fdtable maximum

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jann Horn <jannh@google.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Dmitry V. Levin <ldv@altlinux.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: linux-api@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org

+99
+1
tools/testing/selftests/Makefile
··· 6 6 TARGETS += capabilities 7 7 TARGETS += cgroup 8 8 TARGETS += clone3 9 + TARGETS += core 9 10 TARGETS += cpufreq 10 11 TARGETS += cpu-hotplug 11 12 TARGETS += drivers/dma-buf
+1
tools/testing/selftests/core/.gitignore
··· 1 + close_range_test
+7
tools/testing/selftests/core/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + CFLAGS += -g -I../../../../usr/include/ 3 + 4 + TEST_GEN_PROGS := close_range_test 5 + 6 + include ../lib.mk 7 +
+90
tools/testing/selftests/core/close_range_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #define _GNU_SOURCE 4 + #include <errno.h> 5 + #include <fcntl.h> 6 + #include <linux/kernel.h> 7 + #include <limits.h> 8 + #include <stdbool.h> 9 + #include <stdio.h> 10 + #include <stdlib.h> 11 + #include <string.h> 12 + #include <syscall.h> 13 + #include <unistd.h> 14 + 15 + #include "../kselftest_harness.h" 16 + 17 + #ifndef __NR_close_range 18 + #define __NR_close_range -1 19 + #endif 20 + 21 + static inline int sys_close_range(unsigned int fd, unsigned int max_fd, 22 + unsigned int flags) 23 + { 24 + return syscall(__NR_close_range, fd, max_fd, flags); 25 + } 26 + 27 + #ifndef ARRAY_SIZE 28 + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 29 + #endif 30 + 31 + TEST(close_range) 32 + { 33 + int i, ret; 34 + int open_fds[101]; 35 + 36 + for (i = 0; i < ARRAY_SIZE(open_fds); i++) { 37 + int fd; 38 + 39 + fd = open("/dev/null", O_RDONLY | O_CLOEXEC); 40 + ASSERT_GE(fd, 0) { 41 + if (errno == ENOENT) 42 + XFAIL(return, "Skipping test since /dev/null does not exist"); 43 + } 44 + 45 + open_fds[i] = fd; 46 + } 47 + 48 + EXPECT_EQ(-1, sys_close_range(open_fds[0], open_fds[100], -1)) { 49 + if (errno == ENOSYS) 50 + XFAIL(return, "close_range() syscall not supported"); 51 + } 52 + 53 + EXPECT_EQ(0, sys_close_range(open_fds[0], open_fds[50], 0)); 54 + 55 + for (i = 0; i <= 50; i++) 56 + EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL)); 57 + 58 + for (i = 51; i <= 100; i++) 59 + EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1); 60 + 61 + /* create a couple of gaps */ 62 + close(57); 63 + close(78); 64 + close(81); 65 + close(82); 66 + close(84); 67 + close(90); 68 + 69 + EXPECT_EQ(0, sys_close_range(open_fds[51], open_fds[92], 0)); 70 + 71 + for (i = 51; i <= 92; i++) 72 + EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL)); 73 + 74 + for (i = 93; i <= 100; i++) 75 + EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1); 76 + 77 + /* test that the kernel caps and still closes all fds */ 78 + EXPECT_EQ(0, sys_close_range(open_fds[93], open_fds[99], 0)); 79 + 80 + for (i = 93; i <= 99; i++) 81 + EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL)); 82 + 83 + EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1); 84 + 85 + EXPECT_EQ(0, sys_close_range(open_fds[100], open_fds[100], 0)); 86 + 87 + EXPECT_EQ(-1, fcntl(open_fds[100], F_GETFL)); 88 + } 89 + 90 + TEST_HARNESS_MAIN