mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Simplify ptrace emulation and code style fixes
PiperOrigin-RevId: 369862187 Change-Id: Ia0759c320cde1c9e3798f0df5c2a0d50ca20fd71
This commit is contained in:
parent
d9824dff16
commit
ab7943abdc
|
@ -27,6 +27,7 @@ cc_library(
|
||||||
hdrs = ["ptrace_hook.h"],
|
hdrs = ["ptrace_hook.h"],
|
||||||
copts = sapi_platform_copts(),
|
copts = sapi_platform_copts(),
|
||||||
visibility = ["@org_gnu_libunwind//:__subpackages__"],
|
visibility = ["@org_gnu_libunwind//:__subpackages__"],
|
||||||
|
deps = ["@com_google_absl//absl/strings"],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
|
|
|
@ -18,8 +18,9 @@ add_library(sandbox2_ptrace_hook STATIC
|
||||||
ptrace_hook.h
|
ptrace_hook.h
|
||||||
)
|
)
|
||||||
add_library(sandbox2::ptrace_hook ALIAS sandbox2_ptrace_hook)
|
add_library(sandbox2::ptrace_hook ALIAS sandbox2_ptrace_hook)
|
||||||
target_link_libraries(sandbox2_ptrace_hook PRIVATE
|
target_link_libraries(sandbox2_ptrace_hook
|
||||||
sapi::base
|
PRIVATE sapi::base
|
||||||
|
PUBLIC absl::strings
|
||||||
)
|
)
|
||||||
|
|
||||||
# sandboxed_api/sandbox2/unwind:unwind
|
# sandboxed_api/sandbox2/unwind:unwind
|
||||||
|
|
|
@ -21,80 +21,75 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
// Maximum register struct size: 128 u64.
|
namespace sandbox2 {
|
||||||
constexpr size_t kRegisterBufferSize = 128 * 8;
|
namespace {
|
||||||
// Contains the register values in a ptrace specified format.
|
|
||||||
// This format is pretty opaque which is why we just forward
|
|
||||||
// the raw bytes (up to a certain limit).
|
|
||||||
static unsigned char register_values[kRegisterBufferSize];
|
|
||||||
static size_t n_register_values_bytes_used = 0;
|
|
||||||
|
|
||||||
// It should not be necessary to put this in a thread local storage as we
|
// Register size is `long` for the supported architectures according to the
|
||||||
// do not support setting up the forkserver when there is more than one thread.
|
// kernel.
|
||||||
// However there might be some edge-cases, so we do this just in case.
|
using RegType = long; // NOLINT
|
||||||
thread_local bool emulate_ptrace = false;
|
constexpr size_t kRegSize = sizeof(RegType);
|
||||||
|
|
||||||
void ArmPtraceEmulation() { emulate_ptrace = true; }
|
// Contains the register values in a ptrace specified format. This format is
|
||||||
|
// pretty opaque which is why we just forward the raw bytes (up to a certain
|
||||||
|
// limit).
|
||||||
|
auto* g_registers = new std::vector<RegType>();
|
||||||
|
|
||||||
void InstallUserRegs(const char *ptr, size_t size) {
|
// Whether ptrace() emulation is in effect. This can only be enabled (per
|
||||||
if (sizeof(register_values) < size) {
|
// thread), never disabled.
|
||||||
fprintf(stderr, "install_user_regs: Got more bytes than supported (%lu)\n",
|
thread_local bool g_emulate_ptrace = false;
|
||||||
size);
|
|
||||||
} else {
|
} // namespace
|
||||||
memcpy(®ister_values, ptr, size);
|
|
||||||
n_register_values_bytes_used = size;
|
void EnablePtraceEmulationWithUserRegs(absl::string_view regs) {
|
||||||
}
|
g_registers->resize((regs.size() + 1) / kRegSize);
|
||||||
|
memcpy(&g_registers->front(), regs.data(), regs.size());
|
||||||
|
g_emulate_ptrace = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replaces the libc version of ptrace.
|
// Replaces the libc version of ptrace.
|
||||||
// This wrapper makes use of process_vm_readv to read process memory instead of
|
// This wrapper makes use of process_vm_readv to read process memory instead of
|
||||||
// issuing ptrace syscalls. Accesses to registers will be emulated, for this the
|
// issuing ptrace syscalls. Accesses to registers will be emulated, for this the
|
||||||
// register values should be set via install_user_regs().
|
// register values should be set via EnablePtraceEmulationWithUserRegs().
|
||||||
// The emulation can be switched on using arm_ptrace_emulation().
|
|
||||||
extern "C" long int ptrace_wrapped( // NOLINT
|
extern "C" long int ptrace_wrapped( // NOLINT
|
||||||
enum __ptrace_request request, pid_t pid, void *addr, void *data) {
|
enum __ptrace_request request, pid_t pid, void* addr, void* data) {
|
||||||
// Register size is `long` for the supported architectures according to the
|
if (!g_emulate_ptrace) {
|
||||||
// kernel.
|
|
||||||
using reg_type = long; // NOLINT
|
|
||||||
constexpr size_t reg_size = sizeof(reg_type);
|
|
||||||
if (!emulate_ptrace) {
|
|
||||||
return ptrace(request, pid, addr, data);
|
return ptrace(request, pid, addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (request) {
|
switch (request) {
|
||||||
case PTRACE_PEEKDATA: {
|
case PTRACE_PEEKDATA: {
|
||||||
long int read_data; // NOLINT
|
long int read_data; // NOLINT
|
||||||
|
struct iovec local = {
|
||||||
|
.iov_base = &read_data,
|
||||||
|
.iov_len = sizeof(long int), // NOLINT
|
||||||
|
};
|
||||||
|
struct iovec remote = {
|
||||||
|
.iov_base = addr,
|
||||||
|
.iov_len = sizeof(long int), // NOLINT
|
||||||
|
};
|
||||||
|
|
||||||
struct iovec local, remote;
|
if (process_vm_readv(pid, &local, 1, &remote, 1, 0) <= 0) {
|
||||||
local.iov_len = sizeof(long int); // NOLINT
|
|
||||||
local.iov_base = &read_data;
|
|
||||||
|
|
||||||
remote.iov_len = sizeof(long int); // NOLINT
|
|
||||||
remote.iov_base = addr;
|
|
||||||
|
|
||||||
if (process_vm_readv(pid, &local, 1, &remote, 1, 0) > 0) {
|
|
||||||
return read_data;
|
|
||||||
} else {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} break;
|
return read_data;
|
||||||
case PTRACE_PEEKUSER: {
|
}
|
||||||
uintptr_t next_offset = reinterpret_cast<uintptr_t>(addr) + reg_size;
|
case PTRACE_PEEKUSER:
|
||||||
// Make sure read is in-bounds and aligned.
|
// Make sure read is in-bounds and aligned.
|
||||||
if (next_offset <= n_register_values_bytes_used &&
|
if (uintptr_t offset = reinterpret_cast<uintptr_t>(addr);
|
||||||
reinterpret_cast<uintptr_t>(addr) % reg_size == 0) {
|
offset + kRegSize > g_registers->size() * kRegSize ||
|
||||||
return reinterpret_cast<reg_type *>(
|
offset % kRegSize != 0) {
|
||||||
®ister_values)[reinterpret_cast<uintptr_t>(addr) / reg_size];
|
|
||||||
} else {
|
|
||||||
return -1;
|
return -1;
|
||||||
|
} else {
|
||||||
|
return (*g_registers)[offset / kRegSize];
|
||||||
}
|
}
|
||||||
} break;
|
default:
|
||||||
default: {
|
fprintf(stderr, "ptrace_wrapped(): operation not permitted: %d\n",
|
||||||
fprintf(stderr, "ptrace-wrapper: forbidden operation invoked: %d\n",
|
|
||||||
request);
|
request);
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace sandbox2
|
||||||
|
|
|
@ -15,12 +15,13 @@
|
||||||
#ifndef SANDBOXED_API_SANDBOX2_UNWIND_PTRACE_HOOK_H_
|
#ifndef SANDBOXED_API_SANDBOX2_UNWIND_PTRACE_HOOK_H_
|
||||||
#define SANDBOXED_API_SANDBOX2_UNWIND_PTRACE_HOOK_H_
|
#define SANDBOXED_API_SANDBOX2_UNWIND_PTRACE_HOOK_H_
|
||||||
|
|
||||||
#include <cstddef>
|
#include "absl/strings/string_view.h"
|
||||||
|
|
||||||
|
namespace sandbox2 {
|
||||||
|
|
||||||
// Sets the register values that the ptrace emulation will return.
|
// Sets the register values that the ptrace emulation will return.
|
||||||
void InstallUserRegs(const char* ptr, size_t size);
|
void EnablePtraceEmulationWithUserRegs(absl::string_view regs);
|
||||||
|
|
||||||
// Enables the ptrace emulation.
|
} // namespace sandbox2
|
||||||
void ArmPtraceEmulation();
|
|
||||||
|
|
||||||
#endif // SANDBOXED_API_SANDBOX2_UNWIND_PTRACE_HOOK_H_
|
#endif // SANDBOXED_API_SANDBOX2_UNWIND_PTRACE_HOOK_H_
|
||||||
|
|
|
@ -123,9 +123,7 @@ bool RunLibUnwindAndSymbolizer(Comms* comms) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& data = setup.regs();
|
EnablePtraceEmulationWithUserRegs(setup.regs());
|
||||||
InstallUserRegs(data.c_str(), data.length());
|
|
||||||
ArmPtraceEmulation();
|
|
||||||
|
|
||||||
std::vector<uintptr_t> ips;
|
std::vector<uintptr_t> ips;
|
||||||
std::vector<std::string> stack_trace =
|
std::vector<std::string> stack_trace =
|
||||||
|
|
Loading…
Reference in New Issue
Block a user