Loading...
Note: File does not exist in v4.10.11.
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
20TEST(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
94TEST_HARNESS_MAIN