1/*
2 *
3 *   Copyright (c) International Business Machines  Corp., 2001
4 *
5 *   This program is free software;  you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation; either version 2 of the License, or
8 *   (at your option) any later version.
9 *
10 *   This program is distributed in the hope that it will be useful,
11 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13 *   the GNU General Public License for more details.
14 *
15 *   You should have received a copy of the GNU General Public License
16 *   along with this program;  if not, write to the Free Software
17 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20/*
21 * Test Name: sigalstack02
22 *
23 * Test Description:
24 *  Verify that,
25 *   1. sigaltstack() fails and sets errno to EINVAL when "ss_flags" field
26 *      pointed to by 'ss' contains invalid flags.
27 *   2. sigaltstack() fails and sets errno to ENOMEM when the size of alternate
28 *      stack area is less than MINSIGSTKSZ.
29 *
30 * Expected Result:
31 *  sigaltstack() should fail with return value -1 and set expected errno.
32 *
33 * Algorithm:
34 *  Setup:
35 *   Setup signal handling.
36 *   Create temporary directory.
37 *   Pause for SIGUSR1 if option specified.
38 *
39 *  Test:
40 *   Loop if the proper options are given.
41 *   Execute system call
42 *   Check return code, if system call failed (return=-1)
43 *	if errno set == expected errno
44 *		Issue sys call fails with expected return value and errno.
45 *	Otherwise,
46 *		Issue sys call fails with unexpected errno.
47 *   Otherwise,
48 *	Issue sys call returns unexpected value.
49 *
50 *  Cleanup:
51 *   Print errno log and/or timing stats if options given
52 *   Delete the temporary directory(s)/file(s) created.
53 *
54 * Usage:  <for command-line>
55 *  sigaltstack02 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t]
56 *	where,  -c n : Run n copies concurrently.
57 *		-e   : Turn on errno logging.
58 *		-f   : Turn off functionality Testing.
59 *		-i n : Execute test n times.
60 *		-I x : Execute test for x seconds.
61 *		-P x : Pause for x seconds between iterations.
62 *		-t   : Turn on syscall timing.
63 *
64 * History
65 *	07/2001 John George
66 *		-Ported
67 *
68 * Restrictions:
69 *  This test should be executed by super-user (root) only.
70 */
71
72#include <stdio.h>
73#include <sys/types.h>
74#include <unistd.h>
75#include <signal.h>
76#include <string.h>
77#include <ucontext.h>
78#include <errno.h>
79
80#include "test.h"
81
82#define INVAL_FLAGS	9999
83
84char *TCID = "sigaltstack02";
85int TST_TOTAL = 2;
86
87stack_t sigstk;			/* signal stack storing struct. */
88
89void setup(void);			/* Main setup function of test */
90void cleanup(void);			/* cleanup function for the test */
91
92struct test_case_t {		/* test case struct. to hold diff. test.conds */
93	int flag;
94	int size;
95	char *desc;
96	int exp_errno;
97} Test_cases[] = {
98	{
99	INVAL_FLAGS, SIGSTKSZ, "Invalid Flag value", EINVAL},
100	/* use value low enough for all kernel versions
101	 * avoid using MINSIGSTKSZ defined by glibc as it could be different
102	 * from the one in kernel ABI
103	 */
104	{
105	0, (2048 - 1), "alternate stack is < MINSIGSTKSZ", ENOMEM},
106	{
107	0, 0, NULL, 0}
108};
109
110int main(int ac, char **av)
111{
112	int lc;
113	char *test_desc;	/* test specific error message */
114	int ind;		/* counter to test different test conditions */
115
116	tst_parse_opts(ac, av, NULL, NULL);
117
118	setup();
119
120	for (lc = 0; TEST_LOOPING(lc); lc++) {
121
122		tst_count = 0;
123
124		for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
125			sigstk.ss_size = Test_cases[ind].size;
126			sigstk.ss_flags = Test_cases[ind].flag;
127			test_desc = Test_cases[ind].desc;
128
129			/* Verify sigaltstack() fails and sets errno */
130			TEST(sigaltstack(&sigstk, NULL));
131
132			/* Check return code from sigaltstack() */
133			if (TEST_RETURN == -1) {
134				if (TEST_ERRNO ==
135				    Test_cases[ind].exp_errno) {
136					tst_resm(TPASS, "stgaltstack() "
137						 "fails, %s, errno:%d",
138						 test_desc, TEST_ERRNO);
139				} else {
140					tst_resm(TFAIL, "sigaltstack() "
141						 "fails, %s, errno:%d, "
142						 "expected errno:%d",
143						 test_desc, TEST_ERRNO,
144						 Test_cases
145						 [ind].exp_errno);
146				}
147			} else {
148				tst_resm(TFAIL, "sigaltstack() returned %ld, "
149					 "expected -1, errno:%d", TEST_RETURN,
150					 Test_cases[ind].exp_errno);
151			}
152		}
153		tst_count++;	/* incr. TEST_LOOP counter */
154	}
155
156	cleanup();
157	tst_exit();
158
159}
160
161/*
162 * void
163 * setup() - performs all ONE TIME setup for this test.
164 * Allocate memory for the alternative stack.
165 */
166void setup(void)
167{
168
169	tst_sig(FORK, DEF_HANDLER, cleanup);
170
171	TEST_PAUSE;
172
173	/* Allocate memory for the alternate stack */
174	if ((sigstk.ss_sp = malloc(SIGSTKSZ)) == NULL) {
175		tst_brkm(TFAIL, cleanup,
176			 "could not allocate memory for the alternate stack");
177	}
178}
179
180/*
181 * void
182 * cleanup() - performs all ONE TIME cleanup for this test at
183 *             completion or premature exit.
184 *  Free the memory allocated for alternate stack.
185 */
186void cleanup(void)
187{
188
189	free(sigstk.ss_sp);
190
191}
192