为什么在Docker里使用gdb调试器会报错

简介:

背景

前几天一个小伙伴发邮件问我,他在docker内部使用gdb调试时刻遇到了gdb如下报错信息
ptrace:Operation not permitted
当时我的答复是在docker create或者docker run时刻开启万精油--privileged参数。小伙伴的问题就此解决了。
但是事实并非如此简单

Docker上涉及到gdb调试权限的特性

capabilities

Docker借用了linux对进程设置capabilities,而其子进程继承父进程capabilites特性来完成对容器capacities的控制。Docker create和docker run参数中有下面两个参数可以对容器默认的capabilites进行修改:
--cap-add //添加某个capabilites属性 --cap-del //剔除某个默认的capabilites属性
cap-add和cap-del可以设置的参数可以通过下面链接查询到:
https://docs.docker.com/engine/reference/commandline/run/

  • Docker 将gdb调试需要SYS_PTRACE属性被禁止掉了,所以gdb在调试的时候会显示ptrace被禁止。所以想在docker内部调试gdb解决办法就是create和run的时候带上--cap-add sys_ptrace*
    例如:
docker run  -it --cap-add sys_ptrace centos:latest /bin/bash
root@7f5a2130e975>cd /home/
root@7fa2130e975> vi test.c
\#include <stdio.h>
int main(){
     int i = 0;
    printf(“Testing begin\n”);
    While(1){
       printf(“Loop cnt:%d\n”,i++);
       sleep(10);   
    }
 }

root@7fa2130975>gcc -c -g -o test.o test.c
root@7fa2130975>gcc -o test -g test.o
root@7fa2130975>./test&
[1] 18
root@7fa2130975>gdb attach 18
//ok可以调试了  

但是这并不是问题的全部,对于上述测试程序,如果执行下面命令gdb又有告警出来

root@7fa2130975>gdb ./test
(gdb) r
Warning:Error disabling address space randomization:Operation not permitted

虽然依然可以调试,但是我们还是需要搞清楚上述告警的意思。地址随机化是linux一项安全特性,它允许内核进程启动每次加载库的时候都在随机化的分布在进程虚拟内存地址空间上(早期固定的库要加载到固定地方,如果固定地方被占用才加载到别地方。会造成多次加载程序,其库地址都不变。如此有安全隐患)。在gdb调试中gdb默认需要关闭linux的地址随机化功能,可以通过gdb 命令set disable-randomization off关闭。如果在地址随机化下调试同一段程序,多次run时候可以看到它的运行地址和函数地址不一致,这没有什么太大的问题。问题可以结束了
关于gdb 设置地址随机化开关详情见下面链接:
http://visualgdb.com/gdbreference/commands/set_disable-randomization
当然上述告警其实也可以不通过gdb设置来完成,可以通过下面介绍的Docker参数可以达成。

seccomp

Docker默认情况下为每个容器都设置了一个默认的seccom profile。一般情况下无需修改。但是docker依然支持
docker create或者docker run时候通过--security-opt seccomp=xxx参数来设置docker容器的seccomp策略。
xxx可以是一个json格式文件,里面定义了docker容器每个具体的seccomp规则。也可以是字符unconfined表示关闭默认的docker seccomp 规则。
可以通过下面命令彻底关闭docker默认seccomp引入的任何限制
docker run -it --security-opt seccomp=unconfined centos:lastes
在运行上述gdb 调试命令run一个进程,告警信息终于彻底消失了。
Docker设置的seccomp 默认profile规则可以通过如下链接查询到:
https://docs.docker.com/engine/security/seccomp/
本文就不再做详细展开了。

Docker背后的实现技术

Docker实现seccomp控制

