当我从 Docker 容器内运行 gdb 时,它没有遇到任何断点 [英] gdb does not hit any breakpoints when I run it from inside Docker container

查看:16
本文介绍了当我从 Docker 容器内运行 gdb 时,它没有遇到任何断点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

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

重现步骤(所有片段都可以复制粘贴)

创建一个docker文件:

cat <<文件从 Ubuntu运行 apt-get 更新运行 apt-get install -y build-essential gdbEOF

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

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

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

cat <<main.cpp &&g++ -g main.cpp &&gdb -ex 'break 5' -ex 'run' ./a.out#include int main(int argc, const char *argv[]){std::cout <<"你好
";返回0;}EOF

观察gdb输出:

GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1[跳过 gdb 问候语]从 ./a.out 读取符号...完成.0x40078c 处的断点 1:文件 main.cpp,第 5 行.1 #include <iostream>23 int main(int argc, const char *argv[])4 {5 std::cout <<"你好
";6 返回 0;7 }启动程序:/a.out你好在启动程序正常退出.(gdb)

从输出中可以看到断点没有被命中,尽管程序被执行(打印'hi')并成功退出.我想这里最重要的是程序确实运行了并且消息在启动程序期间正常退出是一种异常行为(根据 GDB 忽略我的断点 )

问题

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

到目前为止我尝试了什么

  1. 按照此处的建议,我尝试更改中的一行/etc/apparmor.d/docker(我是在主机上做的):将 profile docker-default flags=(attach_disconnected,mediate_deleted) { 替换为 profile docker-default flags=(attach_disconnected,mediate_deleted,complain) {.然后运行docker容器,编译,gdb.结果是一样的:在启动过程中程序正常退出.

  2. 正如另一个答案中所建议的那样,我尝试从容器内执行 strace -f -o syscall.txt gdb ./a.out,但出现以下错误:

    strace:test_ptrace_setoptions_followfork:PTRACE_TRACEME 不起作用:权限被拒绝strace:test_ptrace_setoptions_followfork:意外退出状态 1

    但我不明白如何解决这个问题.我尝试以 root 身份启动容器:sudo docker run --rm -it gdb_problem_testing bash 然后尝试了 strace——这给了我同样的错误.我必须承认我不明白 docker 是如何管理用户权限的,即容器内的 root 拥有哪些用户权限以及它从谁那里继承了权限(来自 docker 守护进程?).由于能打断点,所以在宿主机运行gdb时,怀疑是用户权限问题,不知道怎么处理.

  3. 在主机中我尝试做 echo 0 |sudo tee/proc/sys/kernel/yama/ptrace_scope 正如 另一个答案.

解决方案

update 2020.01.04:使用 answer 给出的 a href="https://stackoverflow.com/users/8807809/kevin-w-matthews">Kevin W-matthews --- 更好,因为它在不提升整个容器的情况下授予了必要的个人能力.><小时>

tldr;使用

docker run --privileged

更长:我遇到了一些docker 中的 gdb 问题---它试图(但失败)禁用地址空间布局随机化---但仅在 docker-machine 上,而不是在我的本机 linux 主机上.

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

The problem

I am able to set and reach a breakpoint if I compile and run from the host, but if I do it from within the docker container gdb does not hit the breakpoints that were set.

Steps to reproduce (all snippets are copy-paste ready)

Create a docker file:

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

Build an image and run an interactive session in it:

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

From inside of the container create small main.cpp, compile, and run 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
";
    return 0;
}
EOF

Observe the gdb output:

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
";
6       return 0;
7   }
Starting program: /a.out 
hi
During startup program exited normally.
(gdb) 

From the output one can see that the breakpoint was not hit, although the program was executed (printed 'hi') and exited successfully. I guess the most important thing here is that the program did run and that the message During startup program exited normally is an anomalous behavior (according to GDB ignores my breakpoints )

Question

What is preventing gdb from setting the breakpoint and how to fix this?

What I tried so far

  1. As suggested here, I tried to change a line in /etc/apparmor.d/docker (I did it in the host): substitute profile docker-default flags=(attach_disconnected,mediate_deleted) { by profile docker-default flags=(attach_disconnected,mediate_deleted,complain) {. Then run the docker container, compile, and gdb. The result was the same: During startup program exited normally.

  2. As suggested in another answer, from within the container, I tried to do strace -f -o syscall.txt gdb ./a.out, but I get the following error:

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

    but I do not understand how to work this around. I tried to start the container as root: sudo docker run --rm -it gdb_problem_testing bash and then tried the strace -- this gave me the same error. I must admit I do not understand how the user privileges are managed by the docker, i.e. what user rights the root inside of the container has and from whom does it inherit the rights (from the docker daemon?). Since I able to hit the breakpoint, when I run gdb in the host, I suspect that my problem would boil down to the user rights, but I do not know how to approach it.

  3. In the host I tried to do echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope as suggested in yet another answer.

解决方案

update 2020.01.04: Use the answer given by Kevin W Matthews --- it's better because it grants the necessary individual capabilities without elevating the entire container.


tldr; use

docker run --privileged

Longer: I was having some problems with gdb in docker---it was attempting (and failing) to disable address space layout randomization---but only on docker-machine, not on my native linux host.

When gdb failed to disable ASLR, all of my breakpoints would be ignored. Using the --privileged flag fixed my issue. Your mileage may vary.

这篇关于当我从 Docker 容器内运行 gdb 时,它没有遇到任何断点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