Files
PlayIntegrityFork/app/src/main/cpp/shadowhook/sh_safe.c
chiteroman e03f363117 v12.2
2023-11-10 21:43:37 +01:00

134 lines
4.7 KiB
C

// Copyright (c) 2021-2022 ByteDance Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Created by Kelun Cai (caikelun@bytedance.com) on 2021-04-11.
#include "sh_safe.h"
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include "sh_util.h"
#include "xdl.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreserved-id-macro"
#pragma clang diagnostic ignored "-Wvariadic-macros"
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#pragma clang diagnostic ignored "-Wsign-conversion"
#pragma clang diagnostic ignored "-Wpacked"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
#include "linux_syscall_support.h"
#pragma clang diagnostic pop
#define SH_SAFE_IDX_PTHREAD_GETSPECIFIC 0
#define SH_SAFE_IDX_PTHREAD_SETSPECIFIC 1
#define SH_SAFE_IDX_ABORT 2
#define SH_SAFE_IDX_SZ 3
typedef struct {
uintptr_t target_addr;
uintptr_t orig_addr;
} sh_safe_addr_t;
static sh_safe_addr_t sh_safe_addrs[SH_SAFE_IDX_SZ];
static int sh_safe_api_level;
static int sh_safe_init_func(void *handle, const char *symbol, size_t idx) {
sh_safe_addrs[idx].target_addr = (uintptr_t)(xdl_sym(handle, symbol, NULL));
if (__predict_false(0 == sh_safe_addrs[idx].target_addr)) return -1;
sh_safe_addrs[idx].orig_addr = 0;
return 0;
}
int sh_safe_init(void) {
sh_safe_api_level = sh_util_get_api_level();
void *handle = xdl_open("libc.so", XDL_DEFAULT);
if (NULL == handle) return -1;
int r = -1;
if (__predict_false(0 != sh_safe_init_func(handle, "pthread_getspecific", SH_SAFE_IDX_PTHREAD_GETSPECIFIC)))
goto end;
if (__predict_false(0 != sh_safe_init_func(handle, "pthread_setspecific", SH_SAFE_IDX_PTHREAD_SETSPECIFIC)))
goto end;
if (__predict_false(0 != sh_safe_init_func(handle, "abort", SH_SAFE_IDX_ABORT))) goto end;
r = 0;
end:
xdl_close(handle);
return r;
}
uintptr_t *sh_safe_get_orig_addr_addr(uintptr_t target_addr) {
for (size_t i = 0; i < SH_SAFE_IDX_SZ; i++) {
if (sh_safe_addrs[i].target_addr == target_addr) {
return &sh_safe_addrs[i].orig_addr;
}
}
return NULL;
}
static uintptr_t sh_safe_get_orig_addr(size_t idx) {
sh_safe_addr_t *addr = &sh_safe_addrs[idx];
return 0 != addr->orig_addr ? addr->orig_addr : addr->target_addr;
}
void *sh_safe_pthread_getspecific(pthread_key_t key) {
uintptr_t addr = sh_safe_get_orig_addr(SH_SAFE_IDX_PTHREAD_GETSPECIFIC);
return ((void *(*)(pthread_key_t))addr)(key);
}
int sh_safe_pthread_setspecific(pthread_key_t key, const void *value) {
if (sh_safe_api_level >= __ANDROID_API_M__) {
uintptr_t addr = sh_safe_get_orig_addr(SH_SAFE_IDX_PTHREAD_SETSPECIFIC);
return ((int (*)(pthread_key_t, const void *))addr)(key, value);
} else {
// Before Android M, pthread_setspecific() will call pthread_mutex_lock() and
// pthread_mutex_unlock(). So if we use pthread_setspecific() in hub's trampo,
// we will NOT be able to hook pthread_mutex_lock() and pthread_mutex_unlock().
void **tls;
#if defined(__aarch64__)
__asm__("mrs %0, tpidr_el0" : "=r"(tls));
#elif defined(__arm__)
__asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(tls));
#endif
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-qual"
tls[key] = (void *)value;
#pragma clang diagnostic pop
return 0;
}
}
void sh_safe_abort(void) {
uintptr_t addr = sh_safe_get_orig_addr(SH_SAFE_IDX_ABORT);
((void (*)(void))addr)();
}
void *sh_safe_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) {
return sys_mmap(addr, length, prot, flags, fd, offset);
}
int sh_safe_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4,
unsigned long arg5) {
return sys_prctl(option, arg2, arg3, arg4, arg5);
}