1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/*\ 7f08c3bdfSopenharmony_ci * [Description] 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * Basic clone3() test. 10f08c3bdfSopenharmony_ci */ 11f08c3bdfSopenharmony_ci 12f08c3bdfSopenharmony_ci#define _GNU_SOURCE 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci#include <stdlib.h> 15f08c3bdfSopenharmony_ci#include <sys/wait.h> 16f08c3bdfSopenharmony_ci 17f08c3bdfSopenharmony_ci#include "tst_test.h" 18f08c3bdfSopenharmony_ci#include "lapi/sched.h" 19f08c3bdfSopenharmony_ci#include "lapi/pidfd.h" 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci#define CHILD_SIGNAL SIGUSR1 22f08c3bdfSopenharmony_ci#define DATA 777 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_cistatic int pidfd, child_tid, parent_tid, parent_received_signal; 25f08c3bdfSopenharmony_cistatic volatile int child_received_signal, child_data; 26f08c3bdfSopenharmony_cistatic struct clone_args *args; 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_cistatic struct tcase { 29f08c3bdfSopenharmony_ci uint64_t flags; 30f08c3bdfSopenharmony_ci int exit_signal; 31f08c3bdfSopenharmony_ci} tcases[] = { 32f08c3bdfSopenharmony_ci {0, SIGCHLD}, 33f08c3bdfSopenharmony_ci {0, SIGUSR2}, 34f08c3bdfSopenharmony_ci {CLONE_FS, SIGCHLD}, 35f08c3bdfSopenharmony_ci {CLONE_NEWPID, SIGCHLD}, 36f08c3bdfSopenharmony_ci {CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_PIDFD, SIGCHLD}, 37f08c3bdfSopenharmony_ci}; 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_cistatic void parent_rx_signal(int sig) 40f08c3bdfSopenharmony_ci{ 41f08c3bdfSopenharmony_ci parent_received_signal = sig; 42f08c3bdfSopenharmony_ci} 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_cistatic void child_rx_signal(int sig, siginfo_t *info, void *ucontext) 45f08c3bdfSopenharmony_ci{ 46f08c3bdfSopenharmony_ci (void) ucontext; 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ci child_received_signal = sig; 49f08c3bdfSopenharmony_ci child_data = info->si_value.sival_int; 50f08c3bdfSopenharmony_ci} 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_cistatic struct sigaction psig_action = { 53f08c3bdfSopenharmony_ci .sa_handler = parent_rx_signal, 54f08c3bdfSopenharmony_ci}; 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_cistatic struct sigaction csig_action = { 57f08c3bdfSopenharmony_ci .sa_sigaction = child_rx_signal, 58f08c3bdfSopenharmony_ci .sa_flags = SA_SIGINFO, 59f08c3bdfSopenharmony_ci}; 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_cistatic siginfo_t uinfo = { 62f08c3bdfSopenharmony_ci .si_signo = CHILD_SIGNAL, 63f08c3bdfSopenharmony_ci .si_code = SI_QUEUE, 64f08c3bdfSopenharmony_ci .si_value.sival_int = DATA, 65f08c3bdfSopenharmony_ci}; 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_cistatic void do_child(int clone_pidfd) 69f08c3bdfSopenharmony_ci{ 70f08c3bdfSopenharmony_ci int count = 1000; 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci if (clone_pidfd) { 73f08c3bdfSopenharmony_ci child_received_signal = 0; 74f08c3bdfSopenharmony_ci child_data = 0; 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci SAFE_SIGACTION(CHILD_SIGNAL, &csig_action, NULL); 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE(0); 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci while (child_received_signal != CHILD_SIGNAL && --count) 81f08c3bdfSopenharmony_ci usleep(100); 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci if (!child_received_signal) { 84f08c3bdfSopenharmony_ci tst_res(TFAIL, "Child haven't got signal"); 85f08c3bdfSopenharmony_ci exit(0); 86f08c3bdfSopenharmony_ci } 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci if (child_received_signal != CHILD_SIGNAL) { 89f08c3bdfSopenharmony_ci tst_res(TFAIL, "Child got %s (%i) signal expected %s", 90f08c3bdfSopenharmony_ci tst_strsig(child_received_signal), 91f08c3bdfSopenharmony_ci child_received_signal, 92f08c3bdfSopenharmony_ci tst_strsig(CHILD_SIGNAL)); 93f08c3bdfSopenharmony_ci exit(0); 94f08c3bdfSopenharmony_ci } 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci tst_res(TPASS, "Child got correct signal %s", 97f08c3bdfSopenharmony_ci tst_strsig(CHILD_SIGNAL)); 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci if (child_data != DATA) { 100f08c3bdfSopenharmony_ci tst_res(TFAIL, "Child got wrong si_value=%i expected %i", 101f08c3bdfSopenharmony_ci child_data, DATA); 102f08c3bdfSopenharmony_ci } else { 103f08c3bdfSopenharmony_ci tst_res(TPASS, "Child got correct si_value"); 104f08c3bdfSopenharmony_ci } 105f08c3bdfSopenharmony_ci } 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci exit(0); 108f08c3bdfSopenharmony_ci} 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_cistatic void run(unsigned int n) 111f08c3bdfSopenharmony_ci{ 112f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 113f08c3bdfSopenharmony_ci int status, clone_pidfd = tc->flags & CLONE_PIDFD; 114f08c3bdfSopenharmony_ci pid_t pid; 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci args->flags = tc->flags; 117f08c3bdfSopenharmony_ci args->pidfd = (uint64_t)(&pidfd); 118f08c3bdfSopenharmony_ci args->child_tid = (uint64_t)(&child_tid); 119f08c3bdfSopenharmony_ci args->parent_tid = (uint64_t)(&parent_tid); 120f08c3bdfSopenharmony_ci args->exit_signal = tc->exit_signal; 121f08c3bdfSopenharmony_ci args->stack = 0; 122f08c3bdfSopenharmony_ci args->stack_size = 0; 123f08c3bdfSopenharmony_ci args->tls = 0; 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci parent_received_signal = 0; 126f08c3bdfSopenharmony_ci SAFE_SIGACTION(tc->exit_signal, &psig_action, NULL); 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_ci TEST(pid = clone3(args, sizeof(*args))); 129f08c3bdfSopenharmony_ci if (pid < 0) { 130f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "clone3() failed (%d)", n); 131f08c3bdfSopenharmony_ci return; 132f08c3bdfSopenharmony_ci } 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci if (!pid) 135f08c3bdfSopenharmony_ci do_child(clone_pidfd); 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci /* Need to send signal to child process */ 138f08c3bdfSopenharmony_ci if (clone_pidfd) { 139f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAIT(0); 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci TEST(pidfd_send_signal(pidfd, CHILD_SIGNAL, &uinfo, 0)); 142f08c3bdfSopenharmony_ci if (TST_RET != 0) { 143f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "pidfd_send_signal() failed"); 144f08c3bdfSopenharmony_ci return; 145f08c3bdfSopenharmony_ci } 146f08c3bdfSopenharmony_ci } 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_ci SAFE_WAITPID(pid, &status, __WALL); 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci if (!parent_received_signal) { 151f08c3bdfSopenharmony_ci tst_res(TFAIL, "Parent haven't got signal"); 152f08c3bdfSopenharmony_ci return; 153f08c3bdfSopenharmony_ci } 154f08c3bdfSopenharmony_ci 155f08c3bdfSopenharmony_ci if (parent_received_signal != tc->exit_signal) { 156f08c3bdfSopenharmony_ci tst_res(TFAIL, "Parent got %s (%i) signal expected %s", 157f08c3bdfSopenharmony_ci tst_strsig(parent_received_signal), 158f08c3bdfSopenharmony_ci parent_received_signal, 159f08c3bdfSopenharmony_ci tst_strsig(tc->exit_signal)); 160f08c3bdfSopenharmony_ci return; 161f08c3bdfSopenharmony_ci } 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci tst_res(TPASS, "Parent got correct signal %s", 164f08c3bdfSopenharmony_ci tst_strsig(parent_received_signal)); 165f08c3bdfSopenharmony_ci} 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_cistatic void setup(void) 168f08c3bdfSopenharmony_ci{ 169f08c3bdfSopenharmony_ci clone3_supported_by_kernel(); 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_ci uinfo.si_pid = getpid(); 172f08c3bdfSopenharmony_ci uinfo.si_uid = getuid(); 173f08c3bdfSopenharmony_ci} 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_cistatic struct tst_test test = { 176f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 177f08c3bdfSopenharmony_ci .test = run, 178f08c3bdfSopenharmony_ci .setup = setup, 179f08c3bdfSopenharmony_ci .needs_root = 1, 180f08c3bdfSopenharmony_ci .needs_checkpoints = 1, 181f08c3bdfSopenharmony_ci .bufs = (struct tst_buffers []) { 182f08c3bdfSopenharmony_ci {&args, .size = sizeof(*args)}, 183f08c3bdfSopenharmony_ci {}, 184f08c3bdfSopenharmony_ci } 185f08c3bdfSopenharmony_ci}; 186