OOT驅(qū)動(dòng)內(nèi)存隔離使用說(shuō)明
本文中含有需要您注意的重要提示信息,忽略該信息可能對(duì)您的業(yè)務(wù)造成影響,請(qǐng)務(wù)必仔細(xì)閱讀。
OOT(Out Of Tree)驅(qū)動(dòng)質(zhì)量存在差異,常常出現(xiàn)use after free
內(nèi)存錯(cuò)誤以及越界訪問(wèn)等問(wèn)題。通過(guò)對(duì)OOT驅(qū)動(dòng)的內(nèi)存池進(jìn)行隔離,可以確保被破壞的內(nèi)存不會(huì)被分配至其他模塊,從而使得OOT驅(qū)動(dòng)破壞的僅為其自身的內(nèi)存。從而能夠快速界定問(wèn)題,減少排查與修復(fù)所需的時(shí)間,進(jìn)而降低業(yè)務(wù)損失。
限制說(shuō)明
操作系統(tǒng)限制
Alibaba Cloud Linux 3在
5.10.134-17.al8
及以上版本的內(nèi)核中支持配置OOT驅(qū)動(dòng)內(nèi)存隔離功能。功能限制
僅支持以下函數(shù)來(lái)分配KMALLOC_NORMAL類型的內(nèi)存(且內(nèi)存大小為8 B~8 KB)進(jìn)行隔離。
kmalloc
kzalloc
kmalloc_node
kzalloc_node
kmalloc_array
kmalloc_array_node
kcalloc
kcalloc_node
數(shù)量限制
僅支持隔離OOT驅(qū)動(dòng)的數(shù)量上限為16。
配置OOT驅(qū)動(dòng)內(nèi)存隔離
您可以根據(jù)實(shí)際需要,選擇以下任一方式配置OOT驅(qū)動(dòng)內(nèi)存隔離功能。
通過(guò)添加參數(shù)控制隔離。
在kernel cmdline中添加
module.oot_list=<OOT模塊1>,<OOT模塊2>
參數(shù)控制隔離。<OOT模塊1>,<OOT模塊2>
需替換為具體的模塊名。若有多個(gè)模塊,請(qǐng)?jiān)诤竺嬉来翁砑幽K名稱,用,
隔開(kāi)。sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="module.oot_list=<OOT模塊1>,<OOT模塊2>"
重啟服務(wù),使配置生效。
警告重啟實(shí)例將導(dǎo)致您的實(shí)例暫停運(yùn)行,這可能引發(fā)業(yè)務(wù)中斷和數(shù)據(jù)丟失。因此,建議您在執(zhí)行此操作之前備份關(guān)鍵數(shù)據(jù),并選擇在非業(yè)務(wù)高峰期進(jìn)行。
sudo reboot
通過(guò)
echo
命令控制隔離。在
/sys/module/module/parameters/oot_list
中寫(xiě)入<OOT模塊1>,<OOT模塊2>
。<OOT模塊1>,<OOT模塊2>
需替換為具體的模塊名。若有多個(gè)模塊,請(qǐng)?jiān)诤竺嬉来翁砑幽K名稱,用,
隔開(kāi)。sudo sh -c 'echo <OOT模塊1>,<OOT模塊2> > /sys/module/module/parameters/oot_list'
重新加載模塊使配置生效。
<OOT模塊>
需替換為具體的模塊名。rmmod <OOT模塊>.ko insmod <OOT模塊>.ko
在加載OOT驅(qū)動(dòng)時(shí),如果模塊被隔離了,內(nèi)核日志會(huì)輸出以下信息,據(jù)此可以得到使用獨(dú)立的slab(內(nèi)存區(qū)域)的index
。
Module <模塊名> use oot-kmalloc-<index>.
OOT驅(qū)動(dòng)內(nèi)存隔離風(fēng)險(xiǎn)處理
被OOT驅(qū)動(dòng)使用的內(nèi)存被視為“臟內(nèi)存”。如果這些內(nèi)存被其他地方使用,則存在被覆蓋的風(fēng)險(xiǎn)。默認(rèn)情況下,OOT驅(qū)動(dòng)使用過(guò)的頁(yè)將被緩存以供自身使用,而不會(huì)返還給buddy子系統(tǒng)。這可能導(dǎo)致一定數(shù)量的內(nèi)存開(kāi)銷。若需調(diào)整這一行為,則可以通過(guò)以下方式。
通過(guò)調(diào)整
module.oot_page_limit
參數(shù)來(lái)控制緩存使用上限。查看
<size>
,指slab具體的大小(8 B~8 KB)。sudo cat /proc/slabinfo
獲取
order
值。<index>
和<size>
需替換為實(shí)際的值。/sys/kernel/slab/oot-kmalloc-<index>-<size>/order
控制緩存使用上限。
<limit>
替換為要寫(xiě)入的緩存,單位:page。例如寫(xiě)入 limit
為100,order
為2,內(nèi)存使用上限為page。 sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="module.oot_page_limit=<limit>"
通過(guò)
/sys/module/module/parameters/oot_page_limit
來(lái)控制緩存使用的上限。查看
<size>
,指slab具體的大小(8 B~8 KB)。sudo cat /proc/slabinfo
獲取
order
值。<index>
和<size>
需替換為實(shí)際的值。/sys/kernel/slab/oot-kmalloc-<index>-<size>/order
控制緩存使用上限。
<limit>
替換為要寫(xiě)入的緩存,單位:page。例如寫(xiě)入 limit
為100,order
為2,內(nèi)存使用上限為page。 sudo sh -c 'echo <limit> > /sys/module/module/parameters/oot_page_limit'
通過(guò)
/sys/kernel/slab/oot-kmalloc-<index>-<size>/oot_page
查看特定slab緩存的單位頁(yè)。查看
<size>
,指slab具體的大小(8 B~8 KB)。sudo cat /proc/slabinfo
查看特定slab緩存的單位頁(yè)。
<index>
和<size>
需替換為實(shí)際的值。/sys/kernel/slab/oot-kmalloc-<index>-<size>/oot_page
定向開(kāi)啟KFENCE
OOT驅(qū)動(dòng)使用獨(dú)立的slab,因此可以開(kāi)啟定向的KFENCE來(lái)捕捉內(nèi)存越界讀寫(xiě)的情況。具體操作,請(qǐng)參考捕獲內(nèi)核的內(nèi)存污染問(wèn)題(KFENCE)。
使用以下命令開(kāi)啟KFENCE監(jiān)控獨(dú)立的slab。
#關(guān)閉所有slab類型的監(jiān)視
for file in /sys/kernel/slab/*
do
sudo sh -c 'echo 0 > $file/kfence_enable'
done
#關(guān)閉order0_page的監(jiān)視
sudo sh -c 'echo 0 > /sys/module/kfence/parameters/order0_page'
#打開(kāi)需要的slab類型的監(jiān)視
sudo sh -c 'echo 1 > /sys/kernel/slab/oot-kmalloc-<index>-<size>/kfence_enable'
常見(jiàn)問(wèn)題
為什么會(huì)出現(xiàn)no symbol version for __kmalloc/__kmalloc_node/kmalloc_caches
報(bào)錯(cuò)信息?
該報(bào)錯(cuò)因?yàn)闊o(wú)侵入改動(dòng),故編譯OOT驅(qū)動(dòng)時(shí)無(wú)法獲取是否被隔離,因此不會(huì)在模塊的信息里加上oot相關(guān)符號(hào)的crc校驗(yàn)值,無(wú)法對(duì)符號(hào)進(jìn)行校驗(yàn),這個(gè)問(wèn)題暫無(wú)規(guī)避方案,基于__kmalloc的相關(guān)內(nèi)核API較穩(wěn)定,因此該問(wèn)題風(fēng)險(xiǎn)不大,出現(xiàn)時(shí)請(qǐng)忽略即可。
問(wèn)題現(xiàn)象
第一次加載要隔離的OOT模塊時(shí),會(huì)出現(xiàn)
no symbol version for __kmalloc/__kmalloc_node/kmalloc_caches
報(bào)錯(cuò)信息,該問(wèn)題只會(huì)出現(xiàn)一次,屬于正常現(xiàn)象。可能原因
Linux內(nèi)核在加載模塊的時(shí)候會(huì)對(duì)模塊的
UND
類型的符號(hào)進(jìn)行重定位并校驗(yàn)crc
值來(lái)確保兼容性,而OOT驅(qū)動(dòng)隔離的原理是在對(duì)__kmalloc等符號(hào)重定位時(shí),把符號(hào)定位到給OOT驅(qū)動(dòng)專用的oot___kmalloc等符號(hào),因此,在編譯OOT驅(qū)動(dòng)時(shí),OOT驅(qū)動(dòng)代碼里使用的是__kmalloc,導(dǎo)致UND符號(hào)里包含的是__kmalloc,但實(shí)際重定位到的是oot___kmalloc,兩者不一致導(dǎo)致出現(xiàn)該問(wèn)題。