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 child. Then check if signal 13 * notification contains si_pid of the child. 14 */ 15 16#define _GNU_SOURCE 1 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 volatile int received; 27static siginfo_t info; 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 signal_handler(LTP_ATTRIBUTE_UNUSED int sig, siginfo_t *si, LTP_ATTRIBUTE_UNUSED void *unused) 38{ 39 memcpy(&info, si, sizeof(info)); 40 received++; 41} 42 43static void child_func(void) 44{ 45 pid_t cpid, ppid; 46 mqd_t mqd_child; 47 48 cpid = tst_getpid(); 49 ppid = getppid(); 50 51 TST_EXP_EQ_LI(cpid, 1); 52 TST_EXP_EQ_LI(ppid, 0); 53 54 TST_CHECKPOINT_WAIT(0); 55 56 tst_res(TINFO, "Send mqueue message from child"); 57 58 mqd_child = SAFE_MQ_OPEN(MQNAME, O_WRONLY, 0, NULL); 59 SAFE_MQ_SEND(mqd_child, "pippo", 5, 1); 60 61 TST_CHECKPOINT_WAKE(0); 62} 63 64static void cleanup(void) 65{ 66 remove_mqueue(mqd); 67} 68 69static void run(void) 70{ 71 pid_t cpid; 72 struct sigaction sa; 73 struct sigevent notif; 74 const struct tst_clone_args args = { 75 .flags = CLONE_NEWPID, 76 .exit_signal = SIGCHLD, 77 }; 78 79 remove_mqueue(mqd); 80 received = 0; 81 82 cpid = SAFE_CLONE(&args); 83 if (!cpid) { 84 child_func(); 85 return; 86 } 87 88 tst_res(TINFO, "Register notification on posix mqueue"); 89 90 mqd = SAFE_MQ_OPEN(MQNAME, O_RDWR | O_CREAT | O_EXCL, 0777, NULL); 91 92 notif.sigev_notify = SIGEV_SIGNAL; 93 notif.sigev_signo = SIGUSR1; 94 95 SAFE_MQ_NOTIFY(mqd, ¬if); 96 97 sa.sa_flags = SA_SIGINFO; 98 SAFE_SIGEMPTYSET(&sa.sa_mask); 99 sa.sa_sigaction = signal_handler; 100 SAFE_SIGACTION(SIGUSR1, &sa, NULL); 101 102 TST_CHECKPOINT_WAKE_AND_WAIT(0); 103 104 tst_reap_children(); 105 106 TST_EXP_EQ_LI(received, 1); 107 TST_EXP_EQ_LI(info.si_signo, SIGUSR1); 108 TST_EXP_EQ_LI(info.si_code, SI_MESGQ); 109 TST_EXP_EQ_LI(info.si_pid, cpid); 110} 111 112static struct tst_test test = { 113 .test_all = run, 114 .cleanup = cleanup, 115 .forks_child = 1, 116 .needs_root = 1, 117 .needs_checkpoints = 1, 118}; 119