linux/tools/testing/selftests/pidfd/pidfd_getfd_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 <limits.h>
   7#include <linux/types.h>
   8#include <sched.h>
   9#include <signal.h>
  10#include <stdio.h>
  11#include <stdlib.h>
  12#include <string.h>
  13#include <syscall.h>
  14#include <sys/prctl.h>
  15#include <sys/wait.h>
  16#include <unistd.h>
  17#include <sys/socket.h>
  18#include <linux/kcmp.h>
  19
  20#include "pidfd.h"
  21#include "../kselftest_harness.h"
  22
  23/*
  24 * UNKNOWN_FD is an fd number that should never exist in the child, as it is
  25 * used to check the negative case.
  26 */
  27#define UNKNOWN_FD 111
  28#define UID_NOBODY 65535
  29
  30static int sys_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1,
  31                    unsigned long idx2)
  32{
  33        return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
  34}
  35
  36static int __child(int sk, int memfd)
  37{
  38        int ret;
  39        char buf;
  40
  41        /*
  42         * Ensure we don't leave around a bunch of orphaned children if our
  43         * tests fail.
  44         */
  45        ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
  46        if (ret) {
  47                fprintf(stderr, "%s: Child could not set DEATHSIG\n",
  48                        strerror(errno));
  49                return -1;
  50        }
  51
  52        ret = send(sk, &memfd, sizeof(memfd), 0);
  53        if (ret != sizeof(memfd)) {
  54                fprintf(stderr, "%s: Child failed to send fd number\n",
  55                        strerror(errno));
  56                return -1;
  57        }
  58
  59        /*
  60         * The fixture setup is completed at this point. The tests will run.
  61         *
  62         * This blocking recv enables the parent to message the child.
  63         * Either we will read 'P' off of the sk, indicating that we need
  64         * to disable ptrace, or we will read a 0, indicating that the other
  65         * side has closed the sk. This occurs during fixture teardown time,
  66         * indicating that the child should exit.
  67         */
  68        while ((ret = recv(sk, &buf, sizeof(buf), 0)) > 0) {
  69                if (buf == 'P') {
  70                        ret = prctl(PR_SET_DUMPABLE, 0);
  71                        if (ret < 0) {
  72                                fprintf(stderr,
  73                                        "%s: Child failed to disable ptrace\n",
  74                                        strerror(errno));
  75                                return -1;
  76                        }
  77                } else {
  78                        fprintf(stderr, "Child received unknown command %c\n",
  79                                buf);
  80                        return -1;
  81                }
  82                ret = send(sk, &buf, sizeof(buf), 0);
  83                if (ret != 1) {
  84                        fprintf(stderr, "%s: Child failed to ack\n",
  85                                strerror(errno));
  86                        return -1;
  87                }
  88        }
  89        if (ret < 0) {
  90                fprintf(stderr, "%s: Child failed to read from socket\n",
  91                        strerror(errno));
  92                return -1;
  93        }
  94
  95        return 0;
  96}
  97
  98static int child(int sk)
  99{
 100        int memfd, ret;
 101
 102        memfd = sys_memfd_create("test", 0);
 103        if (memfd < 0) {
 104                fprintf(stderr, "%s: Child could not create memfd\n",
 105                        strerror(errno));
 106                ret = -1;
 107        } else {
 108                ret = __child(sk, memfd);
 109                close(memfd);
 110        }
 111
 112        close(sk);
 113        return ret;
 114}
 115
 116FIXTURE(child)
 117{
 118        /*
 119         * remote_fd is the number of the FD which we are trying to retrieve
 120         * from the child.
 121         */
 122        int remote_fd;
 123        /* pid points to the child which we are fetching FDs from */
 124        pid_t pid;
 125        /* pidfd is the pidfd of the child */
 126        int pidfd;
 127        /*
 128         * sk is our side of the socketpair used to communicate with the child.
 129         * When it is closed, the child will exit.
 130         */
 131        int sk;
 132};
 133
 134FIXTURE_SETUP(child)
 135{
 136        int ret, sk_pair[2];
 137
 138        ASSERT_EQ(0, socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sk_pair)) {
 139                TH_LOG("%s: failed to create socketpair", strerror(errno));
 140        }
 141        self->sk = sk_pair[0];
 142
 143        self->pid = fork();
 144        ASSERT_GE(self->pid, 0);
 145
 146        if (self->pid == 0) {
 147                close(sk_pair[0]);
 148                if (child(sk_pair[1]))
 149                        _exit(EXIT_FAILURE);
 150                _exit(EXIT_SUCCESS);
 151        }
 152
 153        close(sk_pair[1]);
 154
 155        self->pidfd = sys_pidfd_open(self->pid, 0);
 156        ASSERT_GE(self->pidfd, 0);
 157
 158        /*
 159         * Wait for the child to complete setup. It'll send the remote memfd's
 160         * number when ready.
 161         */
 162        ret = recv(sk_pair[0], &self->remote_fd, sizeof(self->remote_fd), 0);
 163        ASSERT_EQ(sizeof(self->remote_fd), ret);
 164}
 165
 166FIXTURE_TEARDOWN(child)
 167{
 168        EXPECT_EQ(0, close(self->pidfd));
 169        EXPECT_EQ(0, close(self->sk));
 170
 171        EXPECT_EQ(0, wait_for_pid(self->pid));
 172}
 173
 174TEST_F(child, disable_ptrace)
 175{
 176        int uid, fd;
 177        char c;
 178
 179        /*
 180         * Turn into nobody if we're root, to avoid CAP_SYS_PTRACE
 181         *
 182         * The tests should run in their own process, so even this test fails,
 183         * it shouldn't result in subsequent tests failing.
 184         */
 185        uid = getuid();
 186        if (uid == 0)
 187                ASSERT_EQ(0, seteuid(UID_NOBODY));
 188
 189        ASSERT_EQ(1, send(self->sk, "P", 1, 0));
 190        ASSERT_EQ(1, recv(self->sk, &c, 1, 0));
 191
 192        fd = sys_pidfd_getfd(self->pidfd, self->remote_fd, 0);
 193        EXPECT_EQ(-1, fd);
 194        EXPECT_EQ(EPERM, errno);
 195
 196        if (uid == 0)
 197                ASSERT_EQ(0, seteuid(0));
 198}
 199
 200TEST_F(child, fetch_fd)
 201{
 202        int fd, ret;
 203
 204        fd = sys_pidfd_getfd(self->pidfd, self->remote_fd, 0);
 205        ASSERT_GE(fd, 0);
 206
 207        ret = sys_kcmp(getpid(), self->pid, KCMP_FILE, fd, self->remote_fd);
 208        if (ret < 0 && errno == ENOSYS)
 209                SKIP(return, "kcmp() syscall not supported");
 210        EXPECT_EQ(ret, 0);
 211
 212        ret = fcntl(fd, F_GETFD);
 213        ASSERT_GE(ret, 0);
 214        EXPECT_GE(ret & FD_CLOEXEC, 0);
 215
 216        close(fd);
 217}
 218
 219TEST_F(child, test_unknown_fd)
 220{
 221        int fd;
 222
 223        fd = sys_pidfd_getfd(self->pidfd, UNKNOWN_FD, 0);
 224        EXPECT_EQ(-1, fd) {
 225                TH_LOG("getfd succeeded while fetching unknown fd");
 226        };
 227        EXPECT_EQ(EBADF, errno) {
 228                TH_LOG("%s: getfd did not get EBADF", strerror(errno));
 229        }
 230}
 231
 232TEST(flags_set)
 233{
 234        ASSERT_EQ(-1, sys_pidfd_getfd(0, 0, 1));
 235        EXPECT_EQ(errno, EINVAL);
 236}
 237
 238#if __NR_pidfd_getfd == -1
 239int main(void)
 240{
 241        fprintf(stderr, "__NR_pidfd_getfd undefined. The pidfd_getfd syscall is unavailable. Test aborting\n");
 242        return KSFT_SKIP;
 243}
 244#else
 245TEST_HARNESS_MAIN
 246#endif
 247