我正在调试一个使用libnetfilter_queue
的程序。该文档指出用户空间队列处理应用程序需要CAP_NET_ADMIN
功能才能运行。我使用setcap
实用程序完成了此操作,如下所示:
$ sudo setcap cap_net_raw,cap_net_admin=eip ./a.out
我已经验证功能是否正确应用为a)程序正常工作,b)getcap
返回以下输出:
$ getcap ./a.out
./a.out = cap_net_admin,cap_net_raw+eip
但是,当我尝试从命令行使用gdb
(例如$ gdb ./a.out
)调试此程序时,由于没有设置正确的权限而失败。 gdb
的调试功能完全正常,并按照正常情况进行调试。
我甚至试图将这些功能应用于gdb
二进制文件本身无济于事。我这样做了(正如manpages所记录的那样,“i
”标志可能允许debugee从调试器继承该功能。
我遗失了一些微不足道的事情,还是真的没有这样做?
答案 0 :(得分:9)
我遇到了同样的问题,一开始我就像上面一样认为,由于安全原因,gdb可能会忽略可执行文件的功能。但是,在调试我的ext2fs-prog打开/dev/sda1
时,阅读源代码甚至使用eclipse调试gdb本身,我意识到:
/bin/bash
。所以,解决方案非常简单,除了将cap_net_admin,cap_net_raw+eip
添加到gdb之外,您还将其应用于shell。即setcap cap_net_admin,cap_net_raw+eip /bin/bash
您还要对gdb执行此操作的原因是因为在创建调试进程之前,gdb是/bin/bash
的父进程。
gdb中的真正可执行命令行如下:
/bin/bash exec /my/executable/program/path
这是gdb内vfork的参数。
答案 1 :(得分:3)
前段时间我遇到了同样的问题。我的猜测是,运行带有附加功能的调试程序是一个安全问题。
您的程序比运行它的用户拥有更多权限。使用调试器,用户可以操纵程序的执行。因此,如果程序在具有额外特权的调试器下运行,则用户可以将这些特权用于除程序打算使用它们之外的其他目的。这将是一个严重的安全漏洞,因为用户首先没有权限。
答案 2 :(得分:3)
对于那些遇到同样问题的人,你可以通过用sudo执行gdb来绕过这个问题。
答案 3 :(得分:2)
对于那些通过IDE运行GDB的人来说,可能无法使用GDB(如@StéphaneJ。的答案)。在这种情况下,您可以运行:
sudo gdbserver localhost:12345 /path/to/application
然后将IDE的GDB实例附加到该(本地)GDBServer。
对于Eclipse CDT,这意味着要进行新的“C / C ++远程应用程序”调试配置,然后在Debugger>下进行。连接选项卡,输入TCP / localhost / 12345(或您在上面选择的任何端口)。这使您可以在Eclipse中进行调试,同时您的应用程序具有特权访问权限。
答案 4 :(得分:2)
我使用@NickHuang的解决方案,直到通过系统更新之一,它破坏了systemd服务(bash上的太多功能无法供systemd启动它或诸如此类)。切换为不使用bash,而是将命令传递给gdb以直接调用可执行文件。命令是
set startup-with-shell off
答案 5 :(得分:0)
好的,所以我为此感到挣扎,所以我想我将答案和总结结合起来。
简单的解决方法是按照建议使用sudo gdb
,但要小心一点。您在这里的操作是以root用户身份运行调试的程序。这很可能导致它的运行方式不同于以普通用户从命令行运行它时的运行方式。可能有点混乱。不是说我会永远陷入这个陷阱……糟糕。
如果您以sudo
作为root用户运行调试程序,或者如果已设置setuid
位,则很好。但是,如果调试后的程序正在使用POSIX功能(setcap
/ getcap
)运行,那么您需要按照Nick Huang的建议在bash和gdb中镜像这些更细化的权限,而不仅仅是使用'sudo'强行强制权限
做其他事情可能会导致您陷入极端学习的境地。