1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <signal.h>
17#include <errno.h>
18#include <string.h>
19#include "stdbool.h"
20#include "syscall.h"
21#include "pthread_impl.h"
22#include "libc.h"
23#include "lock.h"
24#include "ksigaction.h"
25
26#define DEFAULT_SIG_NUM 64
27#define SIGNO2SET(s)            ((sigset_t)1 << (s))
28#define NULL_SIGNAL_SET         ((sigset_t)0x00000000)
29#define SET_BIT(bitmap, pos)    (bitmap |= (1u << pos))
30#define CLEAR_BIT(bitmap, pos)  (bitmap &= ~(1u << pos))
31#define CHECK_BIT(bitmap, pos)  ((bitmap & (1u << pos)) ? 1 : 0)
32#define SIG_FLAG_NOIGNORE 1
33
34struct sigactq {
35	struct sigaction act;
36	bool	ign_flag;
37	unsigned char   signo;
38	unsigned char   sigmask;
39	unsigned char   reserve[2];
40};
41typedef struct sigactq sigactq_t;
42
43typedef void (*sa_sighandler_t)(int);
44typedef struct sigaction sigaction_t;
45
46static sigactq_t g_sig_arr[DEFAULT_SIG_NUM];
47static pthread_spinlock_t sig_lite_lock;
48
49struct sig_default_act {
50	unsigned char singNo;
51	unsigned char flag;
52	sa_sighandler_t action;
53};
54
55static void __sig_core(int signo);
56static void __sig_kill(int signo);
57static void __sig_cont(int signo);
58static void __sig_stop(int signo);
59static void __sig_ignore(int signo);
60static const struct sig_default_act sig_default_action[] = {
61	{SIGHUP, 0, __sig_kill},
62	{SIGINT, 0, __sig_kill},
63	{SIGQUIT, 0, __sig_core},
64	{SIGILL, 0, __sig_core},
65	{SIGTRAP, 0, __sig_core},
66	{SIGABRT, 0, __sig_core},
67	{SIGBUS, 0, __sig_core},
68	{SIGFPE, 0, __sig_core},
69	{SIGKILL, SIG_FLAG_NOIGNORE, __sig_kill},
70	{SIGUSR1, 0, __sig_kill},
71	{SIGSEGV, 0, __sig_core},
72	{SIGUSR2, 0, __sig_kill},
73	{SIGPIPE, 0, __sig_kill},
74	{SIGALRM, 0, __sig_kill},
75	{SIGTERM, 0, __sig_kill},
76	{SIGSTKFLT, 0, __sig_kill},
77	{SIGCHLD, 0, __sig_ignore},
78	{SIGCONT, SIG_FLAG_NOIGNORE, __sig_cont},
79	{SIGSTOP, SIG_FLAG_NOIGNORE, __sig_stop},
80	{SIGTSTP, 0, __sig_stop},
81	{SIGTTIN, 0, __sig_stop},
82	{SIGTTOU, 0, __sig_stop},
83	{SIGURG, 0, __sig_ignore},
84	{SIGXCPU, 0, __sig_core},
85	{SIGXFSZ, 0, __sig_core},
86	{SIGVTALRM, 0, __sig_kill},
87	{SIGPROF, 0, __sig_kill},
88	{SIGWINCH, 0, __sig_ignore},
89	{SIGIO, 0, __sig_kill},
90	{SIGPWR, 0, __sig_kill},
91	{SIGSYS, 0, __sig_ignore},
92	{32, 0, __sig_ignore},
93	{33, 0, __sig_ignore},
94	{34, 0, __sig_ignore},
95	{35, 0, __sig_ignore},
96	{36, 0, __sig_ignore},
97	{37, 0, __sig_ignore},
98	{38, 0, __sig_ignore},
99	{39, 0, __sig_ignore},
100	{40, 0, __sig_ignore},
101	{41, 0, __sig_ignore},
102	{42, 0, __sig_ignore},
103	{43, 0, __sig_ignore},
104	{44, 0, __sig_ignore},
105	{45, 0, __sig_ignore},
106	{46, 0, __sig_ignore},
107	{47, 0, __sig_ignore},
108	{48, 0, __sig_ignore},
109	{49, 0, __sig_ignore},
110	{50, 0, __sig_ignore},
111	{51, 0, __sig_ignore},
112	{52, 0, __sig_ignore},
113	{53, 0, __sig_ignore},
114	{54, 0, __sig_ignore},
115	{55, 0, __sig_ignore},
116	{56, 0, __sig_ignore},
117	{57, 0, __sig_ignore},
118	{58, 0, __sig_ignore},
119	{59, 0, __sig_ignore},
120	{60, 0, __sig_ignore},
121	{61, 0, __sig_ignore},
122	{62, 0, __sig_ignore},
123	{63, 0, __sig_ignore},
124	{64, 0, __sig_ignore},
125};
126
127static void __sig_core(int signo)
128{
129	exit(-1);
130}
131
132static void __sig_kill(int signo)
133{
134	exit(-1);
135}
136
137static void __sig_cont(int signo)
138{
139	return;
140}
141
142static void __sig_stop(int signo)
143{
144    return;
145}
146
147static void __sig_ignore(int signo)
148{
149    return;
150}
151
152static sigactq_t *__sig_find_action(int sig)
153{
154	int i;
155
156	for (i = 0; i < sizeof(sig_default_action) / sizeof(struct sig_default_act); i++) {
157		if (g_sig_arr[i].signo == sig) {
158			return (g_sig_arr + i);
159		}
160	}
161}
162
163static void __sig_copy_sigaction(sigaction_t *src, sigaction_t *dst)
164{
165	dst->sa_handler = src->sa_handler;
166	dst->sa_mask = src->sa_mask;
167	dst->sa_flags = src->sa_flags;
168}
169
170static int __sig_cannot_catche(int sig, sa_sighandler_t handler)
171{
172	int i;
173
174	for (i = 0; i < sizeof(sig_default_action) / sizeof(struct sig_default_act); i++) {
175		if (sig == sig_default_action[i].singNo) {
176			return (sig_default_action[i].flag == SIG_FLAG_NOIGNORE) && (handler != SIG_DFL);
177		}
178	}
179	/* This sig can be catch and ignore return false */
180	return 0;
181}
182
183static void __sig_operation(unsigned int receivedSigno)
184{
185	int i;
186	sigset_t mask, oldmask;
187
188	sigemptyset(&mask);
189	sigemptyset(&oldmask);
190
191	for (i = 0; i < sizeof(sig_default_action) / sizeof(struct sig_default_act); i++) {
192		if (!g_sig_arr[i].ign_flag && g_sig_arr[i].signo == receivedSigno && g_sig_arr[i].act.sa_handler) {
193			sigaddset(&mask, receivedSigno);
194			sigprocmask(SIG_BLOCK, &mask, &oldmask);
195			sigprocmask(SIG_BLOCK, &g_sig_arr[i].act.sa_mask, NULL);
196			(*g_sig_arr[i].act.sa_handler)(g_sig_arr[i].signo);
197			sigprocmask(SIG_SETMASK, &oldmask, NULL);
198			return;
199		}
200	}
201}
202
203void arm_signal_process(unsigned int receivedSig)
204{
205	__sig_operation(receivedSig);
206}
207
208static void __sig_add_def_action()
209{
210	int i;
211
212	for (i = 0; i < sizeof(sig_default_action) / sizeof(struct sig_default_act); i++) {
213		g_sig_arr[i].signo = (unsigned char)sig_default_action[i].singNo;
214		g_sig_arr[i].act.sa_handler = sig_default_action[i].action;
215		sigemptyset(&g_sig_arr[i].act.sa_mask);
216		g_sig_arr[i].act.sa_flags = sig_default_action[i].flag;
217		g_sig_arr[i].ign_flag = false;
218	}
219}
220
221static sa_sighandler_t __sig_find_def_action(unsigned char signo)
222{
223	int i;
224
225	for (i = 0; i < sizeof(sig_default_action) / sizeof(struct sig_default_act); i++) {
226		if (signo == sig_default_action[i].singNo) {
227			return sig_default_action[i].action;
228		}
229	}
230	return NULL;
231}
232
233static int __sig_dfl_opr(int sig, sigactq_t *sigact, const sigaction_t *act)
234{
235	sa_sighandler_t def_handler = NULL;
236
237	def_handler = __sig_find_def_action(sig);
238
239	if (def_handler != NULL) {
240		/* Replace it from signal action queue */
241		sigact->act.sa_handler = def_handler;
242		sigact->act.sa_mask = act->sa_mask;
243		sigact->act.sa_flags = act->sa_flags;
244	}
245	return 0;
246}
247
248static int __sig_action_opr(int sig, const sigaction_t *act, sigaction_t *oact)
249{
250	int ret = 0;
251	sa_sighandler_t handler = NULL;
252	sigactq_t *sigact = NULL;
253
254	if (act == NULL) return -EINVAL;
255
256	if (sig < SIGHUP || sig > (_NSIG - 1)) return -EINVAL;
257
258	handler = act->sa_handler;
259	/* Skip sig that can not be catched */
260	if (__sig_cannot_catche(sig, handler)) return -EINVAL;
261
262	pthread_spin_lock(&sig_lite_lock);
263	sigact = __sig_find_action(sig);
264	if (sigact && oact) __sig_copy_sigaction(&sigact->act, oact);
265
266	sigact->ign_flag = false;
267
268	if (handler == SIG_IGN && sigact) {
269		sigact->ign_flag = true;
270	} else if (handler == SIG_DFL) {
271		ret = __sig_dfl_opr(sig, sigact, act);
272	} else {
273		sigact->act.sa_handler = handler;
274		sigact->act.sa_mask = act->sa_mask;
275		sigact->act.sa_flags = act->sa_flags;
276	}
277
278	pthread_spin_unlock(&sig_lite_lock);
279	return ret;
280}
281
282void __sig_init(void)
283{
284	signal(SIGSYS, arm_do_signal);
285	pthread_spin_init(&sig_lite_lock, 0);
286	__sig_add_def_action();
287}
288
289static int unmask_done;
290static unsigned long handler_set[_NSIG / (8 * sizeof(long))];
291
292void __get_handler_set(sigset_t *set)
293{
294	memcpy(set, handler_set, sizeof handler_set);
295}
296
297volatile int __eintr_valid_flag;
298
299int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old)
300{
301	sigaction_t ksa, ksa_old;
302	int r = 0;
303
304	if (sa) {
305		if ((uintptr_t)sa->sa_handler > 1UL) {
306			a_or_l(handler_set + (sig - 1) / (8 * sizeof(long)),
307				1UL<<(sig - 1) % (8 * sizeof(long)));
308
309			/* If pthread_create has not yet been called,
310			 * implementation-internal signals might not
311			 * yet have been unblocked. They must be
312			 * unblocked before any signal handler is
313			 * installed, so that an application cannot
314			 * receive an illegal sigset_t (with them
315			 * blocked) as part of the ucontext_t passed
316			 * to the signal handler. */
317			if (!libc.threaded && !unmask_done) {
318				__syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,
319					SIGPT_SET, 0, _NSIG/8);
320				unmask_done = 1;
321			}
322
323			if (!(sa->sa_flags & SA_RESTART)) {
324				a_store(&__eintr_valid_flag, 1);
325			}
326		}
327		ksa.sa_handler = sa->sa_handler;
328		ksa.sa_flags = sa->sa_flags;
329#ifdef SA_RESTORER
330		ksa.sa_flags |= SA_RESTORER;
331		ksa.sa_restorer = (sa->sa_flags & SA_SIGINFO) ? __restore_rt : __restore;
332#endif
333		memcpy(&ksa.sa_mask, &sa->sa_mask, _NSIG / 8);
334	}
335
336	if (sig == SIGSYS) {
337		return syscall(SYS_rt_sigaction, sig, sa ? &ksa : 0, old?&ksa_old:0, _NSIG / 8);
338	} else {
339		r = __sig_action_opr(sig, (const sigaction_t*)sa ? &ksa : 0, (sigaction_t*)old?&ksa_old:0);
340	}
341	if (old && !r) {
342		old->sa_handler = ksa_old.sa_handler;
343		old->sa_flags = ksa_old.sa_flags;
344		memcpy(&old->sa_mask, &ksa_old.sa_mask, _NSIG / 8);
345	}
346	return __syscall_ret(r);
347}
348
349int __sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old)
350{
351	unsigned long set[_NSIG/(8*sizeof(long))];
352
353	if (sig-32U < 3 || sig-1U >= _NSIG-1) {
354		errno = EINVAL;
355		return -1;
356	}
357
358	/* Doing anything with the disposition of SIGABRT requires a lock,
359	 * so that it cannot be changed while abort is terminating the
360	 * process and so any change made by abort can't be observed. */
361	if (sig == SIGABRT) {
362		__block_all_sigs(&set);
363		LOCK(__abort_lock);
364	}
365	int r = __libc_sigaction(sig, sa, old);
366	if (sig == SIGABRT) {
367		UNLOCK(__abort_lock);
368		__restore_sigs(&set);
369	}
370	return r;
371}
372
373weak_alias(__sigaction, sigaction);
374