• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2021 SUSE LLC
4  */
5 /*\
6  * [Description]
7  *
8  * - First check close_range works on a valid range.
9  * - Then check close_range does not accept invalid paramters.
10  * - Then check it accepts a large lower fd.
11  * - Finally check CLOEXEC works
12  *
13  */
14 
15 #include <stdlib.h>
16 
17 #include "tst_test.h"
18 #include "tst_clone.h"
19 #include "lapi/fcntl.h"
20 #include "lapi/close_range.h"
21 #include "lapi/clone.h"
22 
try_close_range(int fd,int flags)23 static int try_close_range(int fd, int flags)
24 {
25 	int res;
26 
27 	TEST(close_range(fd, fd, flags));
28 
29 	if (TST_RET == -1 && TST_ERR == EINVAL)
30 		res = TCONF;
31 	else if (TST_RET == -1)
32 		res = TFAIL;
33 	else
34 		res = TPASS;
35 
36 	return res;
37 }
38 
run(unsigned int n)39 static void run(unsigned int n)
40 {
41 	const struct tst_clone_args args = {
42 		.flags = CLONE_FILES,
43 		.exit_signal = SIGCHLD,
44 	};
45 	int fd = -1, res;
46 
47 	switch (n) {
48 	case 0:
49 		fd = SAFE_OPEN("/", O_PATH);
50 		SAFE_DUP2(fd, 100);
51 
52 		TST_EXP_PASS(close_range(fd, 100, 0),
53 			     "close_range(%d, 100, 0)", fd);
54 		TST_EXP_FAIL(fcntl(fd, F_GETFD), EBADF,
55 			     "fcntl(%d, F_GETFD)", fd);
56 		TST_EXP_FAIL(fcntl(100, F_GETFD), EBADF);
57 		break;
58 	case 1:
59 		TST_EXP_FAIL(close_range(4, 3, 0), EINVAL);
60 		break;
61 	case 2:
62 		TST_EXP_FAIL(close_range(3, ~0U, ~0U), EINVAL);
63 		break;
64 	case 3:
65 		TST_EXP_PASS(close_range(~0U, ~0U, 0));
66 		break;
67 	case 4:
68 		fd = SAFE_OPEN("/", O_PATH);
69 
70 		res = try_close_range(fd, CLOSE_RANGE_CLOEXEC);
71 		tst_res(res | TTERRNO,
72 			"close_range(%d, %d, CLOSE_RANGE_CLOEXEC)", fd, fd);
73 
74 		if (res != TPASS)
75 			break;
76 
77 		TST_EXP_FD_SILENT(fcntl(fd, F_GETFD), "fcntl(%d, F_GETFD)", fd);
78 		if (TST_RET & FD_CLOEXEC)
79 			tst_res(TPASS, "FD_CLOEXEC was set on %d", fd);
80 		else
81 			tst_res(TFAIL, "FD_CLOEXEC not set on %d", fd);
82 		break;
83 	case 5:
84 		fd = SAFE_OPEN("/", O_PATH);
85 
86 		if (!SAFE_CLONE(&args)) {
87 			res = try_close_range(fd, CLOSE_RANGE_UNSHARE);
88 			tst_res(res | TTERRNO,
89 				"close_range(%d, %d, CLOSE_RANGE_UNSHARE)",
90 				fd, fd);
91 
92 			if (res != TPASS)
93 				exit(0);
94 
95 			TST_EXP_FAIL(fcntl(fd, F_GETFD), EBADF,
96 				     "fcntl(%d, F_GETFD)", fd);
97 			exit(0);
98 		}
99 
100 		tst_reap_children();
101 
102 		TST_EXP_PASS(fcntl(fd, F_GETFD), "%d is open", fd);
103 	}
104 
105 	if (fd > -1)
106 		TST_EXP_PASS_SILENT(close_range(fd, fd, 0),
107 				    "close_range(%d, %d, 0)", fd, fd);
108 }
109 
110 static struct tst_test test = {
111 	.tcnt = 6,
112 	.forks_child = 1,
113 	.test = run,
114 };
115