从Linux 2.6.23开始支持这种特性对进程能够使用的系统调用进行控制,如此可以进行一些安全性策略。sandbox就是依赖于此技术。docker梳理了Linux的系统调用,从300+个系统调用中屏蔽掉了44个系统调用,但是又最大程度的不影响正常的应用使用系统。

  • 在Docker engine上有一个叫seccomp模块提供了为docker提供默认seccomp规则(GetDefaultProfile()函数),而我们在命令行配置的seccomp属性会覆盖默认的seccomp规则(在setSeccomp()函数里)。最终规则在engine内部创建runc spec时刻函数createSpec生产。将seccomp传递到oci runtime spec的spec.linux.seccomp字段里。
  • 而runc通过seccomp库的InitSeccomp()函数,在Init一个容器时刻和exec触发的将一个进程setns到容器内部时刻调用此函数 将seccomp属性设置到容器的init进程或者exec进程里。
  • Linux进程属性里有seccomp属性,此属性也会父子继承,通过/proc/$pid/status里可以看到进程的seccomp属性。

Docker实现capabilities

从Linux 2.1开始支持的特性,将超级用户的权限划分为多个组,每个进程都有一个capabilities属性,子进程从自己的父进程中基础capacities。这个特性和sudo不一样,因为sudo控制粒度太粗;而capabilities控制粒度很精细。linux有一系列的调用可以设置、查看,清除和比较进程的capabilities。可以通过:
man cap_set_flag
来查看这一系列的系统调用。而具体进程的capacities可以通过/proc/$pid/status中:
Capxxx字段看到,本文就不再展开。感兴趣的朋友可以参考
https://www.cnblogs.com/iamfy/archive/2012/09/20/2694977.html

  • 在oci runtime spec里规定了spec.Process.Capabilities属性。runc中finializeNamespace()根据此属性对进程的capabilities进行设置。此函数会在init容器和exec加一个进程到容器时刻调用。
相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
1月前
|
安全 Docker 容器
Docker中运行容器时Operation not permitted报错问题解决
【10月更文挑战第2天】Docker中运行容器时Operation not permitted报错问题解决
289 3
|
5月前
|
JavaScript 前端开发 数据安全/隐私保护
阿里云云效操作报错合集之流水线中获取不到CI_COMMIT_REF_NAME变量,导致docker镜像打包失败,什么原因
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
1月前
|
搜索推荐 应用服务中间件 nginx
docker与containerd镜像获取及导出导入的区别与注意事项(报错信息:ctr: content digest sha256........ac47: not found)
docker与containerd镜像获取及导出导入的区别与注意事项(报错信息:ctr: content digest sha256........ac47: not found)
|
29天前
|
JavaScript 前端开发 Docker
拿下奇怪的前端报错(二):nvm不可用报错`GLIBC_2.27‘‘GLIBCXX_3.4.20‘not Found?+ 使用docker构建多个前端项目实践
本文介绍了在多版本Node.js环境中使用nvm进行版本管理和遇到的问题,以及通过Docker化构建流程来解决兼容性问题的方法。文中详细描述了构建Docker镜像、启动临时容器复制构建产物的具体步骤,有效解决了不同项目对Node.js版本的不同需求。
|
30天前
|
网络虚拟化 Docker 容器
docker Desktop报错 error pulling image configuration 处理
docker Desktop报错 error pulling image configuration 处理
34 0
|
1月前
|
网络协议 应用服务中间件 Linux
docker常见报错提示WARNING: IPv4 forwarding is disabled. Networking will not work.或/usr/bin/docker-current:
### 故障与解决方法概览 1. **故障现象**:运行 `docker run -d -P httpd:centos` 时提示“IPv4转发已禁用,网络将无法工作”。 - **解决方法**:通过编辑 `/etc/sysctl.conf` 设置 `net.ipv4.ip_forward=1` 并执行 `sysctl -p` 启用路由转发,然后重启 Docker 服务。
|
2月前
|
Shell 数据安全/隐私保护 Docker
9-2|docker rm报错
9-2|docker rm报错
|
2月前
|
Unix Shell Linux
5-15|Docker报错OCI runtime exec failed: exec failed: unable to start container process: exec: “/bin/ba
5-15|Docker报错OCI runtime exec failed: exec failed: unable to start container process: exec: “/bin/ba
|
2月前
|
关系型数据库 MySQL 数据库
docker启动mysql多实例连接报错Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’
docker启动mysql多实例连接报错Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’
178 0
|
3月前
|
运维 Java Devops
阿里云云效操作报错合集之部署docker时遇到报错,该怎么办
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。