1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* IBM Corporation
3 * 01/02/2003 Port to LTP avenkat@us.ibm.com
4 * 06/30/2001 Port to Linux nsharoff@us.ibm.com
5 *
6 * Copyright (c) International Business Machines Corp., 2002
7 * Copyright (c) Cyril Hrubis <chrubis@suse.cz> 2014
8 *
9 * Test checks that when a child is killed by its parent with sig, it
10 * returns the correct values(sig and core dump bit) to the waiting parent.
11 *
12 * RESTRICTIONS
13 * The ulimit for core file size must be greater than 0.
14 */
15
16 #define _GNU_SOURCE
17 #include <errno.h>
18 #include <sys/types.h>
19 #include <signal.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <sys/wait.h>
23 #include <sys/resource.h>
24
25 #include "tst_test.h"
26
27 static struct tcase {
28 int sig;
29 int dumps_core;
30 } tcases[] = {
31 {SIGHUP, 0},
32 {SIGINT, 0},
33 {SIGQUIT, 1},
34 {SIGILL, 1},
35 {SIGTRAP, 1},
36 {SIGABRT, 1},
37 {SIGIOT, 1},
38 {SIGBUS, 1},
39 {SIGFPE, 1},
40 {SIGKILL, 0},
41 {SIGUSR1, 0},
42 {SIGSEGV, 1},
43 {SIGUSR2, 0},
44 {SIGPIPE, 0},
45 {SIGALRM, 0},
46 {SIGTERM, 0},
47 #ifdef SIGSTKFLT
48 {SIGSTKFLT, 0},
49 #endif
50 {SIGXCPU, 1},
51 {SIGXFSZ, 1},
52 {SIGVTALRM, 0},
53 {SIGPROF, 0},
54 {SIGIO, 0},
55 {SIGPWR, 0},
56 {SIGSYS, 1},
57 };
58
verify_kill(unsigned int n)59 static void verify_kill(unsigned int n)
60 {
61 int core;
62 pid_t pid, npid;
63 int nsig, status;
64 struct tcase *tc = &tcases[n];
65
66 pid = SAFE_FORK();
67 if (!pid)
68 pause();
69
70 SAFE_KILL(pid, tc->sig);
71 npid = SAFE_WAIT(&status);
72
73 if (npid != pid) {
74 tst_res(TFAIL, "wait() returned %d, expected %d", npid, pid);
75 return;
76 }
77
78 nsig = WTERMSIG(status);
79 core = WCOREDUMP(status);
80
81 if (tc->dumps_core) {
82 if (!core) {
83 tst_res(TFAIL, "core dump bit not set for %s", tst_strsig(tc->sig));
84 return;
85 }
86 } else {
87 if (core) {
88 tst_res(TFAIL, "core dump bit set for %s", tst_strsig(tc->sig));
89 return;
90 }
91 }
92
93 if (nsig != tc->sig) {
94 tst_res(TFAIL, "wait: unexpected signal %d returned, expected %d", nsig, tc->sig);
95 return;
96 }
97
98 tst_res(TPASS, "signal %-16s%s", tst_strsig(tc->sig),
99 tc->dumps_core ? " dumped core" : "");
100 }
101
102 #define MIN_RLIMIT_CORE (512 * 1024)
103
setup(void)104 static void setup(void)
105 {
106 struct rlimit rlim;
107
108 SAFE_GETRLIMIT(RLIMIT_CORE, &rlim);
109
110 if (rlim.rlim_max < MIN_RLIMIT_CORE) {
111 if (geteuid() != 0) {
112 tst_brk(TCONF, "hard limit(%lu)less than MIN_RLIMT_CORE(%i)",
113 rlim.rlim_max, MIN_RLIMIT_CORE);
114 }
115 tst_res(TINFO, "Raising rlim_max to %i", MIN_RLIMIT_CORE);
116 rlim.rlim_max = MIN_RLIMIT_CORE;
117 }
118 if (rlim.rlim_cur < MIN_RLIMIT_CORE) {
119 tst_res(TINFO, "Adjusting RLIMIT_CORE to %i", MIN_RLIMIT_CORE);
120 rlim.rlim_cur = MIN_RLIMIT_CORE;
121 SAFE_SETRLIMIT(RLIMIT_CORE, &rlim);
122 }
123 }
124
125 static struct tst_test test = {
126 .needs_tmpdir = 1,
127 .forks_child = 1,
128 .setup = setup,
129 .tcnt = ARRAY_SIZE(tcases),
130 .test = verify_kill,
131 };
132