0001
0002
0003
0004
0005
0006
0007
0008
0009 #define _GNU_SOURCE
0010 #include <errno.h>
0011 #include <linux/types.h>
0012 #include <linux/sched.h>
0013 #include <stdio.h>
0014 #include <stdlib.h>
0015 #include <stdbool.h>
0016 #include <sys/syscall.h>
0017 #include <sys/types.h>
0018 #include <sys/un.h>
0019 #include <sys/wait.h>
0020 #include <unistd.h>
0021 #include <sched.h>
0022
0023 #include "../kselftest.h"
0024 #include "clone3_selftests.h"
0025
0026 #ifndef MAX_PID_NS_LEVEL
0027 #define MAX_PID_NS_LEVEL 32
0028 #endif
0029
0030 static int pipe_1[2];
0031 static int pipe_2[2];
0032
0033 static void child_exit(int ret)
0034 {
0035 fflush(stdout);
0036 fflush(stderr);
0037 _exit(ret);
0038 }
0039
0040 static int call_clone3_set_tid(pid_t *set_tid,
0041 size_t set_tid_size,
0042 int flags,
0043 int expected_pid,
0044 bool wait_for_it)
0045 {
0046 int status;
0047 pid_t pid = -1;
0048
0049 struct __clone_args args = {
0050 .flags = flags,
0051 .exit_signal = SIGCHLD,
0052 .set_tid = ptr_to_u64(set_tid),
0053 .set_tid_size = set_tid_size,
0054 };
0055
0056 pid = sys_clone3(&args, sizeof(args));
0057 if (pid < 0) {
0058 ksft_print_msg("%s - Failed to create new process\n",
0059 strerror(errno));
0060 return -errno;
0061 }
0062
0063 if (pid == 0) {
0064 int ret;
0065 char tmp = 0;
0066 int exit_code = EXIT_SUCCESS;
0067
0068 ksft_print_msg("I am the child, my PID is %d (expected %d)\n",
0069 getpid(), set_tid[0]);
0070 if (wait_for_it) {
0071 ksft_print_msg("[%d] Child is ready and waiting\n",
0072 getpid());
0073
0074
0075 close(pipe_1[0]);
0076 ret = write(pipe_1[1], &tmp, 1);
0077 if (ret != 1) {
0078 ksft_print_msg(
0079 "Writing to pipe returned %d", ret);
0080 exit_code = EXIT_FAILURE;
0081 }
0082 close(pipe_1[1]);
0083 close(pipe_2[1]);
0084 ret = read(pipe_2[0], &tmp, 1);
0085 if (ret != 1) {
0086 ksft_print_msg(
0087 "Reading from pipe returned %d", ret);
0088 exit_code = EXIT_FAILURE;
0089 }
0090 close(pipe_2[0]);
0091 }
0092
0093 if (set_tid[0] != getpid())
0094 child_exit(EXIT_FAILURE);
0095 child_exit(exit_code);
0096 }
0097
0098 if (expected_pid == 0 || expected_pid == pid) {
0099 ksft_print_msg("I am the parent (%d). My child's pid is %d\n",
0100 getpid(), pid);
0101 } else {
0102 ksft_print_msg(
0103 "Expected child pid %d does not match actual pid %d\n",
0104 expected_pid, pid);
0105 return -1;
0106 }
0107
0108 if (waitpid(pid, &status, 0) < 0) {
0109 ksft_print_msg("Child returned %s\n", strerror(errno));
0110 return -errno;
0111 }
0112
0113 if (!WIFEXITED(status))
0114 return -1;
0115
0116 return WEXITSTATUS(status);
0117 }
0118
0119 static void test_clone3_set_tid(pid_t *set_tid,
0120 size_t set_tid_size,
0121 int flags,
0122 int expected,
0123 int expected_pid,
0124 bool wait_for_it)
0125 {
0126 int ret;
0127
0128 ksft_print_msg(
0129 "[%d] Trying clone3() with CLONE_SET_TID to %d and 0x%x\n",
0130 getpid(), set_tid[0], flags);
0131 ret = call_clone3_set_tid(set_tid, set_tid_size, flags, expected_pid,
0132 wait_for_it);
0133 ksft_print_msg(
0134 "[%d] clone3() with CLONE_SET_TID %d says :%d - expected %d\n",
0135 getpid(), set_tid[0], ret, expected);
0136 if (ret != expected)
0137 ksft_test_result_fail(
0138 "[%d] Result (%d) is different than expected (%d)\n",
0139 getpid(), ret, expected);
0140 else
0141 ksft_test_result_pass(
0142 "[%d] Result (%d) matches expectation (%d)\n",
0143 getpid(), ret, expected);
0144 }
0145 int main(int argc, char *argv[])
0146 {
0147 FILE *f;
0148 char buf;
0149 char *line;
0150 int status;
0151 int ret = -1;
0152 size_t len = 0;
0153 int pid_max = 0;
0154 uid_t uid = getuid();
0155 char proc_path[100] = {0};
0156 pid_t pid, ns1, ns2, ns3, ns_pid;
0157 pid_t set_tid[MAX_PID_NS_LEVEL * 2];
0158
0159 ksft_print_header();
0160 ksft_set_plan(29);
0161 test_clone3_supported();
0162
0163 if (pipe(pipe_1) < 0 || pipe(pipe_2) < 0)
0164 ksft_exit_fail_msg("pipe() failed\n");
0165
0166 f = fopen("/proc/sys/kernel/pid_max", "r");
0167 if (f == NULL)
0168 ksft_exit_fail_msg(
0169 "%s - Could not open /proc/sys/kernel/pid_max\n",
0170 strerror(errno));
0171 fscanf(f, "%d", &pid_max);
0172 fclose(f);
0173 ksft_print_msg("/proc/sys/kernel/pid_max %d\n", pid_max);
0174
0175
0176 memset(&set_tid, 0, sizeof(set_tid));
0177 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL + 1, 0, -EINVAL, 0, 0);
0178
0179 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2, 0, -EINVAL, 0, 0);
0180
0181 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2 + 1, 0,
0182 -EINVAL, 0, 0);
0183
0184 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 42, 0, -EINVAL, 0, 0);
0185
0186
0187
0188
0189
0190 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL - 1, 0, -EINVAL, 0, 0);
0191
0192 memset(&set_tid, 0xff, sizeof(set_tid));
0193 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL + 1, 0, -EINVAL, 0, 0);
0194
0195 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2, 0, -EINVAL, 0, 0);
0196
0197 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2 + 1, 0,
0198 -EINVAL, 0, 0);
0199
0200 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 42, 0, -EINVAL, 0, 0);
0201
0202
0203
0204
0205
0206 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL - 1, 0, -EINVAL, 0, 0);
0207
0208 memset(&set_tid, 0, sizeof(set_tid));
0209
0210 set_tid[0] = 0;
0211 test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
0212
0213 set_tid[0] = -1;
0214 test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
0215
0216
0217 test_clone3_set_tid(set_tid, 2, 0, -EINVAL, 0, 0);
0218
0219
0220 if (uid == 0)
0221 test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
0222 else
0223 ksft_test_result_skip("Clone3() with set_tid requires root\n");
0224
0225
0226 set_tid[0] = 1;
0227 if (uid == 0)
0228 test_clone3_set_tid(set_tid, 1, 0, -EEXIST, 0, 0);
0229 else
0230 ksft_test_result_skip("Clone3() with set_tid requires root\n");
0231
0232
0233 if (uid == 0)
0234 test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, 0, 0, 0);
0235 else
0236 ksft_test_result_skip("Clone3() with set_tid requires root\n");
0237
0238
0239 set_tid[0] = pid_max;
0240 test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
0241
0242 if (uid == 0)
0243 test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
0244 else
0245 ksft_test_result_skip("Clone3() with set_tid requires root\n");
0246
0247 if (uid != 0) {
0248
0249
0250
0251
0252 ksft_cnt.ksft_xskip += ksft_plan - ksft_test_num();
0253 goto out;
0254 }
0255
0256
0257 pid = fork();
0258 if (pid == 0) {
0259 ksft_print_msg("Child has PID %d\n", getpid());
0260 child_exit(EXIT_SUCCESS);
0261 }
0262 if (waitpid(pid, &status, 0) < 0)
0263 ksft_exit_fail_msg("Waiting for child %d failed", pid);
0264
0265
0266 set_tid[0] = pid;
0267 test_clone3_set_tid(set_tid, 1, 0, 0, 0, 0);
0268
0269
0270 test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
0271
0272
0273
0274
0275
0276
0277 set_tid[0] = 1;
0278 set_tid[1] = pid;
0279 test_clone3_set_tid(set_tid, 2, CLONE_NEWPID, 0, pid, 0);
0280
0281 ksft_print_msg("unshare PID namespace\n");
0282 if (unshare(CLONE_NEWPID) == -1)
0283 ksft_exit_fail_msg("unshare(CLONE_NEWPID) failed: %s\n",
0284 strerror(errno));
0285
0286 set_tid[0] = pid;
0287
0288
0289 test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
0290
0291
0292 ns_pid = fork();
0293 if (ns_pid == 0) {
0294
0295
0296
0297
0298 set_tid[0] = 43;
0299 set_tid[1] = -1;
0300 test_clone3_set_tid(set_tid, 2, 0, -EINVAL, 0, 0);
0301
0302 set_tid[0] = 43;
0303 set_tid[1] = pid;
0304 test_clone3_set_tid(set_tid, 2, 0, 0, 43, 0);
0305
0306 ksft_print_msg("Child in PID namespace has PID %d\n", getpid());
0307 set_tid[0] = 2;
0308 test_clone3_set_tid(set_tid, 1, 0, 0, 2, 0);
0309
0310 set_tid[0] = 1;
0311 set_tid[1] = -1;
0312 set_tid[2] = pid;
0313
0314 test_clone3_set_tid(set_tid, 3, CLONE_NEWPID, -EINVAL, 0, 0);
0315
0316 set_tid[0] = 1;
0317 set_tid[1] = 42;
0318 set_tid[2] = pid;
0319
0320
0321
0322
0323
0324 test_clone3_set_tid(set_tid, 4, CLONE_NEWPID, -EINVAL, 0, 0);
0325
0326
0327
0328
0329
0330 test_clone3_set_tid(set_tid, 3, CLONE_NEWPID, 0, 42, true);
0331
0332 child_exit(ksft_cnt.ksft_fail);
0333 }
0334
0335 close(pipe_1[1]);
0336 close(pipe_2[0]);
0337 while (read(pipe_1[0], &buf, 1) > 0) {
0338 ksft_print_msg("[%d] Child is ready and waiting\n", getpid());
0339 break;
0340 }
0341
0342 snprintf(proc_path, sizeof(proc_path), "/proc/%d/status", pid);
0343 f = fopen(proc_path, "r");
0344 if (f == NULL)
0345 ksft_exit_fail_msg(
0346 "%s - Could not open %s\n",
0347 strerror(errno), proc_path);
0348
0349 while (getline(&line, &len, f) != -1) {
0350 if (strstr(line, "NSpid")) {
0351 int i;
0352
0353
0354 i = sscanf(line, "NSpid:\t%d\t%d\t%d",
0355 &ns3, &ns2, &ns1);
0356 if (i != 3) {
0357 ksft_print_msg(
0358 "Unexpected 'NSPid:' entry: %s",
0359 line);
0360 ns1 = ns2 = ns3 = 0;
0361 }
0362 break;
0363 }
0364 }
0365 fclose(f);
0366 free(line);
0367 close(pipe_2[0]);
0368
0369
0370 write(pipe_2[1], &buf, 1);
0371 close(pipe_2[1]);
0372
0373 if (waitpid(ns_pid, &status, 0) < 0) {
0374 ksft_print_msg("Child returned %s\n", strerror(errno));
0375 ret = -errno;
0376 goto out;
0377 }
0378
0379 if (!WIFEXITED(status))
0380 ksft_test_result_fail("Child error\n");
0381
0382 ksft_cnt.ksft_pass += 6 - (ksft_cnt.ksft_fail - WEXITSTATUS(status));
0383 ksft_cnt.ksft_fail = WEXITSTATUS(status);
0384
0385 if (ns3 == pid && ns2 == 42 && ns1 == 1)
0386 ksft_test_result_pass(
0387 "PIDs in all namespaces as expected (%d,%d,%d)\n",
0388 ns3, ns2, ns1);
0389 else
0390 ksft_test_result_fail(
0391 "PIDs in all namespaces not as expected (%d,%d,%d)\n",
0392 ns3, ns2, ns1);
0393 out:
0394 ret = 0;
0395
0396 return !ret ? ksft_exit_pass() : ksft_exit_fail();
0397 }