1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines  Corp., 2002
4f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2009-2019
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci * AUTHORS
7f08c3bdfSopenharmony_ci * Paul Larson
8f08c3bdfSopenharmony_ci * Matthias Maennich
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci * DESCRIPTION
11f08c3bdfSopenharmony_ci * Test 1: Suppress handling SIGUSR1 and SIGUSR1, raise them and assert their
12f08c3bdfSopenharmony_ci * signal pending.
13f08c3bdfSopenharmony_ci * Test 2: Call sigpending(sigset_t*=-1), it should return -1 with errno EFAULT.
14f08c3bdfSopenharmony_ci */
15f08c3bdfSopenharmony_ci
16f08c3bdfSopenharmony_ci#include "config.h"
17f08c3bdfSopenharmony_ci#include "tst_test.h"
18f08c3bdfSopenharmony_ci#include "ltp_signal.h"
19f08c3bdfSopenharmony_ci#include "lapi/syscalls.h"
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_cistatic void sigpending_info(void)
22f08c3bdfSopenharmony_ci{
23f08c3bdfSopenharmony_ci	switch (tst_variant) {
24f08c3bdfSopenharmony_ci	case 0:
25f08c3bdfSopenharmony_ci		tst_res(TINFO, "Testing libc sigpending()");
26f08c3bdfSopenharmony_ci	break;
27f08c3bdfSopenharmony_ci	case 1:
28f08c3bdfSopenharmony_ci		tst_res(TINFO, "Testing __NR_sigpending syscall");
29f08c3bdfSopenharmony_ci	break;
30f08c3bdfSopenharmony_ci	case 2:
31f08c3bdfSopenharmony_ci		tst_res(TINFO, "Testing __NR_rt_sigpending syscall");
32f08c3bdfSopenharmony_ci	break;
33f08c3bdfSopenharmony_ci	}
34f08c3bdfSopenharmony_ci}
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_cistatic int tested_sigpending(sigset_t *sigset)
37f08c3bdfSopenharmony_ci{
38f08c3bdfSopenharmony_ci	switch (tst_variant) {
39f08c3bdfSopenharmony_ci	case 0:
40f08c3bdfSopenharmony_ci#ifndef HAVE_SIGPENDING
41f08c3bdfSopenharmony_ci		tst_brk(TCONF, "libc sigpending() is not implemented");
42f08c3bdfSopenharmony_ci#else
43f08c3bdfSopenharmony_ci		return sigpending(sigset);
44f08c3bdfSopenharmony_ci#endif
45f08c3bdfSopenharmony_ci	break;
46f08c3bdfSopenharmony_ci	case 1:
47f08c3bdfSopenharmony_ci		return tst_syscall(__NR_sigpending, sigset);
48f08c3bdfSopenharmony_ci	case 2:
49f08c3bdfSopenharmony_ci		return tst_syscall(__NR_rt_sigpending, sigset, SIGSETSIZE);
50f08c3bdfSopenharmony_ci	}
51f08c3bdfSopenharmony_ci	return -1;
52f08c3bdfSopenharmony_ci}
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_cistatic int sighandler_counter;
55f08c3bdfSopenharmony_cistatic void sighandler(int signum LTP_ATTRIBUTE_UNUSED)
56f08c3bdfSopenharmony_ci{
57f08c3bdfSopenharmony_ci	++sighandler_counter;
58f08c3bdfSopenharmony_ci}
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_cistatic void test_sigpending(void)
61f08c3bdfSopenharmony_ci{
62f08c3bdfSopenharmony_ci	int SIGMAX = MIN(sizeof(sigset_t) * 8, (size_t)_NSIG);
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci	int i; /* loop index */
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_ci	sighandler_counter = 0;
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_ci	/* set up signal mask and handler */
69f08c3bdfSopenharmony_ci	sigset_t only_SIGUSR, old_mask;
70f08c3bdfSopenharmony_ci	sighandler_t old_sighandler1, old_sighandler2;
71f08c3bdfSopenharmony_ci	sigemptyset(&only_SIGUSR);
72f08c3bdfSopenharmony_ci	sigaddset(&only_SIGUSR, SIGUSR1);
73f08c3bdfSopenharmony_ci	sigaddset(&only_SIGUSR, SIGUSR2);
74f08c3bdfSopenharmony_ci	if (sigprocmask(SIG_SETMASK, &only_SIGUSR, &old_mask))
75f08c3bdfSopenharmony_ci		tst_brk(TBROK, "sigprocmask failed");
76f08c3bdfSopenharmony_ci	old_sighandler1 = SAFE_SIGNAL(SIGUSR1, sighandler);
77f08c3bdfSopenharmony_ci	old_sighandler2 = SAFE_SIGNAL(SIGUSR2, sighandler);
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci	/* Initially no signal should be pending */
80f08c3bdfSopenharmony_ci	sigset_t pending;
81f08c3bdfSopenharmony_ci	sigemptyset(&pending);
82f08c3bdfSopenharmony_ci	TEST(tested_sigpending(&pending));
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci	for (i = 1; i < SIGMAX; ++i)
85f08c3bdfSopenharmony_ci		if (sigismember(&pending, i))
86f08c3bdfSopenharmony_ci			tst_brk(TFAIL,
87f08c3bdfSopenharmony_ci				"initialization failed: no signal should be pending by now");
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ci	/* raise a signal */
90f08c3bdfSopenharmony_ci	if (raise(SIGUSR1))
91f08c3bdfSopenharmony_ci		tst_brk(TBROK, "raising SIGUSR1 failed");
92f08c3bdfSopenharmony_ci	if (sighandler_counter > 0)
93f08c3bdfSopenharmony_ci		tst_brk(TFAIL,
94f08c3bdfSopenharmony_ci			"signal handler is not (yet) supposed to be called");
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci	/* now we should have exactly one pending signal (SIGUSR1) */
97f08c3bdfSopenharmony_ci	sigemptyset(&pending);
98f08c3bdfSopenharmony_ci	TEST(tested_sigpending(&pending));
99f08c3bdfSopenharmony_ci	for (i = 1; i < SIGMAX; ++i)
100f08c3bdfSopenharmony_ci		if ((i == SIGUSR1) != sigismember(&pending, i))
101f08c3bdfSopenharmony_ci			tst_brk(TFAIL, "only SIGUSR1 should be pending by now");
102f08c3bdfSopenharmony_ci
103f08c3bdfSopenharmony_ci	/* raise another signal */
104f08c3bdfSopenharmony_ci	if (raise(SIGUSR2))
105f08c3bdfSopenharmony_ci		tst_brk(TBROK, "raising SIGUSR2 failed");
106f08c3bdfSopenharmony_ci	if (sighandler_counter > 0)
107f08c3bdfSopenharmony_ci		tst_brk(TFAIL,
108f08c3bdfSopenharmony_ci			"signal handler is not (yet) supposed to be called");
109f08c3bdfSopenharmony_ci
110f08c3bdfSopenharmony_ci	/* now we should have exactly two pending signals (SIGUSR1, SIGUSR2) */
111f08c3bdfSopenharmony_ci	sigemptyset(&pending);
112f08c3bdfSopenharmony_ci	TEST(tested_sigpending(&pending));
113f08c3bdfSopenharmony_ci	for (i = 1; i < SIGMAX; ++i)
114f08c3bdfSopenharmony_ci		if ((i == SIGUSR1 || i == SIGUSR2) != sigismember(&pending, i))
115f08c3bdfSopenharmony_ci			tst_brk(TFAIL,
116f08c3bdfSopenharmony_ci				"only SIGUSR1, SIGUSR2 should be pending by now");
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci	tst_res(TPASS, "basic sigpending test successful");
119f08c3bdfSopenharmony_ci
120f08c3bdfSopenharmony_ci	/* reinstate old mask */
121f08c3bdfSopenharmony_ci	if (sigprocmask(SIG_SETMASK, &old_mask, NULL))
122f08c3bdfSopenharmony_ci		tst_brk(TBROK, "sigprocmask failed");
123f08c3bdfSopenharmony_ci
124f08c3bdfSopenharmony_ci	/* at this time the signal handler has been called, once for each signal */
125f08c3bdfSopenharmony_ci	if (sighandler_counter != 2)
126f08c3bdfSopenharmony_ci		tst_brk(TFAIL,
127f08c3bdfSopenharmony_ci			"signal handler has not been called for each signal");
128f08c3bdfSopenharmony_ci
129f08c3bdfSopenharmony_ci	/* reinstate the original signal handlers */
130f08c3bdfSopenharmony_ci	SAFE_SIGNAL(SIGUSR1, old_sighandler1);
131f08c3bdfSopenharmony_ci	SAFE_SIGNAL(SIGUSR2, old_sighandler2);
132f08c3bdfSopenharmony_ci}
133f08c3bdfSopenharmony_ci
134f08c3bdfSopenharmony_cistatic void test_efault_on_invalid_sigset(void)
135f08c3bdfSopenharmony_ci{
136f08c3bdfSopenharmony_ci	/* set sigset to point to an invalid location */
137f08c3bdfSopenharmony_ci	sigset_t *sigset = tst_get_bad_addr(NULL);
138f08c3bdfSopenharmony_ci
139f08c3bdfSopenharmony_ci	TEST(tested_sigpending(sigset));
140f08c3bdfSopenharmony_ci
141f08c3bdfSopenharmony_ci	/* check return code */
142f08c3bdfSopenharmony_ci	if (TST_RET == -1) {
143f08c3bdfSopenharmony_ci		if (TST_ERR != EFAULT) {
144f08c3bdfSopenharmony_ci			tst_res(TFAIL | TTERRNO,
145f08c3bdfSopenharmony_ci				"syscall failed with wrong errno, expected errno=%d, got %d",
146f08c3bdfSopenharmony_ci				EFAULT, TST_ERR);
147f08c3bdfSopenharmony_ci		} else {
148f08c3bdfSopenharmony_ci			tst_res(TPASS | TTERRNO, "expected failure");
149f08c3bdfSopenharmony_ci		}
150f08c3bdfSopenharmony_ci	} else {
151f08c3bdfSopenharmony_ci		tst_res(TFAIL,
152f08c3bdfSopenharmony_ci			"syscall failed, expected return value=-1, got %ld",
153f08c3bdfSopenharmony_ci			TST_RET);
154f08c3bdfSopenharmony_ci	}
155f08c3bdfSopenharmony_ci}
156f08c3bdfSopenharmony_ci
157f08c3bdfSopenharmony_cistatic void run(void)
158f08c3bdfSopenharmony_ci{
159f08c3bdfSopenharmony_ci	sigpending_info();
160f08c3bdfSopenharmony_ci	test_sigpending();
161f08c3bdfSopenharmony_ci	test_efault_on_invalid_sigset();
162f08c3bdfSopenharmony_ci}
163f08c3bdfSopenharmony_ci
164f08c3bdfSopenharmony_cistatic struct tst_test test = {
165f08c3bdfSopenharmony_ci	.test_all = run,
166f08c3bdfSopenharmony_ci	.test_variants = 3,
167f08c3bdfSopenharmony_ci};
168