1 /* 2 * Copyright (c) International Business Machines Corp., 2003. 3 * Copyright (c) 2012 Wanlong Gao <gaowanlong (at) 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 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 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 110 static int do_child(void) 111 { 112 return 0; 113 } 114 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 */ 124 static void sigusr2_handler(int sig) 125 { 126 if (child_pid != 0) 127 fail = TRUE; 128 } 129