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 #include <sys/resource.h> 15 #include <linux/close_range.h> 16 17 #include "../kselftest_harness.h" 18 #include "../clone3/clone3_selftests.h" 19 20 TEST(unshare_EMFILE) 21 { 22 pid_t pid; 23 int status; 24 struct __clone_args args = { 25 .flags = CLONE_FILES, 26 .exit_signal = SIGCHLD, 27 }; 28 int fd; 29 ssize_t n, n2; 30 static char buf[512], buf2[512]; 31 struct rlimit rlimit; 32 int nr_open; 33 34 fd = open("/proc/sys/fs/nr_open", O_RDWR); 35 ASSERT_GE(fd, 0); 36 37 n = read(fd, buf, sizeof(buf)); 38 ASSERT_GT(n, 0); 39 ASSERT_EQ(buf[n - 1], '\n'); 40 41 ASSERT_EQ(sscanf(buf, "%d", &nr_open), 1); 42 43 ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &rlimit)); 44 45 /* bump fs.nr_open */ 46 n2 = sprintf(buf2, "%d\n", nr_open + 1024); 47 lseek(fd, 0, SEEK_SET); 48 write(fd, buf2, n2); 49 50 /* bump ulimit -n */ 51 rlimit.rlim_cur = nr_open + 1024; 52 rlimit.rlim_max = nr_open + 1024; 53 EXPECT_EQ(0, setrlimit(RLIMIT_NOFILE, &rlimit)) { 54 lseek(fd, 0, SEEK_SET); 55 write(fd, buf, n); 56 exit(EXIT_FAILURE); 57 } 58 59 /* get a descriptor past the old fs.nr_open */ 60 EXPECT_GE(dup2(2, nr_open + 64), 0) { 61 lseek(fd, 0, SEEK_SET); 62 write(fd, buf, n); 63 exit(EXIT_FAILURE); 64 } 65 66 /* get descriptor table shared */ 67 pid = sys_clone3(&args, sizeof(args)); 68 EXPECT_GE(pid, 0) { 69 lseek(fd, 0, SEEK_SET); 70 write(fd, buf, n); 71 exit(EXIT_FAILURE); 72 } 73 74 if (pid == 0) { 75 int err; 76 77 /* restore fs.nr_open */ 78 lseek(fd, 0, SEEK_SET); 79 write(fd, buf, n); 80 /* ... and now unshare(CLONE_FILES) must fail with EMFILE */ 81 err = unshare(CLONE_FILES); 82 EXPECT_EQ(err, -1) 83 exit(EXIT_FAILURE); 84 EXPECT_EQ(errno, EMFILE) 85 exit(EXIT_FAILURE); 86 exit(EXIT_SUCCESS); 87 } 88 89 EXPECT_EQ(waitpid(pid, &status, 0), pid); 90 EXPECT_EQ(true, WIFEXITED(status)); 91 EXPECT_EQ(0, WEXITSTATUS(status)); 92 } 93 94 TEST_HARNESS_MAIN 95