0001
0002 #include <errno.h>
0003 #include <fcntl.h>
0004 #include <stdio.h>
0005 #include <string.h>
0006 #include <unistd.h>
0007 #include <sys/socket.h>
0008 #include <sys/stat.h>
0009 #include <sys/sysmacros.h>
0010 #include <sys/types.h>
0011
0012 #include "../kselftest_harness.h"
0013
0014
0015 void rm(struct __test_metadata *_metadata, const char *pathname,
0016 int is_dir)
0017 {
0018 int rc;
0019
0020 if (is_dir)
0021 rc = rmdir(pathname);
0022 else
0023 rc = unlink(pathname);
0024
0025 if (rc < 0) {
0026 ASSERT_EQ(errno, ENOENT) {
0027 TH_LOG("Not ENOENT: %s", pathname);
0028 }
0029 } else {
0030 ASSERT_EQ(rc, 0) {
0031 TH_LOG("Failed to remove: %s", pathname);
0032 }
0033 }
0034 }
0035
0036 FIXTURE(file) {
0037 char *pathname;
0038 int is_dir;
0039 };
0040
0041 FIXTURE_VARIANT(file)
0042 {
0043 const char *name;
0044 int expected;
0045 int is_dir;
0046 void (*setup)(struct __test_metadata *_metadata,
0047 FIXTURE_DATA(file) *self,
0048 const FIXTURE_VARIANT(file) *variant);
0049 int major, minor, mode;
0050 };
0051
0052 void setup_link(struct __test_metadata *_metadata,
0053 FIXTURE_DATA(file) *self,
0054 const FIXTURE_VARIANT(file) *variant)
0055 {
0056 const char * const paths[] = {
0057 "/bin/true",
0058 "/usr/bin/true",
0059 };
0060 int i;
0061
0062 for (i = 0; i < ARRAY_SIZE(paths); i++) {
0063 if (access(paths[i], X_OK) == 0) {
0064 ASSERT_EQ(symlink(paths[i], self->pathname), 0);
0065 return;
0066 }
0067 }
0068 ASSERT_EQ(1, 0) {
0069 TH_LOG("Could not find viable 'true' binary");
0070 }
0071 }
0072
0073 FIXTURE_VARIANT_ADD(file, S_IFLNK)
0074 {
0075 .name = "S_IFLNK",
0076 .expected = ELOOP,
0077 .setup = setup_link,
0078 };
0079
0080 void setup_dir(struct __test_metadata *_metadata,
0081 FIXTURE_DATA(file) *self,
0082 const FIXTURE_VARIANT(file) *variant)
0083 {
0084 ASSERT_EQ(mkdir(self->pathname, 0755), 0);
0085 }
0086
0087 FIXTURE_VARIANT_ADD(file, S_IFDIR)
0088 {
0089 .name = "S_IFDIR",
0090 .is_dir = 1,
0091 .expected = EACCES,
0092 .setup = setup_dir,
0093 };
0094
0095 void setup_node(struct __test_metadata *_metadata,
0096 FIXTURE_DATA(file) *self,
0097 const FIXTURE_VARIANT(file) *variant)
0098 {
0099 dev_t dev;
0100 int rc;
0101
0102 dev = makedev(variant->major, variant->minor);
0103 rc = mknod(self->pathname, 0755 | variant->mode, dev);
0104 ASSERT_EQ(rc, 0) {
0105 if (errno == EPERM)
0106 SKIP(return, "Please run as root; cannot mknod(%s)",
0107 variant->name);
0108 }
0109 }
0110
0111 FIXTURE_VARIANT_ADD(file, S_IFBLK)
0112 {
0113 .name = "S_IFBLK",
0114 .expected = EACCES,
0115 .setup = setup_node,
0116
0117 .major = 7,
0118 .minor = 0,
0119 .mode = S_IFBLK,
0120 };
0121
0122 FIXTURE_VARIANT_ADD(file, S_IFCHR)
0123 {
0124 .name = "S_IFCHR",
0125 .expected = EACCES,
0126 .setup = setup_node,
0127
0128 .major = 1,
0129 .minor = 5,
0130 .mode = S_IFCHR,
0131 };
0132
0133 void setup_fifo(struct __test_metadata *_metadata,
0134 FIXTURE_DATA(file) *self,
0135 const FIXTURE_VARIANT(file) *variant)
0136 {
0137 ASSERT_EQ(mkfifo(self->pathname, 0755), 0);
0138 }
0139
0140 FIXTURE_VARIANT_ADD(file, S_IFIFO)
0141 {
0142 .name = "S_IFIFO",
0143 .expected = EACCES,
0144 .setup = setup_fifo,
0145 };
0146
0147 FIXTURE_SETUP(file)
0148 {
0149 ASSERT_GT(asprintf(&self->pathname, "%s.test", variant->name), 6);
0150 self->is_dir = variant->is_dir;
0151
0152 rm(_metadata, self->pathname, variant->is_dir);
0153 variant->setup(_metadata, self, variant);
0154 }
0155
0156 FIXTURE_TEARDOWN(file)
0157 {
0158 rm(_metadata, self->pathname, self->is_dir);
0159 }
0160
0161 TEST_F(file, exec_errno)
0162 {
0163 char * const argv[2] = { (char * const)self->pathname, NULL };
0164
0165 EXPECT_LT(execv(argv[0], argv), 0);
0166 EXPECT_EQ(errno, variant->expected);
0167 }
0168
0169
0170 FIXTURE(sock)
0171 {
0172 int fd;
0173 };
0174
0175 FIXTURE_SETUP(sock)
0176 {
0177 self->fd = socket(AF_INET, SOCK_STREAM, 0);
0178 ASSERT_GE(self->fd, 0);
0179 }
0180
0181 FIXTURE_TEARDOWN(sock)
0182 {
0183 if (self->fd >= 0)
0184 ASSERT_EQ(close(self->fd), 0);
0185 }
0186
0187 TEST_F(sock, exec_errno)
0188 {
0189 char * const argv[2] = { " magic socket ", NULL };
0190 char * const envp[1] = { NULL };
0191
0192 EXPECT_LT(fexecve(self->fd, argv, envp), 0);
0193 EXPECT_EQ(errno, EACCES);
0194 }
0195
0196 TEST_HARNESS_MAIN