Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 #define _GNU_SOURCE
0004 #include <errno.h>
0005 #include <fcntl.h>
0006 #include <linux/kernel.h>
0007 #include <limits.h>
0008 #include <stdbool.h>
0009 #include <stdio.h>
0010 #include <stdlib.h>
0011 #include <string.h>
0012 #include <syscall.h>
0013 #include <unistd.h>
0014 #include <sys/resource.h>
0015 
0016 #include "../kselftest_harness.h"
0017 #include "../clone3/clone3_selftests.h"
0018 
0019 #ifndef __NR_close_range
0020     #if defined __alpha__
0021         #define __NR_close_range 546
0022     #elif defined _MIPS_SIM
0023         #if _MIPS_SIM == _MIPS_SIM_ABI32    /* o32 */
0024             #define __NR_close_range (436 + 4000)
0025         #endif
0026         #if _MIPS_SIM == _MIPS_SIM_NABI32   /* n32 */
0027             #define __NR_close_range (436 + 6000)
0028         #endif
0029         #if _MIPS_SIM == _MIPS_SIM_ABI64    /* n64 */
0030             #define __NR_close_range (436 + 5000)
0031         #endif
0032     #elif defined __ia64__
0033         #define __NR_close_range (436 + 1024)
0034     #else
0035         #define __NR_close_range 436
0036     #endif
0037 #endif
0038 
0039 #ifndef CLOSE_RANGE_UNSHARE
0040 #define CLOSE_RANGE_UNSHARE (1U << 1)
0041 #endif
0042 
0043 #ifndef CLOSE_RANGE_CLOEXEC
0044 #define CLOSE_RANGE_CLOEXEC (1U << 2)
0045 #endif
0046 
0047 static inline int sys_close_range(unsigned int fd, unsigned int max_fd,
0048                   unsigned int flags)
0049 {
0050     return syscall(__NR_close_range, fd, max_fd, flags);
0051 }
0052 
0053 TEST(core_close_range)
0054 {
0055     int i, ret;
0056     int open_fds[101];
0057 
0058     for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
0059         int fd;
0060 
0061         fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
0062         ASSERT_GE(fd, 0) {
0063             if (errno == ENOENT)
0064                 SKIP(return, "Skipping test since /dev/null does not exist");
0065         }
0066 
0067         open_fds[i] = fd;
0068     }
0069 
0070     EXPECT_EQ(-1, sys_close_range(open_fds[0], open_fds[100], -1)) {
0071         if (errno == ENOSYS)
0072             SKIP(return, "close_range() syscall not supported");
0073     }
0074 
0075     EXPECT_EQ(0, sys_close_range(open_fds[0], open_fds[50], 0));
0076 
0077     for (i = 0; i <= 50; i++)
0078         EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
0079 
0080     for (i = 51; i <= 100; i++)
0081         EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
0082 
0083     /* create a couple of gaps */
0084     close(57);
0085     close(78);
0086     close(81);
0087     close(82);
0088     close(84);
0089     close(90);
0090 
0091     EXPECT_EQ(0, sys_close_range(open_fds[51], open_fds[92], 0));
0092 
0093     for (i = 51; i <= 92; i++)
0094         EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
0095 
0096     for (i = 93; i <= 100; i++)
0097         EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
0098 
0099     /* test that the kernel caps and still closes all fds */
0100     EXPECT_EQ(0, sys_close_range(open_fds[93], open_fds[99], 0));
0101 
0102     for (i = 93; i <= 99; i++)
0103         EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
0104 
0105     EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
0106 
0107     EXPECT_EQ(0, sys_close_range(open_fds[100], open_fds[100], 0));
0108 
0109     EXPECT_EQ(-1, fcntl(open_fds[100], F_GETFL));
0110 }
0111 
0112 TEST(close_range_unshare)
0113 {
0114     int i, ret, status;
0115     pid_t pid;
0116     int open_fds[101];
0117     struct __clone_args args = {
0118         .flags = CLONE_FILES,
0119         .exit_signal = SIGCHLD,
0120     };
0121 
0122     for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
0123         int fd;
0124 
0125         fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
0126         ASSERT_GE(fd, 0) {
0127             if (errno == ENOENT)
0128                 SKIP(return, "Skipping test since /dev/null does not exist");
0129         }
0130 
0131         open_fds[i] = fd;
0132     }
0133 
0134     pid = sys_clone3(&args, sizeof(args));
0135     ASSERT_GE(pid, 0);
0136 
0137     if (pid == 0) {
0138         ret = sys_close_range(open_fds[0], open_fds[50],
0139                       CLOSE_RANGE_UNSHARE);
0140         if (ret)
0141             exit(EXIT_FAILURE);
0142 
0143         for (i = 0; i <= 50; i++)
0144             if (fcntl(open_fds[i], F_GETFL) != -1)
0145                 exit(EXIT_FAILURE);
0146 
0147         for (i = 51; i <= 100; i++)
0148             if (fcntl(open_fds[i], F_GETFL) == -1)
0149                 exit(EXIT_FAILURE);
0150 
0151         /* create a couple of gaps */
0152         close(57);
0153         close(78);
0154         close(81);
0155         close(82);
0156         close(84);
0157         close(90);
0158 
0159         ret = sys_close_range(open_fds[51], open_fds[92],
0160                       CLOSE_RANGE_UNSHARE);
0161         if (ret)
0162             exit(EXIT_FAILURE);
0163 
0164         for (i = 51; i <= 92; i++)
0165             if (fcntl(open_fds[i], F_GETFL) != -1)
0166                 exit(EXIT_FAILURE);
0167 
0168         for (i = 93; i <= 100; i++)
0169             if (fcntl(open_fds[i], F_GETFL) == -1)
0170                 exit(EXIT_FAILURE);
0171 
0172         /* test that the kernel caps and still closes all fds */
0173         ret = sys_close_range(open_fds[93], open_fds[99],
0174                       CLOSE_RANGE_UNSHARE);
0175         if (ret)
0176             exit(EXIT_FAILURE);
0177 
0178         for (i = 93; i <= 99; i++)
0179             if (fcntl(open_fds[i], F_GETFL) != -1)
0180                 exit(EXIT_FAILURE);
0181 
0182         if (fcntl(open_fds[100], F_GETFL) == -1)
0183             exit(EXIT_FAILURE);
0184 
0185         ret = sys_close_range(open_fds[100], open_fds[100],
0186                       CLOSE_RANGE_UNSHARE);
0187         if (ret)
0188             exit(EXIT_FAILURE);
0189 
0190         if (fcntl(open_fds[100], F_GETFL) != -1)
0191             exit(EXIT_FAILURE);
0192 
0193         exit(EXIT_SUCCESS);
0194     }
0195 
0196     EXPECT_EQ(waitpid(pid, &status, 0), pid);
0197     EXPECT_EQ(true, WIFEXITED(status));
0198     EXPECT_EQ(0, WEXITSTATUS(status));
0199 }
0200 
0201 TEST(close_range_unshare_capped)
0202 {
0203     int i, ret, status;
0204     pid_t pid;
0205     int open_fds[101];
0206     struct __clone_args args = {
0207         .flags = CLONE_FILES,
0208         .exit_signal = SIGCHLD,
0209     };
0210 
0211     for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
0212         int fd;
0213 
0214         fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
0215         ASSERT_GE(fd, 0) {
0216             if (errno == ENOENT)
0217                 SKIP(return, "Skipping test since /dev/null does not exist");
0218         }
0219 
0220         open_fds[i] = fd;
0221     }
0222 
0223     pid = sys_clone3(&args, sizeof(args));
0224     ASSERT_GE(pid, 0);
0225 
0226     if (pid == 0) {
0227         ret = sys_close_range(open_fds[0], UINT_MAX,
0228                       CLOSE_RANGE_UNSHARE);
0229         if (ret)
0230             exit(EXIT_FAILURE);
0231 
0232         for (i = 0; i <= 100; i++)
0233             if (fcntl(open_fds[i], F_GETFL) != -1)
0234                 exit(EXIT_FAILURE);
0235 
0236         exit(EXIT_SUCCESS);
0237     }
0238 
0239     EXPECT_EQ(waitpid(pid, &status, 0), pid);
0240     EXPECT_EQ(true, WIFEXITED(status));
0241     EXPECT_EQ(0, WEXITSTATUS(status));
0242 }
0243 
0244 TEST(close_range_cloexec)
0245 {
0246     int i, ret;
0247     int open_fds[101];
0248     struct rlimit rlimit;
0249 
0250     for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
0251         int fd;
0252 
0253         fd = open("/dev/null", O_RDONLY);
0254         ASSERT_GE(fd, 0) {
0255             if (errno == ENOENT)
0256                 SKIP(return, "Skipping test since /dev/null does not exist");
0257         }
0258 
0259         open_fds[i] = fd;
0260     }
0261 
0262     ret = sys_close_range(1000, 1000, CLOSE_RANGE_CLOEXEC);
0263     if (ret < 0) {
0264         if (errno == ENOSYS)
0265             SKIP(return, "close_range() syscall not supported");
0266         if (errno == EINVAL)
0267             SKIP(return, "close_range() doesn't support CLOSE_RANGE_CLOEXEC");
0268     }
0269 
0270     /* Ensure the FD_CLOEXEC bit is set also with a resource limit in place.  */
0271     ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &rlimit));
0272     rlimit.rlim_cur = 25;
0273     ASSERT_EQ(0, setrlimit(RLIMIT_NOFILE, &rlimit));
0274 
0275     /* Set close-on-exec for two ranges: [0-50] and [75-100].  */
0276     ret = sys_close_range(open_fds[0], open_fds[50], CLOSE_RANGE_CLOEXEC);
0277     ASSERT_EQ(0, ret);
0278     ret = sys_close_range(open_fds[75], open_fds[100], CLOSE_RANGE_CLOEXEC);
0279     ASSERT_EQ(0, ret);
0280 
0281     for (i = 0; i <= 50; i++) {
0282         int flags = fcntl(open_fds[i], F_GETFD);
0283 
0284         EXPECT_GT(flags, -1);
0285         EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0286     }
0287 
0288     for (i = 51; i <= 74; i++) {
0289         int flags = fcntl(open_fds[i], F_GETFD);
0290 
0291         EXPECT_GT(flags, -1);
0292         EXPECT_EQ(flags & FD_CLOEXEC, 0);
0293     }
0294 
0295     for (i = 75; i <= 100; i++) {
0296         int flags = fcntl(open_fds[i], F_GETFD);
0297 
0298         EXPECT_GT(flags, -1);
0299         EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0300     }
0301 
0302     /* Test a common pattern.  */
0303     ret = sys_close_range(3, UINT_MAX, CLOSE_RANGE_CLOEXEC);
0304     for (i = 0; i <= 100; i++) {
0305         int flags = fcntl(open_fds[i], F_GETFD);
0306 
0307         EXPECT_GT(flags, -1);
0308         EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0309     }
0310 }
0311 
0312 TEST(close_range_cloexec_unshare)
0313 {
0314     int i, ret;
0315     int open_fds[101];
0316     struct rlimit rlimit;
0317 
0318     for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
0319         int fd;
0320 
0321         fd = open("/dev/null", O_RDONLY);
0322         ASSERT_GE(fd, 0) {
0323             if (errno == ENOENT)
0324                 SKIP(return, "Skipping test since /dev/null does not exist");
0325         }
0326 
0327         open_fds[i] = fd;
0328     }
0329 
0330     ret = sys_close_range(1000, 1000, CLOSE_RANGE_CLOEXEC);
0331     if (ret < 0) {
0332         if (errno == ENOSYS)
0333             SKIP(return, "close_range() syscall not supported");
0334         if (errno == EINVAL)
0335             SKIP(return, "close_range() doesn't support CLOSE_RANGE_CLOEXEC");
0336     }
0337 
0338     /* Ensure the FD_CLOEXEC bit is set also with a resource limit in place.  */
0339     ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &rlimit));
0340     rlimit.rlim_cur = 25;
0341     ASSERT_EQ(0, setrlimit(RLIMIT_NOFILE, &rlimit));
0342 
0343     /* Set close-on-exec for two ranges: [0-50] and [75-100].  */
0344     ret = sys_close_range(open_fds[0], open_fds[50],
0345                   CLOSE_RANGE_CLOEXEC | CLOSE_RANGE_UNSHARE);
0346     ASSERT_EQ(0, ret);
0347     ret = sys_close_range(open_fds[75], open_fds[100],
0348                   CLOSE_RANGE_CLOEXEC | CLOSE_RANGE_UNSHARE);
0349     ASSERT_EQ(0, ret);
0350 
0351     for (i = 0; i <= 50; i++) {
0352         int flags = fcntl(open_fds[i], F_GETFD);
0353 
0354         EXPECT_GT(flags, -1);
0355         EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0356     }
0357 
0358     for (i = 51; i <= 74; i++) {
0359         int flags = fcntl(open_fds[i], F_GETFD);
0360 
0361         EXPECT_GT(flags, -1);
0362         EXPECT_EQ(flags & FD_CLOEXEC, 0);
0363     }
0364 
0365     for (i = 75; i <= 100; i++) {
0366         int flags = fcntl(open_fds[i], F_GETFD);
0367 
0368         EXPECT_GT(flags, -1);
0369         EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0370     }
0371 
0372     /* Test a common pattern.  */
0373     ret = sys_close_range(3, UINT_MAX,
0374                   CLOSE_RANGE_CLOEXEC | CLOSE_RANGE_UNSHARE);
0375     for (i = 0; i <= 100; i++) {
0376         int flags = fcntl(open_fds[i], F_GETFD);
0377 
0378         EXPECT_GT(flags, -1);
0379         EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0380     }
0381 }
0382 
0383 /*
0384  * Regression test for syzbot+96cfd2b22b3213646a93@syzkaller.appspotmail.com
0385  */
0386 TEST(close_range_cloexec_syzbot)
0387 {
0388     int fd1, fd2, fd3, flags, ret, status;
0389     pid_t pid;
0390     struct __clone_args args = {
0391         .flags = CLONE_FILES,
0392         .exit_signal = SIGCHLD,
0393     };
0394 
0395     /* Create a huge gap in the fd table. */
0396     fd1 = open("/dev/null", O_RDWR);
0397     EXPECT_GT(fd1, 0);
0398 
0399     fd2 = dup2(fd1, 1000);
0400     EXPECT_GT(fd2, 0);
0401 
0402     pid = sys_clone3(&args, sizeof(args));
0403     ASSERT_GE(pid, 0);
0404 
0405     if (pid == 0) {
0406         ret = sys_close_range(3, ~0U, CLOSE_RANGE_CLOEXEC);
0407         if (ret)
0408             exit(EXIT_FAILURE);
0409 
0410         /*
0411              * We now have a private file descriptor table and all
0412              * our open fds should still be open but made
0413              * close-on-exec.
0414              */
0415         flags = fcntl(fd1, F_GETFD);
0416         EXPECT_GT(flags, -1);
0417         EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0418 
0419         flags = fcntl(fd2, F_GETFD);
0420         EXPECT_GT(flags, -1);
0421         EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0422 
0423         fd3 = dup2(fd1, 42);
0424         EXPECT_GT(fd3, 0);
0425 
0426         /*
0427              * Duplicating the file descriptor must remove the
0428              * FD_CLOEXEC flag.
0429              */
0430         flags = fcntl(fd3, F_GETFD);
0431         EXPECT_GT(flags, -1);
0432         EXPECT_EQ(flags & FD_CLOEXEC, 0);
0433 
0434         exit(EXIT_SUCCESS);
0435     }
0436 
0437     EXPECT_EQ(waitpid(pid, &status, 0), pid);
0438     EXPECT_EQ(true, WIFEXITED(status));
0439     EXPECT_EQ(0, WEXITSTATUS(status));
0440 
0441     /*
0442      * We had a shared file descriptor table before along with requesting
0443      * close-on-exec so the original fds must not be close-on-exec.
0444      */
0445     flags = fcntl(fd1, F_GETFD);
0446     EXPECT_GT(flags, -1);
0447     EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0448 
0449     flags = fcntl(fd2, F_GETFD);
0450     EXPECT_GT(flags, -1);
0451     EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0452 
0453     fd3 = dup2(fd1, 42);
0454     EXPECT_GT(fd3, 0);
0455 
0456     flags = fcntl(fd3, F_GETFD);
0457     EXPECT_GT(flags, -1);
0458     EXPECT_EQ(flags & FD_CLOEXEC, 0);
0459 
0460     EXPECT_EQ(close(fd1), 0);
0461     EXPECT_EQ(close(fd2), 0);
0462     EXPECT_EQ(close(fd3), 0);
0463 }
0464 
0465 /*
0466  * Regression test for syzbot+96cfd2b22b3213646a93@syzkaller.appspotmail.com
0467  */
0468 TEST(close_range_cloexec_unshare_syzbot)
0469 {
0470     int i, fd1, fd2, fd3, flags, ret, status;
0471     pid_t pid;
0472     struct __clone_args args = {
0473         .flags = CLONE_FILES,
0474         .exit_signal = SIGCHLD,
0475     };
0476 
0477     /*
0478      * Create a huge gap in the fd table. When we now call
0479      * CLOSE_RANGE_UNSHARE with a shared fd table and and with ~0U as upper
0480      * bound the kernel will only copy up to fd1 file descriptors into the
0481      * new fd table. If the kernel is buggy and doesn't handle
0482      * CLOSE_RANGE_CLOEXEC correctly it will not have copied all file
0483      * descriptors and we will oops!
0484      *
0485      * On a buggy kernel this should immediately oops. But let's loop just
0486      * to be sure.
0487      */
0488     fd1 = open("/dev/null", O_RDWR);
0489     EXPECT_GT(fd1, 0);
0490 
0491     fd2 = dup2(fd1, 1000);
0492     EXPECT_GT(fd2, 0);
0493 
0494     for (i = 0; i < 100; i++) {
0495 
0496         pid = sys_clone3(&args, sizeof(args));
0497         ASSERT_GE(pid, 0);
0498 
0499         if (pid == 0) {
0500             ret = sys_close_range(3, ~0U, CLOSE_RANGE_UNSHARE |
0501                               CLOSE_RANGE_CLOEXEC);
0502             if (ret)
0503                 exit(EXIT_FAILURE);
0504 
0505             /*
0506              * We now have a private file descriptor table and all
0507              * our open fds should still be open but made
0508              * close-on-exec.
0509              */
0510             flags = fcntl(fd1, F_GETFD);
0511             EXPECT_GT(flags, -1);
0512             EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0513 
0514             flags = fcntl(fd2, F_GETFD);
0515             EXPECT_GT(flags, -1);
0516             EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
0517 
0518             fd3 = dup2(fd1, 42);
0519             EXPECT_GT(fd3, 0);
0520 
0521             /*
0522              * Duplicating the file descriptor must remove the
0523              * FD_CLOEXEC flag.
0524              */
0525             flags = fcntl(fd3, F_GETFD);
0526             EXPECT_GT(flags, -1);
0527             EXPECT_EQ(flags & FD_CLOEXEC, 0);
0528 
0529             EXPECT_EQ(close(fd1), 0);
0530             EXPECT_EQ(close(fd2), 0);
0531             EXPECT_EQ(close(fd3), 0);
0532 
0533             exit(EXIT_SUCCESS);
0534         }
0535 
0536         EXPECT_EQ(waitpid(pid, &status, 0), pid);
0537         EXPECT_EQ(true, WIFEXITED(status));
0538         EXPECT_EQ(0, WEXITSTATUS(status));
0539     }
0540 
0541     /*
0542      * We created a private file descriptor table before along with
0543      * requesting close-on-exec so the original fds must not be
0544      * close-on-exec.
0545      */
0546     flags = fcntl(fd1, F_GETFD);
0547     EXPECT_GT(flags, -1);
0548     EXPECT_EQ(flags & FD_CLOEXEC, 0);
0549 
0550     flags = fcntl(fd2, F_GETFD);
0551     EXPECT_GT(flags, -1);
0552     EXPECT_EQ(flags & FD_CLOEXEC, 0);
0553 
0554     fd3 = dup2(fd1, 42);
0555     EXPECT_GT(fd3, 0);
0556 
0557     flags = fcntl(fd3, F_GETFD);
0558     EXPECT_GT(flags, -1);
0559     EXPECT_EQ(flags & FD_CLOEXEC, 0);
0560 
0561     EXPECT_EQ(close(fd1), 0);
0562     EXPECT_EQ(close(fd2), 0);
0563     EXPECT_EQ(close(fd3), 0);
0564 }
0565 
0566 TEST_HARNESS_MAIN