1 /* Specific tests for Linux pidfd_getpid.
2 Copyright (C) 2023-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
22 #include <support/check.h>
23 #include <support/xunistd.h>
24 #include <support/test-driver.h>
25 #include <sys/pidfd.h>
27 #include <sys/mount.h>
33 /* The pidfd_getfd syscall was the last in the set of pidfd related
34 syscalls added to the kernel. Use pidfd_getfd to decide if this
35 kernel has pidfd support that we can test. */
36 int r
= pidfd_getfd (0, 0, 1);
37 TEST_VERIFY_EXIT (r
== -1);
39 FAIL_UNSUPPORTED ("kernel does not support pidfd_getfd, skipping test");
41 FAIL_UNSUPPORTED ("kernel does not allow pidfd_getfd, skipping test");
44 /* Check if pidfd_getpid returns EREMOTE for process not in current
47 pid_t child0
= xfork ();
48 TEST_VERIFY_EXIT (child0
>= 0);
51 /* Create another unrelated descriptor, so child2 will inherit the
53 pid_t child1
= xfork ();
54 TEST_VERIFY_EXIT (child1
>= 0);
57 int child1_pidfd
= pidfd_open (child1
, 0);
58 TEST_VERIFY_EXIT (child1_pidfd
!= -1);
60 if (unshare (CLONE_NEWNS
| CLONE_NEWUSER
| CLONE_NEWPID
) < 0)
62 /* Older kernels may not support all the options, or security
63 policy may block this call. */
64 if (errno
== EINVAL
|| errno
== EPERM
|| errno
== ENOSPC
)
65 exit (EXIT_UNSUPPORTED
);
66 FAIL_EXIT1 ("unshare user/fs/pid failed: %m");
69 if (mount (NULL
, "/", NULL
, MS_REC
| MS_PRIVATE
, 0) != 0)
71 /* This happens if we're trying to create a nested container,
72 like if the build is running under podman, and we lack
75 _exit (EXIT_UNSUPPORTED
);
80 pid_t child2
= xfork ();
84 xwaitpid (child2
, &status
, 0);
85 TEST_VERIFY (WIFEXITED (status
));
86 xwaitpid (child1
, &status
, 0);
87 TEST_VERIFY (WIFEXITED (status
));
89 _exit (WEXITSTATUS (status
));
92 /* Now that we're pid 1 (effectively "root") we can mount /proc */
93 if (mount ("proc", "/proc", "proc", 0, NULL
) != 0)
96 _exit (EXIT_UNSUPPORTED
);
101 TEST_COMPARE (pidfd_getpid (child1_pidfd
), -1);
102 TEST_COMPARE (errno
, EREMOTE
);
104 _exit (EXIT_SUCCESS
);
106 int child0_pidfd
= pidfd_open (child0
, 0);
107 TEST_VERIFY_EXIT (child0_pidfd
!= -1);
109 pid_t child0pid
= pidfd_getpid (child0_pidfd
);
112 TEST_COMPARE (waitid (P_PIDFD
, child0_pidfd
, &info
, WEXITED
), 0);
113 if (info
.si_status
== EXIT_UNSUPPORTED
)
114 FAIL_UNSUPPORTED ("unable to unshare user/fs/pid");
115 TEST_COMPARE (info
.si_status
, 0);
116 TEST_COMPARE (info
.si_code
, CLD_EXITED
);
117 TEST_COMPARE (info
.si_pid
, child0pid
);
123 #include <support/test-driver.c>