xref: /openbmc/linux/tools/testing/selftests/exec/non-regular.c (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
1*0f71241aSKees Cook // SPDX-License-Identifier: GPL-2.0+
2*0f71241aSKees Cook #include <errno.h>
3*0f71241aSKees Cook #include <fcntl.h>
4*0f71241aSKees Cook #include <stdio.h>
5*0f71241aSKees Cook #include <string.h>
6*0f71241aSKees Cook #include <unistd.h>
7*0f71241aSKees Cook #include <sys/socket.h>
8*0f71241aSKees Cook #include <sys/stat.h>
9*0f71241aSKees Cook #include <sys/sysmacros.h>
10*0f71241aSKees Cook #include <sys/types.h>
11*0f71241aSKees Cook 
12*0f71241aSKees Cook #include "../kselftest_harness.h"
13*0f71241aSKees Cook 
14*0f71241aSKees Cook /* Remove a file, ignoring the result if it didn't exist. */
rm(struct __test_metadata * _metadata,const char * pathname,int is_dir)15*0f71241aSKees Cook void rm(struct __test_metadata *_metadata, const char *pathname,
16*0f71241aSKees Cook 	int is_dir)
17*0f71241aSKees Cook {
18*0f71241aSKees Cook 	int rc;
19*0f71241aSKees Cook 
20*0f71241aSKees Cook 	if (is_dir)
21*0f71241aSKees Cook 		rc = rmdir(pathname);
22*0f71241aSKees Cook 	else
23*0f71241aSKees Cook 		rc = unlink(pathname);
24*0f71241aSKees Cook 
25*0f71241aSKees Cook 	if (rc < 0) {
26*0f71241aSKees Cook 		ASSERT_EQ(errno, ENOENT) {
27*0f71241aSKees Cook 			TH_LOG("Not ENOENT: %s", pathname);
28*0f71241aSKees Cook 		}
29*0f71241aSKees Cook 	} else {
30*0f71241aSKees Cook 		ASSERT_EQ(rc, 0) {
31*0f71241aSKees Cook 			TH_LOG("Failed to remove: %s", pathname);
32*0f71241aSKees Cook 		}
33*0f71241aSKees Cook 	}
34*0f71241aSKees Cook }
35*0f71241aSKees Cook 
FIXTURE(file)36*0f71241aSKees Cook FIXTURE(file) {
37*0f71241aSKees Cook 	char *pathname;
38*0f71241aSKees Cook 	int is_dir;
39*0f71241aSKees Cook };
40*0f71241aSKees Cook 
FIXTURE_VARIANT(file)41*0f71241aSKees Cook FIXTURE_VARIANT(file)
42*0f71241aSKees Cook {
43*0f71241aSKees Cook 	const char *name;
44*0f71241aSKees Cook 	int expected;
45*0f71241aSKees Cook 	int is_dir;
46*0f71241aSKees Cook 	void (*setup)(struct __test_metadata *_metadata,
47*0f71241aSKees Cook 		      FIXTURE_DATA(file) *self,
48*0f71241aSKees Cook 		      const FIXTURE_VARIANT(file) *variant);
49*0f71241aSKees Cook 	int major, minor, mode; /* for mknod() */
50*0f71241aSKees Cook };
51*0f71241aSKees Cook 
setup_link(struct __test_metadata * _metadata,FIXTURE_DATA (file)* self,const FIXTURE_VARIANT (file)* variant)52*0f71241aSKees Cook void setup_link(struct __test_metadata *_metadata,
53*0f71241aSKees Cook 		FIXTURE_DATA(file) *self,
54*0f71241aSKees Cook 		const FIXTURE_VARIANT(file) *variant)
55*0f71241aSKees Cook {
56*0f71241aSKees Cook 	const char * const paths[] = {
57*0f71241aSKees Cook 		"/bin/true",
58*0f71241aSKees Cook 		"/usr/bin/true",
59*0f71241aSKees Cook 	};
60*0f71241aSKees Cook 	int i;
61*0f71241aSKees Cook 
62*0f71241aSKees Cook 	for (i = 0; i < ARRAY_SIZE(paths); i++) {
63*0f71241aSKees Cook 		if (access(paths[i], X_OK) == 0) {
64*0f71241aSKees Cook 			ASSERT_EQ(symlink(paths[i], self->pathname), 0);
65*0f71241aSKees Cook 			return;
66*0f71241aSKees Cook 		}
67*0f71241aSKees Cook 	}
68*0f71241aSKees Cook 	ASSERT_EQ(1, 0) {
69*0f71241aSKees Cook 		TH_LOG("Could not find viable 'true' binary");
70*0f71241aSKees Cook 	}
71*0f71241aSKees Cook }
72*0f71241aSKees Cook 
FIXTURE_VARIANT_ADD(file,S_IFLNK)73*0f71241aSKees Cook FIXTURE_VARIANT_ADD(file, S_IFLNK)
74*0f71241aSKees Cook {
75*0f71241aSKees Cook 	.name = "S_IFLNK",
76*0f71241aSKees Cook 	.expected = ELOOP,
77*0f71241aSKees Cook 	.setup = setup_link,
78*0f71241aSKees Cook };
79*0f71241aSKees Cook 
setup_dir(struct __test_metadata * _metadata,FIXTURE_DATA (file)* self,const FIXTURE_VARIANT (file)* variant)80*0f71241aSKees Cook void setup_dir(struct __test_metadata *_metadata,
81*0f71241aSKees Cook 	       FIXTURE_DATA(file) *self,
82*0f71241aSKees Cook 	       const FIXTURE_VARIANT(file) *variant)
83*0f71241aSKees Cook {
84*0f71241aSKees Cook 	ASSERT_EQ(mkdir(self->pathname, 0755), 0);
85*0f71241aSKees Cook }
86*0f71241aSKees Cook 
FIXTURE_VARIANT_ADD(file,S_IFDIR)87*0f71241aSKees Cook FIXTURE_VARIANT_ADD(file, S_IFDIR)
88*0f71241aSKees Cook {
89*0f71241aSKees Cook 	.name = "S_IFDIR",
90*0f71241aSKees Cook 	.is_dir = 1,
91*0f71241aSKees Cook 	.expected = EACCES,
92*0f71241aSKees Cook 	.setup = setup_dir,
93*0f71241aSKees Cook };
94*0f71241aSKees Cook 
setup_node(struct __test_metadata * _metadata,FIXTURE_DATA (file)* self,const FIXTURE_VARIANT (file)* variant)95*0f71241aSKees Cook void setup_node(struct __test_metadata *_metadata,
96*0f71241aSKees Cook 		FIXTURE_DATA(file) *self,
97*0f71241aSKees Cook 		const FIXTURE_VARIANT(file) *variant)
98*0f71241aSKees Cook {
99*0f71241aSKees Cook 	dev_t dev;
100*0f71241aSKees Cook 	int rc;
101*0f71241aSKees Cook 
102*0f71241aSKees Cook 	dev = makedev(variant->major, variant->minor);
103*0f71241aSKees Cook 	rc = mknod(self->pathname, 0755 | variant->mode, dev);
104*0f71241aSKees Cook 	ASSERT_EQ(rc, 0) {
105*0f71241aSKees Cook 		if (errno == EPERM)
106*0f71241aSKees Cook 			SKIP(return, "Please run as root; cannot mknod(%s)",
107*0f71241aSKees Cook 				variant->name);
108*0f71241aSKees Cook 	}
109*0f71241aSKees Cook }
110*0f71241aSKees Cook 
FIXTURE_VARIANT_ADD(file,S_IFBLK)111*0f71241aSKees Cook FIXTURE_VARIANT_ADD(file, S_IFBLK)
112*0f71241aSKees Cook {
113*0f71241aSKees Cook 	.name = "S_IFBLK",
114*0f71241aSKees Cook 	.expected = EACCES,
115*0f71241aSKees Cook 	.setup = setup_node,
116*0f71241aSKees Cook 	/* /dev/loop0 */
117*0f71241aSKees Cook 	.major = 7,
118*0f71241aSKees Cook 	.minor = 0,
119*0f71241aSKees Cook 	.mode = S_IFBLK,
120*0f71241aSKees Cook };
121*0f71241aSKees Cook 
FIXTURE_VARIANT_ADD(file,S_IFCHR)122*0f71241aSKees Cook FIXTURE_VARIANT_ADD(file, S_IFCHR)
123*0f71241aSKees Cook {
124*0f71241aSKees Cook 	.name = "S_IFCHR",
125*0f71241aSKees Cook 	.expected = EACCES,
126*0f71241aSKees Cook 	.setup = setup_node,
127*0f71241aSKees Cook 	/* /dev/zero */
128*0f71241aSKees Cook 	.major = 1,
129*0f71241aSKees Cook 	.minor = 5,
130*0f71241aSKees Cook 	.mode = S_IFCHR,
131*0f71241aSKees Cook };
132*0f71241aSKees Cook 
setup_fifo(struct __test_metadata * _metadata,FIXTURE_DATA (file)* self,const FIXTURE_VARIANT (file)* variant)133*0f71241aSKees Cook void setup_fifo(struct __test_metadata *_metadata,
134*0f71241aSKees Cook 		FIXTURE_DATA(file) *self,
135*0f71241aSKees Cook 		const FIXTURE_VARIANT(file) *variant)
136*0f71241aSKees Cook {
137*0f71241aSKees Cook 	ASSERT_EQ(mkfifo(self->pathname, 0755), 0);
138*0f71241aSKees Cook }
139*0f71241aSKees Cook 
FIXTURE_VARIANT_ADD(file,S_IFIFO)140*0f71241aSKees Cook FIXTURE_VARIANT_ADD(file, S_IFIFO)
141*0f71241aSKees Cook {
142*0f71241aSKees Cook 	.name = "S_IFIFO",
143*0f71241aSKees Cook 	.expected = EACCES,
144*0f71241aSKees Cook 	.setup = setup_fifo,
145*0f71241aSKees Cook };
146*0f71241aSKees Cook 
FIXTURE_SETUP(file)147*0f71241aSKees Cook FIXTURE_SETUP(file)
148*0f71241aSKees Cook {
149*0f71241aSKees Cook 	ASSERT_GT(asprintf(&self->pathname, "%s.test", variant->name), 6);
150*0f71241aSKees Cook 	self->is_dir = variant->is_dir;
151*0f71241aSKees Cook 
152*0f71241aSKees Cook 	rm(_metadata, self->pathname, variant->is_dir);
153*0f71241aSKees Cook 	variant->setup(_metadata, self, variant);
154*0f71241aSKees Cook }
155*0f71241aSKees Cook 
FIXTURE_TEARDOWN(file)156*0f71241aSKees Cook FIXTURE_TEARDOWN(file)
157*0f71241aSKees Cook {
158*0f71241aSKees Cook 	rm(_metadata, self->pathname, self->is_dir);
159*0f71241aSKees Cook }
160*0f71241aSKees Cook 
TEST_F(file,exec_errno)161*0f71241aSKees Cook TEST_F(file, exec_errno)
162*0f71241aSKees Cook {
163*0f71241aSKees Cook 	char * const argv[2] = { (char * const)self->pathname, NULL };
164*0f71241aSKees Cook 
165*0f71241aSKees Cook 	EXPECT_LT(execv(argv[0], argv), 0);
166*0f71241aSKees Cook 	EXPECT_EQ(errno, variant->expected);
167*0f71241aSKees Cook }
168*0f71241aSKees Cook 
169*0f71241aSKees Cook /* S_IFSOCK */
FIXTURE(sock)170*0f71241aSKees Cook FIXTURE(sock)
171*0f71241aSKees Cook {
172*0f71241aSKees Cook 	int fd;
173*0f71241aSKees Cook };
174*0f71241aSKees Cook 
FIXTURE_SETUP(sock)175*0f71241aSKees Cook FIXTURE_SETUP(sock)
176*0f71241aSKees Cook {
177*0f71241aSKees Cook 	self->fd = socket(AF_INET, SOCK_STREAM, 0);
178*0f71241aSKees Cook 	ASSERT_GE(self->fd, 0);
179*0f71241aSKees Cook }
180*0f71241aSKees Cook 
FIXTURE_TEARDOWN(sock)181*0f71241aSKees Cook FIXTURE_TEARDOWN(sock)
182*0f71241aSKees Cook {
183*0f71241aSKees Cook 	if (self->fd >= 0)
184*0f71241aSKees Cook 		ASSERT_EQ(close(self->fd), 0);
185*0f71241aSKees Cook }
186*0f71241aSKees Cook 
TEST_F(sock,exec_errno)187*0f71241aSKees Cook TEST_F(sock, exec_errno)
188*0f71241aSKees Cook {
189*0f71241aSKees Cook 	char * const argv[2] = { " magic socket ", NULL };
190*0f71241aSKees Cook 	char * const envp[1] = { NULL };
191*0f71241aSKees Cook 
192*0f71241aSKees Cook 	EXPECT_LT(fexecve(self->fd, argv, envp), 0);
193*0f71241aSKees Cook 	EXPECT_EQ(errno, EACCES);
194*0f71241aSKees Cook }
195*0f71241aSKees Cook 
196*0f71241aSKees Cook TEST_HARNESS_MAIN
197