1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) Bull S.A.S. 2008 4 * 01/12/08 Nadia Derbey <Nadia.Derbey@bull.net> 5 * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> 6 */ 7 8/*\ 9 * [Description] 10 * 11 * Clone a process with CLONE_NEWPID flag, register notification on a posix 12 * mqueue and send a mqueue message from the parent. Then check if signal 13 * notification contains si_pid of the parent. 14 */ 15 16#define _GNU_SOURCE 17#include <signal.h> 18#include <mqueue.h> 19#include "tst_test.h" 20#include "tst_safe_posix_ipc.h" 21#include "lapi/sched.h" 22 23#define MQNAME "/LTP_PIDNS30_MQ" 24 25static mqd_t mqd = -1; 26static siginfo_t info; 27static volatile int received; 28 29static void remove_mqueue(mqd_t mqd) 30{ 31 if (mqd != -1) 32 SAFE_MQ_CLOSE(mqd); 33 34 mq_unlink(MQNAME); 35} 36 37static void child_signal_handler(LTP_ATTRIBUTE_UNUSED int sig, siginfo_t *si, LTP_ATTRIBUTE_UNUSED void *unused) 38{ 39 received = 1; 40 memcpy(&info, si, sizeof(info)); 41} 42 43static void child_func(void) 44{ 45 pid_t cpid, ppid; 46 struct sigaction sa; 47 struct sigevent notif; 48 mqd_t mqd_child; 49 50 cpid = tst_getpid(); 51 ppid = getppid(); 52 53 TST_EXP_EQ_LI(cpid, 1); 54 TST_EXP_EQ_LI(ppid, 0); 55 56 TST_CHECKPOINT_WAIT(0); 57 58 tst_res(TINFO, "Register notification on posix mqueue"); 59 60 mqd_child = SAFE_MQ_OPEN(MQNAME, O_RDONLY, 0, NULL); 61 notif.sigev_notify = SIGEV_SIGNAL; 62 notif.sigev_signo = SIGUSR1; 63 notif.sigev_value.sival_int = mqd_child; 64 65 SAFE_MQ_NOTIFY(mqd_child, ¬if); 66 67 sa.sa_flags = SA_SIGINFO; 68 SAFE_SIGEMPTYSET(&sa.sa_mask); 69 sa.sa_sigaction = child_signal_handler; 70 SAFE_SIGACTION(SIGUSR1, &sa, NULL); 71 72 TST_CHECKPOINT_WAKE_AND_WAIT(0); 73 74 if (received) 75 tst_res(TPASS, "Signal notification has been received"); 76 else 77 tst_res(TFAIL, "Signal notification has not been received"); 78 79 TST_EXP_EQ_LI(info.si_signo, SIGUSR1); 80 TST_EXP_EQ_LI(info.si_code, SI_MESGQ); 81 TST_EXP_EQ_LI(info.si_pid, 0); 82} 83 84static void cleanup(void) 85{ 86 remove_mqueue(mqd); 87} 88 89static void run(void) 90{ 91 const struct tst_clone_args args = { 92 .flags = CLONE_NEWPID, 93 .exit_signal = SIGCHLD, 94 }; 95 96 remove_mqueue(mqd); 97 received = 0; 98 99 if (!SAFE_CLONE(&args)) { 100 child_func(); 101 return; 102 } 103 104 mqd = SAFE_MQ_OPEN(MQNAME, O_RDWR | O_CREAT | O_EXCL, 0777, 0); 105 106 TST_CHECKPOINT_WAKE_AND_WAIT(0); 107 108 tst_res(TINFO, "Send mqueue message"); 109 110 SAFE_MQ_SEND(mqd, "pippo", 5, 1); 111 112 TST_CHECKPOINT_WAKE(0); 113} 114 115static struct tst_test test = { 116 .test_all = run, 117 .cleanup = cleanup, 118 .forks_child = 1, 119 .needs_root = 1, 120 .needs_checkpoints = 1, 121}; 122