• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 <sigchain.h>
17 #include <locale.h>
18 #include <pthread.h>
19 #include <errno.h>
20 #include <threads.h>
21 #include <hilog_adapter.h>
22 #include <stdlib.h>
23 #include <errno.h>
24 #include "syscall.h"
25 
26 extern int __libc_sigaction(int sig, const struct sigaction *restrict sa,
27                             struct sigaction *restrict old);
28 
29 #define SIG_CHAIN_KEY_VALUE_1 1
30 #define SIGNAL_CHAIN_SPECIAL_ACTION_MAX 2
31 
32 #define SIGCHAIN_LOG_DOMAIN 0xD003F00
33 #define SIGCHAIN_LOG_TAG "SIGCHAIN"
34 
35 #if (defined(OHOS_ENABLE_PARAMETER) || defined(ENABLE_MUSL_LOG))
36 #define SIGCHAIN_PRINT_ERROR(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_ERROR, \
37     SIGCHAIN_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__))
38 #define SIGCHAIN_PRINT_INFO(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_INFO, \
39     SIGCHAIN_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__))
40 #define SIGCHAIN_PRINT_DEBUG(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_DEBUG, \
41     SIGCHAIN_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__))
42 #define SIGCHAIN_LOG_FATAL(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_FATAL, \
43     SIGCHAIN_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__))
44 #else
45 #define SIGCHAIN_PRINT_ERROR(...)
46 #define SIGCHAIN_PRINT_INFO(...)
47 #define SIGCHAIN_PRINT_DEBUG(...)
48 #define SIGCHAIN_LOG_FATAL(...)
49 #endif
50 
51 #define SIGCHAIN_PRINT_FATAL(...)  do {                    \
52     SIGCHAIN_LOG_FATAL(__VA_ARGS__);                      \
53     abort();                                               \
54 } while(0)
55 
56 struct sc_signal_chain {
57     bool marked;
58     struct sigaction sig_action;
59     struct signal_chain_action sca_special_actions[SIGNAL_CHAIN_SPECIAL_ACTION_MAX];
60 };
61 
62 /* Signal chain set, from 0 to 63. */
63 static struct sc_signal_chain sig_chains[_NSIG - 1];
64 /* static thread Keyword */
65 static pthread_key_t g_sigchain_key;
66 /* This is once flag! */
67 static once_flag g_flag = ONCE_FLAG_INIT;
68 
69 /**
70   * @brief Create the thread key
71   * @retval void
72   */
create_pthread_key(void)73 static void create_pthread_key(void)
74 {
75     SIGCHAIN_PRINT_INFO("%{public}s create the thread key!", __func__);
76     int rc = pthread_key_create(&g_sigchain_key, NULL);
77     if (rc != 0) {
78         SIGCHAIN_PRINT_FATAL("%{public}s failed to create sigchain pthread key, rc:%{public}d",
79                 __func__,  rc);
80     }
81 }
82 
83 /**
84   * @brief Get the key of the signal thread.
85   * @retval int32_t, the value of the sigchain key.
86   */
get_handling_signal_key()87 static pthread_key_t get_handling_signal_key()
88 {
89     call_once(&g_flag, create_pthread_key);
90     return g_sigchain_key;
91 }
92 
93 /**
94   * @brief Get the value of the sigchain key
95   * @retval bool, true if set the value of the key,or false.
96   */
get_handling_signal()97 static bool get_handling_signal()
98 {
99     void *result = pthread_getspecific(get_handling_signal_key());
100     return result == NULL ? false : true;
101 }
102 
103 /**
104   * @brief Set the value of the sigchain key
105   * @param[in] value, the value of the sigchain key
106   * @retval void.
107   */
set_handling_signal(bool value)108 static void set_handling_signal(bool value)
109 {
110     pthread_setspecific(get_handling_signal_key(),
111                         (void *)((uintptr_t)(value)));
112 }
113 
114 /**
115   * @brief Set the mask of the system. Its prototype comes from pthread_sigmask.
116   * @param[in] how, the value of the mask operation .
117   * @param[in] set, the new value of the sigset.
118   * @param[in] old, the old value of the sigset.
119   */
sigchain_sigmask(int how,const sigset_t * restrict set,sigset_t * restrict old)120 static int sigchain_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict old)
121 {
122     int ret;
123     if (set && (unsigned)how - SIG_BLOCK > 2U) return EINVAL;
124     ret = -__syscall(SYS_rt_sigprocmask, how, set, old, _NSIG/8);
125     if (!ret && old) {
126         if (sizeof old->__bits[0] == 8) {
127             old->__bits[0] &= ~0x380000000ULL;
128         } else {
129             old->__bits[0] &= ~0x80000000UL;
130             old->__bits[1] &= ~0x3UL;
131         }
132     }
133     return ret;
134 }
135 
136 /**
137   * @brief Judge whether the signal is marked
138   * @param[in] signo, the value of the signal.
139   * @retval true if the signal is marked, or false.
140   */
ismarked(int signo)141 static bool ismarked(int signo)
142 {
143     return sig_chains[signo - 1].marked;
144 }
145 
146 /**
147   * @brief This is a callback function, which is registered to the kernel
148   * @param[in] signo, the value of the signal.
149   * @param[in] siginfo, the information of the signal.
150   * @param[in] ucontext_raw, the context of the signal.
151   * @retval void
152   */
signal_chain_handler(int signo,siginfo_t * siginfo,void * ucontext_raw)153 static void signal_chain_handler(int signo, siginfo_t* siginfo, void* ucontext_raw)
154 {
155     SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo);
156     /* First call special handler. */
157     /* If a process crashes, the sigchain'll call the corresponding  handler */
158     if (!get_handling_signal()) {
159         for (int i = 0; i < SIGNAL_CHAIN_SPECIAL_ACTION_MAX; i++) {
160             if (sig_chains[signo - 1].sca_special_actions[i].sca_sigaction == NULL) {
161                 continue;
162             }
163             /* The special handler might not return. */
164             bool noreturn = (sig_chains[signo - 1].sca_special_actions[i].sca_flags &
165                              SIGCHAIN_ALLOW_NORETURN);
166             sigset_t previous_mask;
167             sigchain_sigmask(SIG_SETMASK, &sig_chains[signo - 1].sca_special_actions[i].sca_mask,
168                             &previous_mask);
169 
170             bool previous_value = get_handling_signal();
171             if (!noreturn) {
172                 set_handling_signal(true);
173             }
174 
175             if (sig_chains[signo - 1].sca_special_actions[i].sca_sigaction(signo,
176                                                             siginfo, ucontext_raw)) {
177                 set_handling_signal(previous_value);
178                 return;
179             }
180 
181             sigchain_sigmask(SIG_SETMASK, &previous_mask, NULL);
182             set_handling_signal(previous_value);
183         }
184     }
185     /* Then Call the user's signal handler */
186     int sa_flags = sig_chains[signo - 1].sig_action.sa_flags;
187     ucontext_t* ucontext = (ucontext_t*)(ucontext_raw);
188 
189     sigset_t mask;
190     sigorset(&mask, &ucontext->uc_sigmask, &sig_chains[signo - 1].sig_action.sa_mask);
191 
192     if (!(sa_flags & SA_NODEFER)) {
193         sigaddset(&mask, signo);
194     }
195 
196     sigchain_sigmask(SIG_SETMASK, &mask, NULL);
197 
198     if ((sa_flags & SA_SIGINFO)) {
199         sig_chains[signo - 1].sig_action.sa_sigaction(signo, siginfo, ucontext_raw);
200     } else {
201         if (sig_chains[signo - 1].sig_action.sa_handler == SIG_IGN) {
202             return;
203         } else if (sig_chains[signo - 1].sig_action.sa_handler == SIG_DFL) {
204             SIGCHAIN_PRINT_DEBUG("%{public}s SIG_DFL handler for signal: %{public}d", __func__, signo);
205             remove_all_special_handler(signo);
206             if (__syscall(SYS_rt_tgsigqueueinfo, __syscall(SYS_getpid), __syscall(SYS_gettid), signo, siginfo) != 0) {
207                 SIGCHAIN_PRINT_ERROR("Failed to rethrow sig(%{public}d), errno(%{public}d).", signo, errno);
208             } else {
209                 SIGCHAIN_PRINT_INFO("pid(%{public}d) rethrow sig(%{public}d).", __syscall(SYS_getpid), signo);
210             }
211         } else {
212             sig_chains[signo - 1].sig_action.sa_handler(signo);
213         }
214     }
215 
216     return;
217 }
218 
219 /**
220   * @brief Register the signal chain with the kernel if needed
221   * @param[in] signo, the value of the signal.
222   * @retval void
223   */
sigchain_register(int signo)224 static void sigchain_register(int signo)
225 {
226     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
227     struct sigaction signal_action = {};
228     sigfillset(&signal_action.sa_mask);
229 
230     signal_action.sa_sigaction = signal_chain_handler;
231     signal_action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
232     __libc_sigaction(signo, &signal_action, &sig_chains[signo - 1].sig_action);
233 }
234 
235 /**
236   * @brief Unregister the signal from sigchain, register the signal's user handler with the kernel if needed
237   * @param[in] signo, the value of the signal.
238   * @retval void
239   */
unregister_sigchain(int signo)240 static void unregister_sigchain(int signo)
241 {
242     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
243     __libc_sigaction(signo, &sig_chains[signo - 1].sig_action, NULL);
244     sig_chains[signo - 1].marked = false;
245 }
246 
247 /**
248   * @brief Mark the signal to the sigchain.
249   * @param[in] signo, the value of the signal.
250   * @retval void
251   */
mark_signal_to_sigchain(int signo)252 static void mark_signal_to_sigchain(int signo)
253 {
254     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
255     if (!sig_chains[signo - 1].marked) {
256         sigchain_register(signo);
257         sig_chains[signo - 1].marked = true;
258     }
259 }
260 
261 /**
262   * @brief Set the action of the signal.
263   * @param[in] signo, the value of the signal.
264   * @param[in] new_sa, the new action of the signal.
265   * @retval void
266   */
setaction(int signo,const struct sigaction * restrict new_sa)267 static void setaction(int signo, const struct sigaction *restrict new_sa)
268 {
269     SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo);
270     sig_chains[signo - 1].sig_action = *new_sa;
271 }
272 
273 /**
274   * @brief Get the action of the signal.
275   * @param[in] signo, the value of the signal.
276   * @retval The current action of the signal
277   */
getaction(int signo)278 static struct sigaction getaction(int signo)
279 {
280     SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo);
281     return sig_chains[signo - 1].sig_action;
282 }
283 
284 /**
285   * @brief Add the special handler to the sigchain.
286   * @param[in] signo, the value of the signal.
287   * @param[in] sa, the action with special handler.
288   * @retval void
289   */
add_special_handler(int signo,struct signal_chain_action * sa)290 static void add_special_handler(int signo, struct signal_chain_action* sa)
291 {
292     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
293     for (int i = 0; i < SIGNAL_CHAIN_SPECIAL_ACTION_MAX; i++) {
294         if (sig_chains[signo - 1].sca_special_actions[i].sca_sigaction == NULL) {
295             sig_chains[signo - 1].sca_special_actions[i] = *sa;
296             SIGCHAIN_PRINT_INFO("%{public}s signo %{public}d is registered with special handler!", __func__, signo);
297             return;
298         }
299     }
300 
301     SIGCHAIN_PRINT_FATAL("Add too many the special handlers!");
302 }
303 
304 /**
305   * @brief Remove the special handler from the sigchain.
306   * @param[in] signo, the value of the signal.
307   * @param[in] fn, the special handler of the signal.
308   * @retval void
309   */
rm_special_handler(int signo,bool (* fn)(int,siginfo_t *,void *))310 static void rm_special_handler(int signo, bool (*fn)(int, siginfo_t*, void*))
311 {
312     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
313     int len = SIGNAL_CHAIN_SPECIAL_ACTION_MAX;
314     for (int i = 0; i < len; i++) {
315         if (sig_chains[signo - 1].sca_special_actions[i].sca_sigaction == fn) {
316             sig_chains[signo - 1].sca_special_actions[i].sca_sigaction = NULL;
317             int count = 0;
318             for (int k = 0; k < len; k++) {
319                 if (sig_chains[signo - 1].sca_special_actions[k].sca_sigaction == NULL) {
320                     count++;
321                 }
322             }
323             if (count == len) {
324                 unregister_sigchain(signo);
325             }
326             return;
327         }
328     }
329 
330     SIGCHAIN_PRINT_FATAL("%{public}s failed to remove the special handler!. signo: %{public}d",
331             __func__, signo);
332 }
333 
334 /**
335   * @brief This is an external interface,
336   *        Mark the signal to sigchain ,add the special handler to the sigchain.
337   * @param[in] signo, the value of the signal.
338   * @param[in] sa, the action with special handler.
339   * @retval void
340   */
add_special_signal_handler(int signo,struct signal_chain_action * sa)341 void add_special_signal_handler(int signo, struct signal_chain_action* sa)
342 {
343     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
344     if (signo <= 0 || signo >= _NSIG) {
345         SIGCHAIN_PRINT_FATAL("%{public}s Invalid signal %{public}d", __func__, signo);
346         return;
347     }
348 
349     // Add the special hander to the sigchain
350     add_special_handler(signo, sa);
351     mark_signal_to_sigchain(signo);
352 }
353 
354 /**
355   * @brief This is an external interface, remove the special handler from the sigchain.
356   * @param[in] signo, the value of the signal.
357   * @param[in] fn, the special handler of the signal.
358   * @retval void
359   */
remove_special_signal_handler(int signo,bool (* fn)(int,siginfo_t *,void *))360 void remove_special_signal_handler(int signo, bool (*fn)(int, siginfo_t*, void*))
361 {
362     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
363     if (signo <= 0 || signo >= _NSIG) {
364         SIGCHAIN_PRINT_FATAL("%{public}s Invalid signal %{public}d", __func__, signo);
365         return;
366     }
367 
368     if (ismarked(signo)) {
369         // remove the special handler from the sigchain.
370         rm_special_handler(signo, fn);
371     }
372 }
373 
374 /**
375   * @brief This is an external interface, remove all special handler from the sigchain.
376   * @param[in] signo, the value of the signal.
377   * @retval void
378   */
remove_all_special_handler(int signo)379 void remove_all_special_handler(int signo)
380 {
381     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
382     if (signo <= 0 || signo >= _NSIG) {
383         SIGCHAIN_PRINT_FATAL("%{public}s Invalid signal %{public}d", __func__, signo);
384         return;
385     }
386 
387     if (ismarked(signo)) {
388         // remove all special handler from the sigchain.
389         for (int i = 0; i < SIGNAL_CHAIN_SPECIAL_ACTION_MAX; i++) {
390             sig_chains[signo - 1].sca_special_actions[i].sca_sigaction = NULL;
391         }
392         unregister_sigchain(signo);
393     }
394 }
395 
396 /**
397   * @brief This is an external interface, add the special handler at the last of sigchain chains.
398   * @param[in] signo, the value of the signal.
399   * @param[in] sa, the action with special handler.
400   * @retval void
401   */
add_special_handler_at_last(int signo,struct signal_chain_action * sa)402 void add_special_handler_at_last(int signo, struct signal_chain_action* sa)
403 {
404     SIGCHAIN_PRINT_INFO("%{public}s signo: %{public}d", __func__, signo);
405     if (signo <= 0 || signo >= _NSIG) {
406         SIGCHAIN_PRINT_FATAL("%{public}s Invalid signal %{public}d", __func__, signo);
407         return;
408     }
409 
410     if (sig_chains[signo - 1].sca_special_actions[SIGNAL_CHAIN_SPECIAL_ACTION_MAX - 1].sca_sigaction == NULL) {
411         sig_chains[signo - 1].sca_special_actions[SIGNAL_CHAIN_SPECIAL_ACTION_MAX - 1] = *sa;
412         mark_signal_to_sigchain(signo);
413         return;
414     }
415 
416     SIGCHAIN_PRINT_FATAL("Add too many the special handlers at last!");
417 }
418 
419 /**
420   * @brief Intercept the signal and sigaction.
421   * @param[in] signo, the value of the signal.
422   * @param[in] sa, the new action with the signal handler.
423   * @param[out] old, the old action with the signal handler.
424   * @retval true if the signal if intercepted, or false.
425   */
intercept_sigaction(int signo,const struct sigaction * restrict sa,struct sigaction * restrict old)426 bool intercept_sigaction(int signo, const struct sigaction *restrict sa,
427                          struct sigaction *restrict old)
428 {
429     SIGCHAIN_PRINT_DEBUG("%{public}s signo: %{public}d", __func__, signo);
430     if (signo <= 0 || signo >= _NSIG) {
431         SIGCHAIN_PRINT_ERROR("%{public}s Invalid signal %{public}d", __func__, signo);
432         return false;
433     }
434 
435     if (ismarked(signo)) {
436         struct sigaction saved_action = getaction(signo);
437 
438         if (sa != NULL) {
439             setaction(signo, sa);
440         }
441         if (old != NULL) {
442             *old = saved_action;
443         }
444         return true;
445     }
446 
447     return false;
448 }
449 
450 /**
451   * @brief Intercept the pthread_sigmask.
452   * @param[in] how, the value of the mask operation .
453   * @param[out] set, the value of the sigset.
454   * @retval void.
455   */
intercept_pthread_sigmask(int how,sigset_t * restrict set)456 void intercept_pthread_sigmask(int how, sigset_t *restrict set)
457 {
458     SIGCHAIN_PRINT_DEBUG("%{public}s how: %{public}d", __func__, how);
459     // Forward directly to the system mask When this sigchain is handling a signal.
460     if (get_handling_signal()) {
461         return;
462     }
463 
464     sigset_t tmpset;
465     if (set != NULL) {
466         tmpset = *set;
467         if (how == SIG_BLOCK || how == SIG_SETMASK) {
468             for (int i = 1; i < _NSIG; ++i) {
469                 if (ismarked(i) && sigismember(&tmpset, i)) {
470                     sigdelset(&tmpset, i);
471                 }
472             }
473         }
474         *set = tmpset;
475     }
476 
477     return;
478 }
479