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