• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) Linux Test Project, 2014-2020
4  *
5  * errno tests for setns(2) - reassociate thread with a namespace
6  */
7 #define _GNU_SOURCE
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <errno.h>
11 #include <sched.h>
12 #include <pwd.h>
13 #include <string.h>
14 #include "config.h"
15 #include "tst_test.h"
16 #include "lapi/syscalls.h"
17 #include "setns.h"
18 
19 static const char nobody_uid[] = "nobody";
20 static struct passwd *ltpuser;
21 static int regular_fd;
22 
23 struct testcase_t {
24 	const char *msg;
25 	int fd;
26 	int ns_type;
27 	int exp_ret;
28 	int exp_errno;
29 	int skip;
30 	void (*setup) (struct testcase_t *, int i);
31 	void (*cleanup) (struct testcase_t *);
32 };
33 
setup0(struct testcase_t * t,int i)34 static void setup0(struct testcase_t *t, int i)
35 {
36 	t->ns_type = ns_types[i];
37 }
38 
setup1(struct testcase_t * t,int i)39 static void setup1(struct testcase_t *t, int i)
40 {
41 	t->ns_type = ns_types[i];
42 	t->fd = regular_fd;
43 }
44 
setup2(struct testcase_t * t,int i)45 static void setup2(struct testcase_t *t, int i)
46 {
47 	t->fd = ns_fds[i];
48 }
49 
setup3(struct testcase_t * t,int i)50 static void setup3(struct testcase_t *t, int i)
51 {
52 	if (ns_total < 2) {
53 		t->skip = 1;
54 		return;
55 	}
56 
57 	t->fd = ns_fds[i];
58 	t->ns_type = ns_types[(i+1) % ns_total];
59 }
60 
setup4(struct testcase_t * t,int i)61 static void setup4(struct testcase_t *t, int i)
62 {
63 	SAFE_SETEUID(ltpuser->pw_uid);
64 
65 	t->fd = ns_fds[i];
66 	t->ns_type = ns_types[i];
67 }
68 
cleanup4(LTP_ATTRIBUTE_UNUSED struct testcase_t * t)69 static void cleanup4(LTP_ATTRIBUTE_UNUSED struct testcase_t *t)
70 {
71 	SAFE_SETEUID(0);
72 }
73 
74 static struct testcase_t tcases[] = {
75 	{
76 		.msg = "invalid fd",
77 		.fd = -1,
78 		.exp_ret = -1,
79 		.exp_errno = EBADF,
80 		.setup = setup0,
81 	},
82 	{
83 		.msg = "regular file fd",
84 		.exp_ret = -1,
85 		.exp_errno = EINVAL,
86 		.setup = setup1,
87 	},
88 	{
89 		.msg = "invalid ns_type",
90 		.ns_type = -1,
91 		.exp_ret = -1,
92 		.exp_errno = EINVAL,
93 		.setup = setup2,
94 	},
95 	{
96 		.msg = "mismatch ns_type/fd",
97 		.exp_ret = -1,
98 		.exp_errno = EINVAL,
99 		.setup = setup3,
100 	},
101 	{
102 		.msg = "without CAP_SYS_ADMIN",
103 		.exp_ret = -1,
104 		.exp_errno = EPERM,
105 		.setup = setup4,
106 		.cleanup = cleanup4,
107 	}
108 };
109 
test_setns(unsigned int testno)110 static void test_setns(unsigned int testno)
111 {
112 	int ret, i;
113 	struct testcase_t *t = &tcases[testno];
114 
115 	for (i = 0; i < ns_total; i++) {
116 		if (t->setup)
117 			t->setup(t, i);
118 
119 		if (t->skip) {
120 			tst_res(TCONF, "skip %s", t->msg);
121 			continue;
122 		}
123 
124 		tst_res(TINFO, "setns(%d, 0x%x)", t->fd, t->ns_type);
125 		ret = tst_syscall(__NR_setns, t->fd, t->ns_type);
126 		if (ret == t->exp_ret) {
127 			if (ret == -1 && errno == t->exp_errno) {
128 				tst_res(TPASS, "%s exp_errno=%d (%s)",
129 					t->msg,	t->exp_errno,
130 					tst_strerrno(t->exp_errno));
131 			} else {
132 				tst_res(TFAIL|TERRNO, "%s exp_errno=%d (%s)",
133 					t->msg, t->exp_errno,
134 					tst_strerrno(t->exp_errno));
135 			}
136 		} else {
137 			tst_res(TFAIL, "%s ret=%d expected=%d",
138 				t->msg,	ret, t->exp_ret);
139 		}
140 
141 		if (t->cleanup)
142 			t->cleanup(t);
143 	}
144 }
145 
setup(void)146 static void setup(void)
147 {
148 	/* runtime check if syscall is supported */
149 	tst_syscall(__NR_setns, -1, 0);
150 
151 	init_available_ns();
152 	if (ns_total == 0)
153 		tst_brk(TCONF, "no ns types/proc entries");
154 
155 	ltpuser = SAFE_GETPWNAM(nobody_uid);
156 	regular_fd = SAFE_OPEN("dummy", O_RDWR|O_CREAT, 0600);
157 	SAFE_UNLINK("dummy");
158 }
159 
cleanup(void)160 static void cleanup(void)
161 {
162 	close_ns_fds();
163 	if (regular_fd)
164 		SAFE_CLOSE(regular_fd);
165 }
166 
167 static struct tst_test test = {
168 	.tcnt = ARRAY_SIZE(tcases),
169 	.test = test_setns,
170 	.setup = setup,
171 	.cleanup = cleanup,
172 	.needs_root = 1,
173 	.needs_tmpdir = 1,
174 };
175 
176