xref: /linux/tools/testing/selftests/core/unshare_test.c (revision 2fe3c78a2c26dd5ee811024a1b7d6cfb4d654319)
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