返回

解决 Google Breakpad Core Handler ptrace 禁用时的 BT 异常

Linux

解决 Google Breakpad Core Handler 在 ptrace 禁用时的 BT 异常问题

ptrace 被禁用时,Google Breakpad 的 core_handler 可能无法生成有效的堆栈回溯 (BT)。 这个问题会导致在分析 minidump 文件时, GDB 无法显示正确的函数调用栈, 而是出现类似 0xabababababababab 的无效地址。 本文将深入探讨这个问题,并提供多种解决方案。

问题分析

core_handler 默认依赖于 Linux 的 ptrace 功能来获取线程和堆栈信息。当 ptrace 由于安全或其他限制被禁用时,core_handler 需要使用其他机制来获取必要的信息。如果配置不当,生成的 minidump 文件可能只包含部分或无效的堆栈信息。

问题核心在于,当 ptrace 不可用时,core_handler 需要依赖 /proc/[pid]/maps/proc/[pid]/mem 来获取内存信息, 这两个虚拟文件在某些安全策略限制下也可能无法访问, 导致堆栈信息缺失。

解决方案

以下是一些解决 core_handlerptrace 禁用时 BT 异常问题的方案:

1. 调整 Seccomp 或 AppArmor 配置

如果你的应用使用了 Seccomp 或 AppArmor 等安全策略,这些策略可能会阻止 core_handler 访问必要的 /proc 文件系统。需要调整安全策略以允许 core_handler 访问。

Seccomp 配置示例:

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "syscalls": [
    {"names": ["prctl", "rt_sigreturn", "read", "write", "exit", "openat", "fstat", "close", "lseek", "getpid", "sigaltstack"], "action": "SCMP_ACT_ALLOW"},
    {"names": ["open"], "args": [{"index": 0, "op": "SCMP_CMP_EQ", "val": "/proc/self/maps"}, {"index":0, "op": "SCMP_CMP_EQ", "val": "/proc/self/mem"}], "action": "SCMP_ACT_ALLOW"},
    {"names":["open"], "action": "SCMP_ACT_ERRNO"},
    {"names": ["clone"], "action": "SCMP_ACT_ALLOW", "includes": [{"index":0, "op": "SCMP_CMP_MASKED_EQ", "val":2049536, "mask":2049536 }]}  // Assuming SIGCHLD handler
  ]
}

操作步骤:

  1. 修改或创建 Seccomp 配置文件。
  2. seccomp_load 系统调用加入代码中,在程序初始化时加载 Seccomp 配置。
  3. 重新编译和部署应用。

AppArmor 配置示例:

  ...
  /proc/[0-9]*/maps r,
  /proc/[0-9]*/mem r,
  ...

操作步骤:

  1. 修改或创建 AppArmor 配置文件。
  2. 使用 apparmor_parser 命令加载配置文件, 或者重启 AppArmor 服务。

安全建议: 仔细审查 Seccomp 和 AppArmor 的配置, 仅授予必要的权限。过多的权限可能带来安全隐患。

2. 使用 MmapMinidumpWriter 代替 CoreHandler

MmapMinidumpWriter 可以直接从进程内存中创建 minidump 文件, 这种方式不依赖 ptrace, 可以作为一种可行的替代方案。

代码示例 (C++):

#include "breakpad/linux/processor/minidump_writer.h"

// ...

bool WriteMinidump(pid_t pid, const char* filename) {
  breakpad::MmapMinidumpWriter writer(pid);
  return writer.Write(filename);
}

// ...

int main() {
  // ... 程序逻辑

  // 注册信号处理函数,捕获崩溃信号
  signal(SIGSEGV, [](int signum) {
    WriteMinidump(getpid(), "crash.dmp");
    // ... 其他处理逻辑
    exit(signum);
  });

  // ... 其他程序逻辑
}

操作步骤:

  1. 在项目中集成 Breakpad 的 MmapMinidumpWriter 组件。
  2. 在代码中注册信号处理函数, 当程序崩溃时调用 MmapMinidumpWriter 生成 minidump 文件。
  3. 重新编译和部署应用。

额外说明: MmapMinidumpWriter 这种方式的缺点是需要在应用内部集成 Breakpad 库,增加了代码复杂性, 并可能导致程序体积增大。

3. 使用 gcore 生成 core dump 文件

如果以上方法均无效,可以考虑使用 gcore 命令手动生成 core dump 文件。 这种方式完全不依赖 Breakpad, 适用于调试各种 core dump 相关问题。

命令行指令:

gcore <pid>

操作步骤:

  1. 找到需要生成 core dump 文件的进程 ID。
  2. 使用 gcore 命令生成 core dump 文件, 如 gcore 1234,会生成 core.1234 文件。
  3. 使用 GDB 加载 core dump 文件进行调试,如 gdb your_application core.1234

安全建议: 尽量避免在生产环境中直接使用 gcore, 因为 gcore 会暂停进程, 影响服务的可用性。

4. 检查 dump_syms 工具路径配置

确保 core_handler 能够正确找到 dump_syms 工具, 否则无法解析符号信息,导致堆栈回溯异常。

环境变量配置:

export BREAKPAD_DUMP_SYMS_PATH=/path/to/dump_syms

操作步骤:

  1. 编译 Breakpad dump_syms 工具。
  2. 设置 BREAKPAD_DUMP_SYMS_PATH 环境变量指向 dump_syms 工具路径。
  3. 重新启动应用。

额外提示: 确保在编译 Breakpad 时,编译选项和你的应用程序的编译选项匹配, 特别是 C++ ABI 版本和优化级别, 避免符号解析错误。

总结

ptrace 被禁用时, 解决 Google Breakpad core_handler BT 异常问题需要综合考虑安全限制、Breakpad 配置和替代方案。 通过调整 Seccomp 或 AppArmor 配置, 使用 MmapMinidumpWriter 或者直接使用 gcore 命令,以及检查 Breakpad 相关配置,可以有效解决该问题, 确保在各种环境下都能生成有效的堆栈回溯信息, 方便调试和问题分析。