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