linux/tools/testing/selftests/core/close_range_test.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#define _GNU_SOURCE
   4#include <errno.h>
   5#include <fcntl.h>
   6#include <linux/kernel.h>
   7#include <limits.h>
   8#include <stdbool.h>
   9#include <stdio.h>
  10#include <stdlib.h>
  11#include <string.h>
  12#include <syscall.h>
  13#include <unistd.h>
  14
  15#include "../kselftest_harness.h"
  16#include "../clone3/clone3_selftests.h"
  17
  18#ifndef __NR_close_range
  19#define __NR_close_range -1
  20#endif
  21
  22#ifndef CLOSE_RANGE_UNSHARE
  23#define CLOSE_RANGE_UNSHARE     (1U << 1)
  24#endif
  25
  26static inline int sys_close_range(unsigned int fd, unsigned int max_fd,
  27                                  unsigned int flags)
  28{
  29        return syscall(__NR_close_range, fd, max_fd, flags);
  30}
  31
  32#ifndef ARRAY_SIZE
  33#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
  34#endif
  35
  36TEST(close_range)
  37{
  38        int i, ret;
  39        int open_fds[101];
  40
  41        for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
  42                int fd;
  43
  44                fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
  45                ASSERT_GE(fd, 0) {
  46                        if (errno == ENOENT)
  47                                XFAIL(return, "Skipping test since /dev/null does not exist");
  48                }
  49
  50                open_fds[i] = fd;
  51        }
  52
  53        EXPECT_EQ(-1, sys_close_range(open_fds[0], open_fds[100], -1)) {
  54                if (errno == ENOSYS)
  55                        XFAIL(return, "close_range() syscall not supported");
  56        }
  57
  58        EXPECT_EQ(0, sys_close_range(open_fds[0], open_fds[50], 0));
  59
  60        for (i = 0; i <= 50; i++)
  61                EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
  62
  63        for (i = 51; i <= 100; i++)
  64                EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
  65
  66        /* create a couple of gaps */
  67        close(57);
  68        close(78);
  69        close(81);
  70        close(82);
  71        close(84);
  72        close(90);
  73
  74        EXPECT_EQ(0, sys_close_range(open_fds[51], open_fds[92], 0));
  75
  76        for (i = 51; i <= 92; i++)
  77                EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
  78
  79        for (i = 93; i <= 100; i++)
  80                EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
  81
  82        /* test that the kernel caps and still closes all fds */
  83        EXPECT_EQ(0, sys_close_range(open_fds[93], open_fds[99], 0));
  84
  85        for (i = 93; i <= 99; i++)
  86                EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
  87
  88        EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
  89
  90        EXPECT_EQ(0, sys_close_range(open_fds[100], open_fds[100], 0));
  91
  92        EXPECT_EQ(-1, fcntl(open_fds[100], F_GETFL));
  93}
  94
  95TEST(close_range_unshare)
  96{
  97        int i, ret, status;
  98        pid_t pid;
  99        int open_fds[101];
 100        struct clone_args args = {
 101                .flags = CLONE_FILES,
 102                .exit_signal = SIGCHLD,
 103        };
 104
 105        for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
 106                int fd;
 107
 108                fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
 109                ASSERT_GE(fd, 0) {
 110                        if (errno == ENOENT)
 111                                XFAIL(return, "Skipping test since /dev/null does not exist");
 112                }
 113
 114                open_fds[i] = fd;
 115        }
 116
 117        pid = sys_clone3(&args, sizeof(args));
 118        ASSERT_GE(pid, 0);
 119
 120        if (pid == 0) {
 121                ret = sys_close_range(open_fds[0], open_fds[50],
 122                                      CLOSE_RANGE_UNSHARE);
 123                if (ret)
 124                        exit(EXIT_FAILURE);
 125
 126                for (i = 0; i <= 50; i++)
 127                        if (fcntl(open_fds[i], F_GETFL) != -1)
 128                                exit(EXIT_FAILURE);
 129
 130                for (i = 51; i <= 100; i++)
 131                        if (fcntl(open_fds[i], F_GETFL) == -1)
 132                                exit(EXIT_FAILURE);
 133
 134                /* create a couple of gaps */
 135                close(57);
 136                close(78);
 137                close(81);
 138                close(82);
 139                close(84);
 140                close(90);
 141
 142                ret = sys_close_range(open_fds[51], open_fds[92],
 143                                      CLOSE_RANGE_UNSHARE);
 144                if (ret)
 145                        exit(EXIT_FAILURE);
 146
 147                for (i = 51; i <= 92; i++)
 148                        if (fcntl(open_fds[i], F_GETFL) != -1)
 149                                exit(EXIT_FAILURE);
 150
 151                for (i = 93; i <= 100; i++)
 152                        if (fcntl(open_fds[i], F_GETFL) == -1)
 153                                exit(EXIT_FAILURE);
 154
 155                /* test that the kernel caps and still closes all fds */
 156                ret = sys_close_range(open_fds[93], open_fds[99],
 157                                      CLOSE_RANGE_UNSHARE);
 158                if (ret)
 159                        exit(EXIT_FAILURE);
 160
 161                for (i = 93; i <= 99; i++)
 162                        if (fcntl(open_fds[i], F_GETFL) != -1)
 163                                exit(EXIT_FAILURE);
 164
 165                if (fcntl(open_fds[100], F_GETFL) == -1)
 166                        exit(EXIT_FAILURE);
 167
 168                ret = sys_close_range(open_fds[100], open_fds[100],
 169                                      CLOSE_RANGE_UNSHARE);
 170                if (ret)
 171                        exit(EXIT_FAILURE);
 172
 173                if (fcntl(open_fds[100], F_GETFL) != -1)
 174                        exit(EXIT_FAILURE);
 175
 176                exit(EXIT_SUCCESS);
 177        }
 178
 179        EXPECT_EQ(waitpid(pid, &status, 0), pid);
 180        EXPECT_EQ(true, WIFEXITED(status));
 181        EXPECT_EQ(0, WEXITSTATUS(status));
 182}
 183
 184TEST(close_range_unshare_capped)
 185{
 186        int i, ret, status;
 187        pid_t pid;
 188        int open_fds[101];
 189        struct clone_args args = {
 190                .flags = CLONE_FILES,
 191                .exit_signal = SIGCHLD,
 192        };
 193
 194        for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
 195                int fd;
 196
 197                fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
 198                ASSERT_GE(fd, 0) {
 199                        if (errno == ENOENT)
 200                                XFAIL(return, "Skipping test since /dev/null does not exist");
 201                }
 202
 203                open_fds[i] = fd;
 204        }
 205
 206        pid = sys_clone3(&args, sizeof(args));
 207        ASSERT_GE(pid, 0);
 208
 209        if (pid == 0) {
 210                ret = sys_close_range(open_fds[0], UINT_MAX,
 211                                      CLOSE_RANGE_UNSHARE);
 212                if (ret)
 213                        exit(EXIT_FAILURE);
 214
 215                for (i = 0; i <= 100; i++)
 216                        if (fcntl(open_fds[i], F_GETFL) != -1)
 217                                exit(EXIT_FAILURE);
 218
 219                exit(EXIT_SUCCESS);
 220        }
 221
 222        EXPECT_EQ(waitpid(pid, &status, 0), pid);
 223        EXPECT_EQ(true, WIFEXITED(status));
 224        EXPECT_EQ(0, WEXITSTATUS(status));
 225}
 226
 227TEST_HARNESS_MAIN
 228