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