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