1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci
16800b99b8Sopenharmony_ci#include "dfx_exit_hook.h"
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <dlfcn.h>
19800b99b8Sopenharmony_ci#include <signal.h>
20800b99b8Sopenharmony_ci#include <stdbool.h>
21800b99b8Sopenharmony_ci#include <stdio.h>
22800b99b8Sopenharmony_ci#include <stdlib.h>
23800b99b8Sopenharmony_ci#include <string.h>
24800b99b8Sopenharmony_ci#include <syscall.h>
25800b99b8Sopenharmony_ci#include <unistd.h>
26800b99b8Sopenharmony_ci
27800b99b8Sopenharmony_ci#include "dfx_log.h"
28800b99b8Sopenharmony_ci#include "dfx_hook_utils.h"
29800b99b8Sopenharmony_ci
30800b99b8Sopenharmony_ci#ifdef LOG_DOMAIN
31800b99b8Sopenharmony_ci#undef LOG_DOMAIN
32800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11
33800b99b8Sopenharmony_ci#endif
34800b99b8Sopenharmony_ci
35800b99b8Sopenharmony_ci#ifdef LOG_TAG
36800b99b8Sopenharmony_ci#undef LOG_TAG
37800b99b8Sopenharmony_ci#define LOG_TAG "DfxExitHook"
38800b99b8Sopenharmony_ci#endif
39800b99b8Sopenharmony_ci
40800b99b8Sopenharmony_citypedef int (*KillFunc)(pid_t pid, int sig);
41800b99b8Sopenharmony_citypedef __attribute__((noreturn)) void (*ExitFunc)(int code);
42800b99b8Sopenharmony_cistatic KillFunc g_hookedKill = NULL;
43800b99b8Sopenharmony_cistatic ExitFunc g_hookedExit = NULL;
44800b99b8Sopenharmony_cistatic ExitFunc g_hookedExitEx = NULL;
45800b99b8Sopenharmony_cistatic bool g_abortWhenExit = false;
46800b99b8Sopenharmony_ci
47800b99b8Sopenharmony_cistatic void __attribute__((constructor)) InitExitHook(void)
48800b99b8Sopenharmony_ci{
49800b99b8Sopenharmony_ci    char* str = getenv("ABORT_EXIT");
50800b99b8Sopenharmony_ci    if (str != NULL && strlen(str) > 0) {
51800b99b8Sopenharmony_ci        printf("AbortExit:%s\n", str);
52800b99b8Sopenharmony_ci        g_abortWhenExit = true;
53800b99b8Sopenharmony_ci    }
54800b99b8Sopenharmony_ci
55800b99b8Sopenharmony_ci    StartHookExitFunc();
56800b99b8Sopenharmony_ci}
57800b99b8Sopenharmony_ci
58800b99b8Sopenharmony_ciint kill(pid_t pid, int sig)
59800b99b8Sopenharmony_ci{
60800b99b8Sopenharmony_ci    DFXLOGF("%{public}d send signal(%{public}d) to %{public}d", getpid(), sig, pid);
61800b99b8Sopenharmony_ci    if ((sig == SIGKILL) && (pid == getpid())) {
62800b99b8Sopenharmony_ci        abort();
63800b99b8Sopenharmony_ci    } else if (sig == SIGKILL) {
64800b99b8Sopenharmony_ci        LogBacktrace();
65800b99b8Sopenharmony_ci    }
66800b99b8Sopenharmony_ci
67800b99b8Sopenharmony_ci    if (g_hookedKill == NULL) {
68800b99b8Sopenharmony_ci        DFXLOGE("hooked kill is NULL?\n");
69800b99b8Sopenharmony_ci        return syscall(SYS_kill, pid, sig);
70800b99b8Sopenharmony_ci    }
71800b99b8Sopenharmony_ci    return g_hookedKill(pid, sig);
72800b99b8Sopenharmony_ci}
73800b99b8Sopenharmony_ci
74800b99b8Sopenharmony_civoid exit(int code)
75800b99b8Sopenharmony_ci{
76800b99b8Sopenharmony_ci    DFXLOGF("%{public}d call exit with code %{public}d", getpid(), code);
77800b99b8Sopenharmony_ci    if (!g_abortWhenExit) {
78800b99b8Sopenharmony_ci        LogBacktrace();
79800b99b8Sopenharmony_ci    }
80800b99b8Sopenharmony_ci
81800b99b8Sopenharmony_ci    if ((!g_abortWhenExit) && (g_hookedExit != NULL)) {
82800b99b8Sopenharmony_ci        g_hookedExit(code);
83800b99b8Sopenharmony_ci    } else if (g_abortWhenExit) {
84800b99b8Sopenharmony_ci        abort();
85800b99b8Sopenharmony_ci    }
86800b99b8Sopenharmony_ci
87800b99b8Sopenharmony_ci    quick_exit(code);
88800b99b8Sopenharmony_ci}
89800b99b8Sopenharmony_ci
90800b99b8Sopenharmony_civoid _exit(int code)
91800b99b8Sopenharmony_ci{
92800b99b8Sopenharmony_ci    DFXLOGF("%{public}d call exit with code %{public}d", getpid(), code);
93800b99b8Sopenharmony_ci    if (!g_abortWhenExit) {
94800b99b8Sopenharmony_ci        LogBacktrace();
95800b99b8Sopenharmony_ci    }
96800b99b8Sopenharmony_ci
97800b99b8Sopenharmony_ci    if ((!g_abortWhenExit) && (g_hookedExitEx != NULL)) {
98800b99b8Sopenharmony_ci        g_hookedExitEx(code);
99800b99b8Sopenharmony_ci    } else if (g_abortWhenExit) {
100800b99b8Sopenharmony_ci        abort();
101800b99b8Sopenharmony_ci    }
102800b99b8Sopenharmony_ci
103800b99b8Sopenharmony_ci    quick_exit(code);
104800b99b8Sopenharmony_ci}
105800b99b8Sopenharmony_ci
106800b99b8Sopenharmony_ciGEN_HOOK_FUNC(StartHookKillFunction, KillFunc, "kill", g_hookedKill)
107800b99b8Sopenharmony_ciGEN_HOOK_FUNC(StartHookExitFunction, ExitFunc, "exit", g_hookedExit)
108800b99b8Sopenharmony_ciGEN_HOOK_FUNC(StartHookExitExFunction, ExitFunc, "_exit", g_hookedExitEx)
109800b99b8Sopenharmony_ci
110800b99b8Sopenharmony_civoid StartHookExitFunc(void)
111800b99b8Sopenharmony_ci{
112800b99b8Sopenharmony_ci    StartHookKillFunction();
113800b99b8Sopenharmony_ci    StartHookExitFunction();
114800b99b8Sopenharmony_ci    StartHookExitExFunction();
115800b99b8Sopenharmony_ci}
116