18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci/* 48c2ecf20Sopenharmony_ci * Based on Christian Brauner's clone3() example. 58c2ecf20Sopenharmony_ci * These tests are assuming to be running in the host's 68c2ecf20Sopenharmony_ci * PID namespace. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#define _GNU_SOURCE 108c2ecf20Sopenharmony_ci#include <errno.h> 118c2ecf20Sopenharmony_ci#include <linux/types.h> 128c2ecf20Sopenharmony_ci#include <linux/sched.h> 138c2ecf20Sopenharmony_ci#include <stdio.h> 148c2ecf20Sopenharmony_ci#include <stdlib.h> 158c2ecf20Sopenharmony_ci#include <stdbool.h> 168c2ecf20Sopenharmony_ci#include <sys/syscall.h> 178c2ecf20Sopenharmony_ci#include <sys/types.h> 188c2ecf20Sopenharmony_ci#include <sys/un.h> 198c2ecf20Sopenharmony_ci#include <sys/wait.h> 208c2ecf20Sopenharmony_ci#include <unistd.h> 218c2ecf20Sopenharmony_ci#include <sched.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include "../kselftest.h" 248c2ecf20Sopenharmony_ci#include "clone3_selftests.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#ifndef MAX_PID_NS_LEVEL 278c2ecf20Sopenharmony_ci#define MAX_PID_NS_LEVEL 32 288c2ecf20Sopenharmony_ci#endif 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic int pipe_1[2]; 318c2ecf20Sopenharmony_cistatic int pipe_2[2]; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic void child_exit(int ret) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci fflush(stdout); 368c2ecf20Sopenharmony_ci fflush(stderr); 378c2ecf20Sopenharmony_ci _exit(ret); 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic int call_clone3_set_tid(pid_t *set_tid, 418c2ecf20Sopenharmony_ci size_t set_tid_size, 428c2ecf20Sopenharmony_ci int flags, 438c2ecf20Sopenharmony_ci int expected_pid, 448c2ecf20Sopenharmony_ci bool wait_for_it) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci int status; 478c2ecf20Sopenharmony_ci pid_t pid = -1; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci struct __clone_args args = { 508c2ecf20Sopenharmony_ci .flags = flags, 518c2ecf20Sopenharmony_ci .exit_signal = SIGCHLD, 528c2ecf20Sopenharmony_ci .set_tid = ptr_to_u64(set_tid), 538c2ecf20Sopenharmony_ci .set_tid_size = set_tid_size, 548c2ecf20Sopenharmony_ci }; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci pid = sys_clone3(&args, sizeof(args)); 578c2ecf20Sopenharmony_ci if (pid < 0) { 588c2ecf20Sopenharmony_ci ksft_print_msg("%s - Failed to create new process\n", 598c2ecf20Sopenharmony_ci strerror(errno)); 608c2ecf20Sopenharmony_ci return -errno; 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (pid == 0) { 648c2ecf20Sopenharmony_ci int ret; 658c2ecf20Sopenharmony_ci char tmp = 0; 668c2ecf20Sopenharmony_ci int exit_code = EXIT_SUCCESS; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci ksft_print_msg("I am the child, my PID is %d (expected %d)\n", 698c2ecf20Sopenharmony_ci getpid(), set_tid[0]); 708c2ecf20Sopenharmony_ci if (wait_for_it) { 718c2ecf20Sopenharmony_ci ksft_print_msg("[%d] Child is ready and waiting\n", 728c2ecf20Sopenharmony_ci getpid()); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci /* Signal the parent that the child is ready */ 758c2ecf20Sopenharmony_ci close(pipe_1[0]); 768c2ecf20Sopenharmony_ci ret = write(pipe_1[1], &tmp, 1); 778c2ecf20Sopenharmony_ci if (ret != 1) { 788c2ecf20Sopenharmony_ci ksft_print_msg( 798c2ecf20Sopenharmony_ci "Writing to pipe returned %d", ret); 808c2ecf20Sopenharmony_ci exit_code = EXIT_FAILURE; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci close(pipe_1[1]); 838c2ecf20Sopenharmony_ci close(pipe_2[1]); 848c2ecf20Sopenharmony_ci ret = read(pipe_2[0], &tmp, 1); 858c2ecf20Sopenharmony_ci if (ret != 1) { 868c2ecf20Sopenharmony_ci ksft_print_msg( 878c2ecf20Sopenharmony_ci "Reading from pipe returned %d", ret); 888c2ecf20Sopenharmony_ci exit_code = EXIT_FAILURE; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci close(pipe_2[0]); 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (set_tid[0] != getpid()) 948c2ecf20Sopenharmony_ci child_exit(EXIT_FAILURE); 958c2ecf20Sopenharmony_ci child_exit(exit_code); 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (expected_pid == 0 || expected_pid == pid) { 998c2ecf20Sopenharmony_ci ksft_print_msg("I am the parent (%d). My child's pid is %d\n", 1008c2ecf20Sopenharmony_ci getpid(), pid); 1018c2ecf20Sopenharmony_ci } else { 1028c2ecf20Sopenharmony_ci ksft_print_msg( 1038c2ecf20Sopenharmony_ci "Expected child pid %d does not match actual pid %d\n", 1048c2ecf20Sopenharmony_ci expected_pid, pid); 1058c2ecf20Sopenharmony_ci return -1; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci if (waitpid(pid, &status, 0) < 0) { 1098c2ecf20Sopenharmony_ci ksft_print_msg("Child returned %s\n", strerror(errno)); 1108c2ecf20Sopenharmony_ci return -errno; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci if (!WIFEXITED(status)) 1148c2ecf20Sopenharmony_ci return -1; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci return WEXITSTATUS(status); 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic void test_clone3_set_tid(pid_t *set_tid, 1208c2ecf20Sopenharmony_ci size_t set_tid_size, 1218c2ecf20Sopenharmony_ci int flags, 1228c2ecf20Sopenharmony_ci int expected, 1238c2ecf20Sopenharmony_ci int expected_pid, 1248c2ecf20Sopenharmony_ci bool wait_for_it) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci int ret; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci ksft_print_msg( 1298c2ecf20Sopenharmony_ci "[%d] Trying clone3() with CLONE_SET_TID to %d and 0x%x\n", 1308c2ecf20Sopenharmony_ci getpid(), set_tid[0], flags); 1318c2ecf20Sopenharmony_ci ret = call_clone3_set_tid(set_tid, set_tid_size, flags, expected_pid, 1328c2ecf20Sopenharmony_ci wait_for_it); 1338c2ecf20Sopenharmony_ci ksft_print_msg( 1348c2ecf20Sopenharmony_ci "[%d] clone3() with CLONE_SET_TID %d says :%d - expected %d\n", 1358c2ecf20Sopenharmony_ci getpid(), set_tid[0], ret, expected); 1368c2ecf20Sopenharmony_ci if (ret != expected) 1378c2ecf20Sopenharmony_ci ksft_test_result_fail( 1388c2ecf20Sopenharmony_ci "[%d] Result (%d) is different than expected (%d)\n", 1398c2ecf20Sopenharmony_ci getpid(), ret, expected); 1408c2ecf20Sopenharmony_ci else 1418c2ecf20Sopenharmony_ci ksft_test_result_pass( 1428c2ecf20Sopenharmony_ci "[%d] Result (%d) matches expectation (%d)\n", 1438c2ecf20Sopenharmony_ci getpid(), ret, expected); 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ciint main(int argc, char *argv[]) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci FILE *f; 1488c2ecf20Sopenharmony_ci char buf; 1498c2ecf20Sopenharmony_ci char *line; 1508c2ecf20Sopenharmony_ci int status; 1518c2ecf20Sopenharmony_ci int ret = -1; 1528c2ecf20Sopenharmony_ci size_t len = 0; 1538c2ecf20Sopenharmony_ci int pid_max = 0; 1548c2ecf20Sopenharmony_ci uid_t uid = getuid(); 1558c2ecf20Sopenharmony_ci char proc_path[100] = {0}; 1568c2ecf20Sopenharmony_ci pid_t pid, ns1, ns2, ns3, ns_pid; 1578c2ecf20Sopenharmony_ci pid_t set_tid[MAX_PID_NS_LEVEL * 2]; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci ksft_print_header(); 1608c2ecf20Sopenharmony_ci ksft_set_plan(29); 1618c2ecf20Sopenharmony_ci test_clone3_supported(); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci if (pipe(pipe_1) < 0 || pipe(pipe_2) < 0) 1648c2ecf20Sopenharmony_ci ksft_exit_fail_msg("pipe() failed\n"); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci f = fopen("/proc/sys/kernel/pid_max", "r"); 1678c2ecf20Sopenharmony_ci if (f == NULL) 1688c2ecf20Sopenharmony_ci ksft_exit_fail_msg( 1698c2ecf20Sopenharmony_ci "%s - Could not open /proc/sys/kernel/pid_max\n", 1708c2ecf20Sopenharmony_ci strerror(errno)); 1718c2ecf20Sopenharmony_ci fscanf(f, "%d", &pid_max); 1728c2ecf20Sopenharmony_ci fclose(f); 1738c2ecf20Sopenharmony_ci ksft_print_msg("/proc/sys/kernel/pid_max %d\n", pid_max); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* Try invalid settings */ 1768c2ecf20Sopenharmony_ci memset(&set_tid, 0, sizeof(set_tid)); 1778c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL + 1, 0, -EINVAL, 0, 0); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2, 0, -EINVAL, 0, 0); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2 + 1, 0, 1828c2ecf20Sopenharmony_ci -EINVAL, 0, 0); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 42, 0, -EINVAL, 0, 0); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci /* 1878c2ecf20Sopenharmony_ci * This can actually work if this test running in a MAX_PID_NS_LEVEL - 1 1888c2ecf20Sopenharmony_ci * nested PID namespace. 1898c2ecf20Sopenharmony_ci */ 1908c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL - 1, 0, -EINVAL, 0, 0); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci memset(&set_tid, 0xff, sizeof(set_tid)); 1938c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL + 1, 0, -EINVAL, 0, 0); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2, 0, -EINVAL, 0, 0); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2 + 1, 0, 1988c2ecf20Sopenharmony_ci -EINVAL, 0, 0); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 42, 0, -EINVAL, 0, 0); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci /* 2038c2ecf20Sopenharmony_ci * This can actually work if this test running in a MAX_PID_NS_LEVEL - 1 2048c2ecf20Sopenharmony_ci * nested PID namespace. 2058c2ecf20Sopenharmony_ci */ 2068c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL - 1, 0, -EINVAL, 0, 0); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci memset(&set_tid, 0, sizeof(set_tid)); 2098c2ecf20Sopenharmony_ci /* Try with an invalid PID */ 2108c2ecf20Sopenharmony_ci set_tid[0] = 0; 2118c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0); 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci set_tid[0] = -1; 2148c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* Claim that the set_tid array actually contains 2 elements. */ 2178c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 2, 0, -EINVAL, 0, 0); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci /* Try it in a new PID namespace */ 2208c2ecf20Sopenharmony_ci if (uid == 0) 2218c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0); 2228c2ecf20Sopenharmony_ci else 2238c2ecf20Sopenharmony_ci ksft_test_result_skip("Clone3() with set_tid requires root\n"); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci /* Try with a valid PID (1) this should return -EEXIST. */ 2268c2ecf20Sopenharmony_ci set_tid[0] = 1; 2278c2ecf20Sopenharmony_ci if (uid == 0) 2288c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 1, 0, -EEXIST, 0, 0); 2298c2ecf20Sopenharmony_ci else 2308c2ecf20Sopenharmony_ci ksft_test_result_skip("Clone3() with set_tid requires root\n"); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* Try it in a new PID namespace */ 2338c2ecf20Sopenharmony_ci if (uid == 0) 2348c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, 0, 0, 0); 2358c2ecf20Sopenharmony_ci else 2368c2ecf20Sopenharmony_ci ksft_test_result_skip("Clone3() with set_tid requires root\n"); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci /* pid_max should fail everywhere */ 2398c2ecf20Sopenharmony_ci set_tid[0] = pid_max; 2408c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (uid == 0) 2438c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0); 2448c2ecf20Sopenharmony_ci else 2458c2ecf20Sopenharmony_ci ksft_test_result_skip("Clone3() with set_tid requires root\n"); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (uid != 0) { 2488c2ecf20Sopenharmony_ci /* 2498c2ecf20Sopenharmony_ci * All remaining tests require root. Tell the framework 2508c2ecf20Sopenharmony_ci * that all those tests are skipped as non-root. 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_ci ksft_cnt.ksft_xskip += ksft_plan - ksft_test_num(); 2538c2ecf20Sopenharmony_ci goto out; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* Find the current active PID */ 2578c2ecf20Sopenharmony_ci pid = fork(); 2588c2ecf20Sopenharmony_ci if (pid == 0) { 2598c2ecf20Sopenharmony_ci ksft_print_msg("Child has PID %d\n", getpid()); 2608c2ecf20Sopenharmony_ci child_exit(EXIT_SUCCESS); 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci if (waitpid(pid, &status, 0) < 0) 2638c2ecf20Sopenharmony_ci ksft_exit_fail_msg("Waiting for child %d failed", pid); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci /* After the child has finished, its PID should be free. */ 2668c2ecf20Sopenharmony_ci set_tid[0] = pid; 2678c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 1, 0, 0, 0, 0); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci /* This should fail as there is no PID 1 in that namespace */ 2708c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci /* 2738c2ecf20Sopenharmony_ci * Creating a process with PID 1 in the newly created most nested 2748c2ecf20Sopenharmony_ci * PID namespace and PID 'pid' in the parent PID namespace. This 2758c2ecf20Sopenharmony_ci * needs to work. 2768c2ecf20Sopenharmony_ci */ 2778c2ecf20Sopenharmony_ci set_tid[0] = 1; 2788c2ecf20Sopenharmony_ci set_tid[1] = pid; 2798c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 2, CLONE_NEWPID, 0, pid, 0); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci ksft_print_msg("unshare PID namespace\n"); 2828c2ecf20Sopenharmony_ci if (unshare(CLONE_NEWPID) == -1) 2838c2ecf20Sopenharmony_ci ksft_exit_fail_msg("unshare(CLONE_NEWPID) failed: %s\n", 2848c2ecf20Sopenharmony_ci strerror(errno)); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci set_tid[0] = pid; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci /* This should fail as there is no PID 1 in that namespace */ 2898c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* Let's create a PID 1 */ 2928c2ecf20Sopenharmony_ci ns_pid = fork(); 2938c2ecf20Sopenharmony_ci if (ns_pid == 0) { 2948c2ecf20Sopenharmony_ci /* 2958c2ecf20Sopenharmony_ci * This and the next test cases check that all pid-s are 2968c2ecf20Sopenharmony_ci * released on error paths. 2978c2ecf20Sopenharmony_ci */ 2988c2ecf20Sopenharmony_ci set_tid[0] = 43; 2998c2ecf20Sopenharmony_ci set_tid[1] = -1; 3008c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 2, 0, -EINVAL, 0, 0); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci set_tid[0] = 43; 3038c2ecf20Sopenharmony_ci set_tid[1] = pid; 3048c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 2, 0, 0, 43, 0); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci ksft_print_msg("Child in PID namespace has PID %d\n", getpid()); 3078c2ecf20Sopenharmony_ci set_tid[0] = 2; 3088c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 1, 0, 0, 2, 0); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci set_tid[0] = 1; 3118c2ecf20Sopenharmony_ci set_tid[1] = -1; 3128c2ecf20Sopenharmony_ci set_tid[2] = pid; 3138c2ecf20Sopenharmony_ci /* This should fail as there is invalid PID at level '1'. */ 3148c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 3, CLONE_NEWPID, -EINVAL, 0, 0); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci set_tid[0] = 1; 3178c2ecf20Sopenharmony_ci set_tid[1] = 42; 3188c2ecf20Sopenharmony_ci set_tid[2] = pid; 3198c2ecf20Sopenharmony_ci /* 3208c2ecf20Sopenharmony_ci * This should fail as there are not enough active PID 3218c2ecf20Sopenharmony_ci * namespaces. Again assuming this is running in the host's 3228c2ecf20Sopenharmony_ci * PID namespace. Not yet nested. 3238c2ecf20Sopenharmony_ci */ 3248c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 4, CLONE_NEWPID, -EINVAL, 0, 0); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /* 3278c2ecf20Sopenharmony_ci * This should work and from the parent we should see 3288c2ecf20Sopenharmony_ci * something like 'NSpid: pid 42 1'. 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_ci test_clone3_set_tid(set_tid, 3, CLONE_NEWPID, 0, 42, true); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci child_exit(ksft_cnt.ksft_fail); 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci close(pipe_1[1]); 3368c2ecf20Sopenharmony_ci close(pipe_2[0]); 3378c2ecf20Sopenharmony_ci while (read(pipe_1[0], &buf, 1) > 0) { 3388c2ecf20Sopenharmony_ci ksft_print_msg("[%d] Child is ready and waiting\n", getpid()); 3398c2ecf20Sopenharmony_ci break; 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci snprintf(proc_path, sizeof(proc_path), "/proc/%d/status", pid); 3438c2ecf20Sopenharmony_ci f = fopen(proc_path, "r"); 3448c2ecf20Sopenharmony_ci if (f == NULL) 3458c2ecf20Sopenharmony_ci ksft_exit_fail_msg( 3468c2ecf20Sopenharmony_ci "%s - Could not open %s\n", 3478c2ecf20Sopenharmony_ci strerror(errno), proc_path); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci while (getline(&line, &len, f) != -1) { 3508c2ecf20Sopenharmony_ci if (strstr(line, "NSpid")) { 3518c2ecf20Sopenharmony_ci int i; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci /* Verify that all generated PIDs are as expected. */ 3548c2ecf20Sopenharmony_ci i = sscanf(line, "NSpid:\t%d\t%d\t%d", 3558c2ecf20Sopenharmony_ci &ns3, &ns2, &ns1); 3568c2ecf20Sopenharmony_ci if (i != 3) { 3578c2ecf20Sopenharmony_ci ksft_print_msg( 3588c2ecf20Sopenharmony_ci "Unexpected 'NSPid:' entry: %s", 3598c2ecf20Sopenharmony_ci line); 3608c2ecf20Sopenharmony_ci ns1 = ns2 = ns3 = 0; 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci break; 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci fclose(f); 3668c2ecf20Sopenharmony_ci free(line); 3678c2ecf20Sopenharmony_ci close(pipe_2[0]); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci /* Tell the clone3()'d child to finish. */ 3708c2ecf20Sopenharmony_ci write(pipe_2[1], &buf, 1); 3718c2ecf20Sopenharmony_ci close(pipe_2[1]); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci if (waitpid(ns_pid, &status, 0) < 0) { 3748c2ecf20Sopenharmony_ci ksft_print_msg("Child returned %s\n", strerror(errno)); 3758c2ecf20Sopenharmony_ci ret = -errno; 3768c2ecf20Sopenharmony_ci goto out; 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci if (!WIFEXITED(status)) 3808c2ecf20Sopenharmony_ci ksft_test_result_fail("Child error\n"); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci ksft_cnt.ksft_pass += 6 - (ksft_cnt.ksft_fail - WEXITSTATUS(status)); 3838c2ecf20Sopenharmony_ci ksft_cnt.ksft_fail = WEXITSTATUS(status); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (ns3 == pid && ns2 == 42 && ns1 == 1) 3868c2ecf20Sopenharmony_ci ksft_test_result_pass( 3878c2ecf20Sopenharmony_ci "PIDs in all namespaces as expected (%d,%d,%d)\n", 3888c2ecf20Sopenharmony_ci ns3, ns2, ns1); 3898c2ecf20Sopenharmony_ci else 3908c2ecf20Sopenharmony_ci ksft_test_result_fail( 3918c2ecf20Sopenharmony_ci "PIDs in all namespaces not as expected (%d,%d,%d)\n", 3928c2ecf20Sopenharmony_ci ns3, ns2, ns1); 3938c2ecf20Sopenharmony_ciout: 3948c2ecf20Sopenharmony_ci ret = 0; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci return !ret ? ksft_exit_pass() : ksft_exit_fail(); 3978c2ecf20Sopenharmony_ci} 398