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