1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2022 FUJITSU LIMITED. All rights reserved. 4 * Author: Yang Xu <xuyang2018.jy@fujitsu.com> 5 */ 6 7/*\ 8 * [Description] 9 * 10 * Tests basic error handling of the pidfd_open syscall. 11 * 12 * - EBADF pidfd is not a valid PID file descriptor 13 * - EBADF targetfd is not an open file descriptor in the process referred 14 * to by pidfd 15 * - EINVAL flags is not 0 16 * - ESRCH the process referred to by pidfd does not exist (it has terminated 17 * and been waited on) 18 * - EPERM the calling process doesn't have PTRACE_MODE_ATTACH_REALCREDS permissions 19 * over the process referred to by pidfd 20 */ 21 22#include <stdlib.h> 23#include <pwd.h> 24#include "tst_test.h" 25#include "tst_safe_macros.h" 26#include "lapi/pidfd.h" 27 28static int valid_pidfd = -1, invalid_pidfd = -1, pidfd = -1; 29static uid_t uid; 30 31static struct tcase { 32 char *name; 33 int *pidfd; 34 int targetfd; 35 int flags; 36 int exp_errno; 37} tcases[] = { 38 {"invalid pidfd", &invalid_pidfd, 0, 0, EBADF}, 39 {"invalid targetfd", &valid_pidfd, -1, 0, EBADF}, 40 {"invalid flags", &valid_pidfd, 0, 1, EINVAL}, 41 {"the process referred to by pidfd doesn't exist", NULL, 0, 0, ESRCH}, 42 {"lack of required permission", &valid_pidfd, 0, 0, EPERM}, 43}; 44 45static void setup(void) 46{ 47 pidfd_open_supported(); 48 pidfd_getfd_supported(); 49 50 struct passwd *pw; 51 52 pw = SAFE_GETPWNAM("nobody"); 53 uid = pw->pw_uid; 54 55 valid_pidfd = SAFE_PIDFD_OPEN(getpid(), 0); 56} 57 58static void cleanup(void) 59{ 60 if (valid_pidfd > -1) 61 SAFE_CLOSE(valid_pidfd); 62 if (pidfd > -1) 63 SAFE_CLOSE(pidfd); 64} 65 66static void run(unsigned int n) 67{ 68 struct tcase *tc = &tcases[n]; 69 int pid; 70 71 if (tc->exp_errno == EPERM) { 72 pid = SAFE_FORK(); 73 if (!pid) { 74 SAFE_SETUID(uid); 75 TST_EXP_FAIL2(pidfd_getfd(valid_pidfd, tc->targetfd, tc->flags), 76 tc->exp_errno, "pidfd_getfd(%d, %d, %d) with %s", 77 valid_pidfd, tc->targetfd, tc->flags, tc->name); 78 TST_CHECKPOINT_WAKE(0); 79 exit(0); 80 } 81 TST_CHECKPOINT_WAIT(0); 82 SAFE_WAIT(NULL); 83 return; 84 } else if (tc->exp_errno == ESRCH) { 85 pid = SAFE_FORK(); 86 if (!pid) { 87 TST_CHECKPOINT_WAIT(0); 88 exit(0); 89 } 90 pidfd = SAFE_PIDFD_OPEN(pid, 0); 91 TST_CHECKPOINT_WAKE(0); 92 SAFE_WAIT(NULL); 93 TST_EXP_FAIL2(pidfd_getfd(pidfd, tc->targetfd, tc->flags), 94 tc->exp_errno, "pidfd_getfd(%d, %d, %d) with %s", 95 pidfd, tc->targetfd, tc->flags, tc->name); 96 SAFE_CLOSE(pidfd); 97 } else { 98 TST_EXP_FAIL2(pidfd_getfd(*tc->pidfd, tc->targetfd, tc->flags), 99 tc->exp_errno, "pidfd_getfd(%d, %d, %d) with %s", 100 *tc->pidfd, tc->targetfd, tc->flags, tc->name); 101 } 102} 103 104static struct tst_test test = { 105 .tcnt = ARRAY_SIZE(tcases), 106 .test = run, 107 .setup = setup, 108 .cleanup = cleanup, 109 .needs_root = 1, 110 .forks_child = 1, 111 .needs_checkpoints = 1, 112}; 113