1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2019 SUSE LLC
4 * Author: Christian Amann <camann@suse.com>
5 */
6
7/*
8 * This tests the rt_sigqueueinfo() syscall.
9 *
10 * It does so by creating a thread which registers the corresponding
11 * signal handler. After that the main thread sends a signal and data
12 * to the handler thread. If the correct signal and data is received,
13 * the test is successful.
14 */
15
16#include <signal.h>
17#include <stdlib.h>
18#include "config.h"
19#include "tst_test.h"
20#include "tst_safe_pthread.h"
21
22#ifdef HAVE_STRUCT_SIGACTION_SA_SIGACTION
23#include "rt_sigqueueinfo.h"
24
25#define SIGNAL	SIGUSR1
26#define DATA	777
27
28static struct sigaction *sig_action;
29static int sig_rec;
30static siginfo_t *uinfo;
31static pid_t tid;
32
33static void received_signal(int sig, siginfo_t *info, void *ucontext)
34{
35	if (info && ucontext) {
36		if (sig == SIGNAL && info->si_value.sival_int == DATA) {
37			tst_res(TPASS, "Received correct signal and data!");
38			sig_rec = 1;
39		} else
40			tst_res(TFAIL, "Received wrong signal and/or data!");
41	} else
42		tst_res(TFAIL, "Signal handling went wrong!");
43}
44
45static void *handle_thread(void *arg LTP_ATTRIBUTE_UNUSED)
46{
47	int ret;
48
49	tid = tst_syscall(__NR_gettid);
50
51	ret = sigaction(SIGNAL, sig_action, NULL);
52	if (ret)
53		tst_brk(TBROK, "Failed to set sigaction for handler thread!");
54
55	TST_CHECKPOINT_WAKE(0);
56	TST_CHECKPOINT_WAIT(1);
57	return arg;
58}
59
60static void verify_sigqueueinfo(void)
61{
62	pthread_t thr;
63
64	SAFE_PTHREAD_CREATE(&thr, NULL, handle_thread, NULL);
65
66	TST_CHECKPOINT_WAIT(0);
67
68	TEST(sys_rt_sigqueueinfo(tid, SIGNAL, uinfo));
69	if (TST_RET != 0) {
70		tst_res(TFAIL | TTERRNO, "rt_sigqueueinfo() failed");
71		return;
72	}
73
74	TST_CHECKPOINT_WAKE(1);
75	SAFE_PTHREAD_JOIN(thr, NULL);
76
77	if (sig_rec)
78		tst_res(TPASS, "rt_sigqueueinfo() was successful!");
79}
80
81static void setup(void)
82{
83	sig_action = SAFE_MALLOC(sizeof(struct sigaction));
84
85	memset(sig_action, 0, sizeof(*sig_action));
86	sig_action->sa_sigaction = received_signal;
87	sig_action->sa_flags = SA_SIGINFO;
88
89	uinfo = SAFE_MALLOC(sizeof(siginfo_t));
90
91	memset(uinfo, 0, sizeof(*uinfo));
92	uinfo->si_code = SI_QUEUE;
93	uinfo->si_pid = getpid();
94	uinfo->si_uid = getuid();
95	uinfo->si_value.sival_int = DATA;
96
97	sig_rec = 0;
98}
99
100static void cleanup(void)
101{
102	free(uinfo);
103	free(sig_action);
104}
105
106static struct tst_test test = {
107	.test_all = verify_sigqueueinfo,
108	.setup = setup,
109	.cleanup = cleanup,
110	.needs_checkpoints = 1,
111};
112
113#else
114	TST_TEST_TCONF(
115		"This system does not support rt_sigqueueinfo().");
116#endif /* HAVE_STRUCT_SIGACTION_SA_SIGACTION */
117