为什么在Docker里使用gdb调试器会报错
背景
前幾天一個(gè)小伙伴發(fā)郵件問(wèn)我,他在docker內(nèi)部使用gdb調(diào)試時(shí)刻遇到了gdb如下報(bào)錯(cuò)信息
ptrace:Operation not permitted
當(dāng)時(shí)我的答復(fù)是在docker create或者docker run時(shí)刻開(kāi)啟萬(wàn)精油--privileged參數(shù)。小伙伴的問(wèn)題就此解決了。
但是事實(shí)并非如此簡(jiǎn)單
Docker上涉及到gdb調(diào)試權(quán)限的特性
capabilities
Docker借用了linux對(duì)進(jìn)程設(shè)置capabilities,而其子進(jìn)程繼承父進(jìn)程capabilites特性來(lái)完成對(duì)容器capacities的控制。Docker create和docker run參數(shù)中有下面兩個(gè)參數(shù)可以對(duì)容器默認(rèn)的capabilites進(jìn)行修改:
--cap-add //添加某個(gè)capabilites屬性 --cap-del //剔除某個(gè)默認(rèn)的capabilites屬性
cap-add和cap-del可以設(shè)置的參數(shù)可以通過(guò)下面鏈接查詢到:
https://docs.docker.com/engine/reference/commandline/run/
- Docker 將gdb調(diào)試需要SYS_PTRACE屬性被禁止掉了,所以gdb在調(diào)試的時(shí)候會(huì)顯示ptrace被禁止。所以想在docker內(nèi)部調(diào)試gdb解決辦法就是create和run的時(shí)候帶上--cap-add sys_ptrace*
例如:
但是這并不是問(wèn)題的全部,對(duì)于上述測(cè)試程序,如果執(zhí)行下面命令gdb又有告警出來(lái)
root@7fa2130975>gdb ./test (gdb) r Warning:Error disabling address space randomization:Operation not permitted雖然依然可以調(diào)試,但是我們還是需要搞清楚上述告警的意思。地址隨機(jī)化是linux一項(xiàng)安全特性,它允許內(nèi)核進(jìn)程啟動(dòng)每次加載庫(kù)的時(shí)候都在隨機(jī)化的分布在進(jìn)程虛擬內(nèi)存地址空間上(早期固定的庫(kù)要加載到固定地方,如果固定地方被占用才加載到別地方。會(huì)造成多次加載程序,其庫(kù)地址都不變。如此有安全隱患)。在gdb調(diào)試中g(shù)db默認(rèn)需要關(guān)閉linux的地址隨機(jī)化功能,可以通過(guò)gdb 命令set disable-randomization off關(guān)閉。如果在地址隨機(jī)化下調(diào)試同一段程序,多次run時(shí)候可以看到它的運(yùn)行地址和函數(shù)地址不一致,這沒(méi)有什么太大的問(wèn)題。問(wèn)題可以結(jié)束了
關(guān)于gdb 設(shè)置地址隨機(jī)化開(kāi)關(guān)詳情見(jiàn)下面鏈接:
http://visualgdb.com/gdbreference/commands/set_disable-randomization
當(dāng)然上述告警其實(shí)也可以不通過(guò)gdb設(shè)置來(lái)完成,可以通過(guò)下面介紹的Docker參數(shù)可以達(dá)成。
seccomp
Docker默認(rèn)情況下為每個(gè)容器都設(shè)置了一個(gè)默認(rèn)的seccom profile。一般情況下無(wú)需修改。但是docker依然支持
docker create或者docker run時(shí)候通過(guò)--security-opt seccomp=xxx參數(shù)來(lái)設(shè)置docker容器的seccomp策略。
xxx可以是一個(gè)json格式文件,里面定義了docker容器每個(gè)具體的seccomp規(guī)則。也可以是字符unconfined表示關(guān)閉默認(rèn)的docker seccomp 規(guī)則。
可以通過(guò)下面命令徹底關(guān)閉docker默認(rèn)seccomp引入的任何限制
docker run -it --security-opt seccomp=unconfined centos:lastes
在運(yùn)行上述gdb 調(diào)試命令run一個(gè)進(jìn)程,告警信息終于徹底消失了。
Docker設(shè)置的seccomp 默認(rèn)profile規(guī)則可以通過(guò)如下鏈接查詢到:
https://docs.docker.com/engine/security/seccomp/
本文就不再做詳細(xì)展開(kāi)了。
Docker背后的實(shí)現(xiàn)技術(shù)
Docker實(shí)現(xiàn)seccomp控制
從Linux 2.6.23開(kāi)始支持這種特性對(duì)進(jìn)程能夠使用的系統(tǒng)調(diào)用進(jìn)行控制,如此可以進(jìn)行一些安全性策略。sandbox就是依賴于此技術(shù)。docker梳理了Linux的系統(tǒng)調(diào)用,從300+個(gè)系統(tǒng)調(diào)用中屏蔽掉了44個(gè)系統(tǒng)調(diào)用,但是又最大程度的不影響正常的應(yīng)用使用系統(tǒng)。
- 在Docker engine上有一個(gè)叫seccomp模塊提供了為docker提供默認(rèn)seccomp規(guī)則(GetDefaultProfile()函數(shù)),而我們?cè)诿钚信渲玫膕eccomp屬性會(huì)覆蓋默認(rèn)的seccomp規(guī)則(在setSeccomp()函數(shù)里)。最終規(guī)則在engine內(nèi)部創(chuàng)建runc spec時(shí)刻函數(shù)createSpec生產(chǎn)。將seccomp傳遞到oci runtime spec的spec.linux.seccomp字段里。
- 而runc通過(guò)seccomp庫(kù)的InitSeccomp()函數(shù),在Init一個(gè)容器時(shí)刻和exec觸發(fā)的將一個(gè)進(jìn)程setns到容器內(nèi)部時(shí)刻調(diào)用此函數(shù) 將seccomp屬性設(shè)置到容器的init進(jìn)程或者exec進(jìn)程里。
- Linux進(jìn)程屬性里有seccomp屬性,此屬性也會(huì)父子繼承,通過(guò)/proc/$pid/status里可以看到進(jìn)程的seccomp屬性。
Docker實(shí)現(xiàn)capabilities
從Linux 2.1開(kāi)始支持的特性,將超級(jí)用戶的權(quán)限劃分為多個(gè)組,每個(gè)進(jìn)程都有一個(gè)capabilities屬性,子進(jìn)程從自己的父進(jìn)程中基礎(chǔ)capacities。這個(gè)特性和sudo不一樣,因?yàn)閟udo控制粒度太粗;而capabilities控制粒度很精細(xì)。linux有一系列的調(diào)用可以設(shè)置、查看,清除和比較進(jìn)程的capabilities。可以通過(guò):
man cap_set_flag
來(lái)查看這一系列的系統(tǒng)調(diào)用。而具體進(jìn)程的capacities可以通過(guò)/proc/$pid/status中:
Capxxx字段看到,本文就不再展開(kāi)。感興趣的朋友可以參考
https://www.cnblogs.com/iamfy/archive/2012/09/20/2694977.html
- 在oci runtime spec里規(guī)定了spec.Process.Capabilities屬性。runc中finializeNamespace()根據(jù)此屬性對(duì)進(jìn)程的capabilities進(jìn)行設(shè)置。此函數(shù)會(huì)在init容器和exec加一個(gè)進(jìn)程到容器時(shí)刻調(diào)用。
總結(jié)
以上是生活随笔為你收集整理的为什么在Docker里使用gdb调试器会报错的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spring Cloud 搭建 Hyst
- 下一篇: 微软发布Azure Cosmos DB产