1 /*
2 * Copyright (c) International Business Machines Corp., 2003.
3 * Copyright (c) 2012 Wanlong Gao <gaowanlong@cn.fujitsu.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 */
18 /*
19 * This is a test for a glibc bug for the clone(2) system call.
20 */
21
22 #if defined UCLINUX && !__THROW
23 /* workaround for libc bug */
24 #define __THROW
25 #endif
26
27 #include <errno.h>
28 #include <sched.h>
29 #include <sys/wait.h>
30 #include "test.h"
31 #include "clone_platform.h"
32
33 #define TRUE 1
34 #define FALSE 0
35
36 static void setup();
37 static int do_child();
38
39 char *TCID = "clone07";
40 int TST_TOTAL = 1;
41
42 static void sigsegv_handler(int);
43 static void sigusr2_handler(int);
44 static int child_pid;
45 static int fail = FALSE;
46
main(int ac,char ** av)47 int main(int ac, char **av)
48 {
49
50 int lc, status;
51 void *child_stack;
52
53 tst_parse_opts(ac, av, NULL, NULL);
54
55 setup();
56
57 for (lc = 0; TEST_LOOPING(lc); lc++) {
58 tst_count = 0;
59 child_stack = malloc(CHILD_STACK_SIZE);
60 if (child_stack == NULL)
61 tst_brkm(TBROK, NULL,
62 "Cannot allocate stack for child");
63
64 child_pid = ltp_clone(SIGCHLD, do_child, NULL,
65 CHILD_STACK_SIZE, child_stack);
66
67 if (child_pid < 0)
68 tst_brkm(TBROK | TERRNO, NULL, "clone failed");
69
70 if ((wait(&status)) == -1)
71 tst_brkm(TBROK | TERRNO, NULL,
72 "wait failed, status: %d", status);
73
74 free(child_stack);
75 }
76
77 if (fail == FALSE)
78 tst_resm(TPASS,
79 "Use of return() in child did not cause SIGSEGV");
80 else
81 tst_resm(TFAIL, "Use of return() in child caused SIGSEGV");
82
83 tst_exit();
84 }
85
setup(void)86 static void setup(void)
87 {
88 struct sigaction def_act;
89 struct sigaction act;
90
91 TEST_PAUSE;
92
93 act.sa_handler = sigsegv_handler;
94 act.sa_flags = SA_RESTART;
95 sigemptyset(&act.sa_mask);
96 if ((sigaction(SIGSEGV, &act, NULL)) == -1)
97 tst_resm(TWARN | TERRNO,
98 "sigaction() for SIGSEGV failed in test_setup()");
99
100 /* Setup signal handler for SIGUSR2 */
101 def_act.sa_handler = sigusr2_handler;
102 def_act.sa_flags = SA_RESTART | SA_RESETHAND;
103 sigemptyset(&def_act.sa_mask);
104
105 if ((sigaction(SIGUSR2, &def_act, NULL)) == -1)
106 tst_resm(TWARN | TERRNO,
107 "sigaction() for SIGUSR2 failed in test_setup()");
108 }
109
do_child(void)110 static int do_child(void)
111 {
112 return 0;
113 }
114
sigsegv_handler(int sig)115 static void sigsegv_handler(int sig)
116 {
117 if (child_pid == 0) {
118 kill(getppid(), SIGUSR2);
119 _exit(42);
120 }
121 }
122
123 /* sig_default_handler() - Default handler for parent */
sigusr2_handler(int sig)124 static void sigusr2_handler(int sig)
125 {
126 if (child_pid != 0)
127 fail = TRUE;
128 }
129