• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "dfx_signal_hook.h"
17 
18 #include <dlfcn.h>
19 #include <securec.h>
20 #include <signal.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include "dfx_define.h"
24 #include "dfx_log.h"
25 #include "pthread.h"
26 
27 #include "dfx_hook_utils.h"
28 
29 #ifdef LOG_DOMAIN
30 #undef LOG_DOMAIN
31 #define LOG_DOMAIN 0xD002D11
32 #endif
33 
34 #ifdef LOG_TAG
35 #undef LOG_TAG
36 #define LOG_TAG "DfxSigHook"
37 #endif
38 
39 #ifndef SIGDUMP
40 #define SIGDUMP 35
41 #endif
42 
43 #define MIN_FRAME 4
44 #define MAX_FRAME 64
45 #define BUF_SZ 512
46 #define MAPINFO_SIZE 256
47 #define MAX_SIGNO 63
48 
InitHook(void)49 void __attribute__((constructor)) InitHook(void)
50 {
51     StartHookFunc();
52 }
53 
54 typedef int (*SigactionFunc)(int sig, const struct sigaction *restrict act, struct sigaction *restrict oact);
55 typedef int (*SigprocmaskFunc)(int how, const sigset_t *restrict set, sigset_t *restrict oldset);
56 typedef int (*PthreadSigmaskFunc)(int how, const sigset_t *restrict set, sigset_t *restrict oldset);
57 typedef sighandler_t (*SignalFunc)(int signum, sighandler_t handler);
58 static SigactionFunc g_hookedSigaction = NULL;
59 static SigprocmaskFunc g_hookedSigprocmask = NULL;
60 static SignalFunc g_hookedSignal = NULL;
61 static PthreadSigmaskFunc g_hookedPthreadSigmask = NULL;
62 
IsPlatformHandleSignal(int sig)63 static bool IsPlatformHandleSignal(int sig)
64 {
65     int platformSignals[] = {
66         SIGABRT, SIGBUS, SIGILL, SIGSEGV, SIGDUMP
67     };
68     for (size_t i = 0; i < sizeof(platformSignals) / sizeof(platformSignals[0]); i++) {
69         if (platformSignals[i] == sig) {
70             return true;
71         }
72     }
73     return false;
74 }
75 
pthread_sigmask(int how,const sigset_t * restrict set,sigset_t * restrict oldset)76 int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oldset)
77 {
78     if (set != NULL) {
79         for (int i = 1; i < MAX_SIGNO; i++) {
80             if (sigismember(set, i) && (IsPlatformHandleSignal(i)) &&
81                 ((how == SIG_BLOCK) || (how == SIG_SETMASK))) {
82                 DFXLOGI("%{public}d:%{public}d pthread_sigmask signal(%{public}d)\n", getpid(), gettid(), i);
83             }
84         }
85     }
86 
87     if (g_hookedPthreadSigmask == NULL) {
88         DFXLOGE("hooked procmask is NULL?\n");
89         return -1;
90     }
91     return g_hookedPthreadSigmask(how, set, oldset);
92 }
93 
sigprocmask(int how,const sigset_t * restrict set,sigset_t * restrict oldset)94 int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oldset)
95 {
96     if (set != NULL) {
97         for (int i = 1; i < MAX_SIGNO; i++) {
98             if (sigismember(set, i) && (IsPlatformHandleSignal(i)) &&
99                 ((how == SIG_BLOCK) || (how == SIG_SETMASK))) {
100                 DFXLOGI("%{public}d:%{public}d sigprocmask signal(%{public}d)\n", getpid(), gettid(), i);
101             }
102         }
103     }
104     if (g_hookedSigprocmask == NULL) {
105         DFXLOGE("hooked procmask is NULL?\n");
106         return -1;
107     }
108     return g_hookedSigprocmask(how, set, oldset);
109 }
110 
signal(int signum,sighandler_t handler)111 sighandler_t signal(int signum, sighandler_t handler)
112 {
113     if (IsPlatformHandleSignal(signum)) {
114         DFXLOGI("%{public}d register signal handler for signal(%{public}d)\n", getpid(), signum);
115     }
116 
117     if (g_hookedSignal == NULL) {
118         DFXLOGE("hooked signal is NULL?\n");
119         return NULL;
120     }
121     return g_hookedSignal(signum, handler);
122 }
123 
IsSigactionAddr(uintptr_t sigactionAddr)124 static bool IsSigactionAddr(uintptr_t sigactionAddr)
125 {
126     bool ret = false;
127     char path[NAME_BUF_LEN] = {0};
128     if (snprintf_s(path, sizeof(path), sizeof(path) - 1, PROC_SELF_MAPS_PATH) <= 0) {
129         DFXLOGW("Fail to print path.");
130         return false;
131     }
132 
133     FILE *fp = fopen(path, "r");
134     if (fp == NULL) {
135         DFXLOGW("Fail to open maps info.");
136         return false;
137     }
138 
139     char mapInfo[MAPINFO_SIZE] = {0};
140     int pos = 0;
141     uint64_t begin = 0;
142     uint64_t end = 0;
143     uint64_t offset = 0;
144     char perms[5] = {0}; // 5:rwxp
145     while (fgets(mapInfo, sizeof(mapInfo), fp) != NULL) {
146         // f79d6000-f7a62000 r-xp 0004b000 b3:06 1605                               /system/lib/ld-musl-arm.so.1
147         if (sscanf_s(mapInfo, "%" SCNxPTR "-%" SCNxPTR " %4s %" SCNxPTR " %*x:%*x %*d%n", &begin, &end,
148             &perms, sizeof(perms), &offset, &pos) != 4) { // 4:scan size
149             DFXLOGW("Fail to parse maps info.");
150             continue;
151         }
152 
153         if ((strstr(mapInfo, "r-xp") != NULL) && (strstr(mapInfo, "ld-musl") != NULL)) {
154             DFXLOGI("begin: %{public}" PRIu64 ", end: %{public}" PRIu64 ", sigactionAddr: %{public}" PRIuPTR  "",
155                 begin, end, sigactionAddr);
156             if ((sigactionAddr >= begin) && (sigactionAddr <= end)) {
157                 ret = true;
158                 break;
159             }
160         } else {
161             continue;
162         }
163     }
164     if (fclose(fp) != 0) {
165         DFXLOGW("Fail to close maps info.");
166     }
167     return ret;
168 }
169 
sigaction(int sig,const struct sigaction * restrict act,struct sigaction * restrict oact)170 int sigaction(int sig, const struct sigaction *restrict act, struct sigaction *restrict oact)
171 {
172     if (g_hookedSigaction == NULL) {
173         DFXLOGE("hooked sigaction is NULL?");
174         return -1;
175     }
176 
177     if (IsPlatformHandleSignal(sig) && (act == NULL || !IsSigactionAddr((uintptr_t)(act->sa_sigaction)))) {
178         DFXLOGI("%{public}d call sigaction and signo is %{public}d\n", getpid(), sig);
179     }
180 
181     return g_hookedSigaction(sig, act, oact);
182 }
183 
184 GEN_HOOK_FUNC(StartHookSigactionFunction, SigactionFunc, "sigaction", g_hookedSigaction)
185 GEN_HOOK_FUNC(StartHookSignalFunction, SignalFunc, "signal", g_hookedSignal)
186 GEN_HOOK_FUNC(StartHookSigprocmaskFunction, SigprocmaskFunc, "sigprocmask", g_hookedSigprocmask)
187 GEN_HOOK_FUNC(StartHookPthreadSigmaskFunction, PthreadSigmaskFunc, "pthread_sigmask", g_hookedPthreadSigmask)
188 
StartHookFunc(void)189 void StartHookFunc(void)
190 {
191     StartHookSigactionFunction();
192     StartHookSignalFunction();
193     StartHookSigprocmaskFunction();
194     StartHookPthreadSigmaskFunction();
195 }
196