当我从Docker容器

时间:2016-01-18 13:36:24

标签: linux debugging permissions docker gdb

问题

如果我从主机编译并运行,我可以设置并达到断点,但如果我在docker容器中执行此操作,gdb不会触及已设置的断点。

重现的步骤(所有代码段都已准备好复制粘贴)

创建一个泊坞文件:

cat << EOF > Dockerfile
FROM ubuntu
RUN apt-get update
RUN apt-get install -y build-essential gdb
EOF

构建图像并在其中运行交互式会话:

docker build -t gdb_problem_testing . && docker run --rm -it  gdb_problem_testing bash

从容器内部创建小的main.cpp,编译并运行gdb:

cat <<EOF > main.cpp && g++ -g main.cpp && gdb -ex 'break 5' -ex 'run' ./a.out
#include <iostream>

int main(int argc, const char *argv[])
{
    std::cout << "hi\n";
    return 0;
}
EOF

观察gdb输出:

GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
[Skipped gdb greeting]
Reading symbols from ./a.out...done.
Breakpoint 1 at 0x40078c: file main.cpp, line 5.
1   #include <iostream>
2   
3   int main(int argc, const char *argv[])
4   {
5       std::cout << "hi\n";
6       return 0;
7   }
Starting program: /a.out 
hi
During startup program exited normally.
(gdb) 

从输出中可以看到断点未被击中,尽管程序已执行(打印为“hi”)并已成功退出。我想这里最重要的是该程序确实运行,并且消息正常启动程序退出是一种异常行为(根据GDB ignores my breakpoints

问题

什么阻止gdb设置断点以及如何解决这个问题?

到目前为止我尝试了什么

  1. 根据建议here,我尝试更改/etc/apparmor.d/docker中的一行(我在主机中执行了此操作): profile docker-default flags=(attach_disconnected,mediate_deleted) {替换profile docker-default flags=(attach_disconnected,mediate_deleted,complain) {。然后运行docker容器,compile和gdb。结果是相同的:During startup program exited normally

  2. 正如another answer中所述,我从容器中尝试strace -f -o syscall.txt gdb ./a.out,但我收到以下错误:

    strace: test_ptrace_setoptions_followfork: PTRACE_TRACEME doesn't work: Permission denied
    strace: test_ptrace_setoptions_followfork: unexpected exit status 1
    

    但我不明白如何解决这个问题。我尝试以root身份启动容器:sudo docker run --rm -it gdb_problem_testing bash然后尝试了strace - 这给了我同样的错误。我必须承认我不理解docker管理用户权限的方式,即容器内部root的用户权限以及继承权限的用户权限(来自docker守护程序?)。由于我能够点击断点,当我在主机中运行gdb时,我怀疑我的问题会归结为用户权限,但我不知道如何处理它。

  3. 在主持人中,我按照another answer中的建议尝试echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

2 个答案:

答案 0 :(得分:23)

tldr;使用

docker run --privileged

更长:我有一些problems with gdb in docker ---它正在尝试(并且失败)禁用address space layout randomization ---但仅在docker-machine上,而不是在我的本机linux主机上。

当gdb无法禁用ASLR时,我的所有断点都将被忽略。使用--privileged标志修复了我的问题。您的里程可能会有所不同。

答案 1 :(得分:1)

我没有使用整个容器,而是使用了该选项

--security-opt seccomp=unconfined

解决地址空间随机化问题。

有些人还建议启用ptrace功能

--cap-add=SYS_PTRACE

但这对我似乎没有任何作用。

以下是Docker compose的相同设置:

security_opt:
  - seccomp:unconfined
cap_add:
  - SYS_PTRACE

详细信息取自this Stack Overflow post