馬培++翟高壽
摘要:操作系統(tǒng)是整個計算機系統(tǒng)的核心,而設(shè)備驅(qū)動程序則占據(jù)操作系統(tǒng)內(nèi)核的相當(dāng)份額并對系統(tǒng)安全產(chǎn)生舉足輕重的作用。作為主機與外圍設(shè)備之間通信控制的橋梁,設(shè)備驅(qū)動無疑會受到硬件設(shè)備故障的直接影響。在Linux系統(tǒng)中,驅(qū)動程序問題是造成系統(tǒng)安全的主要根源之一。特別地,由于設(shè)備驅(qū)動代碼的編寫往往沒有考慮到硬件設(shè)備的瞬時故障,所以當(dāng)硬件設(shè)備發(fā)生瞬時差錯的時候,就有可能導(dǎo)致相應(yīng)驅(qū)動程序甚至整個系統(tǒng)出現(xiàn)不可預(yù)料的后果。本文主要討論了面向硬件瞬時故障的驅(qū)動程序敏感代碼的自動分析方法,并設(shè)計和實現(xiàn)了對應(yīng)的代碼分析工具原型。運用該工具原型對Linux內(nèi)核設(shè)備驅(qū)動源碼的實驗分析結(jié)果表明,該方法和原型可以發(fā)現(xiàn)設(shè)備驅(qū)動中潛在的受到硬件設(shè)備瞬時故障影響的敏感代碼。據(jù)此,采用適當(dāng)方法對敏感代碼進行修復(fù)完善,將可以實現(xiàn)設(shè)備驅(qū)動程序的安全加固。
關(guān)鍵詞:設(shè)備驅(qū)動程序;硬件瞬時故障;敏感代碼;Linux;自動分析
中圖分類號:TP311
文獻標(biāo)識碼:A
DOI:10.3969/j.issn.1003-6970.2015.12.003
本文著錄格式:馬培,翟高壽.面向硬件瞬時故障的Linux設(shè)備驅(qū)動敏感代碼的自動分析與檢測[J].軟件,2015,36(12):09-15
0 引言
可靠性對于操作系統(tǒng)來說一直是最重要的問題,由于計算機已經(jīng)深深嵌入到我們的生活中,并且故障一旦發(fā)生我們很難有機會能彌補,因而我們需要計算機更高的可靠性來保證系統(tǒng)運行的正確性。
應(yīng)用程序是通過設(shè)備驅(qū)動程序喚起設(shè)備,而設(shè)備和驅(qū)動程序的交互是通過硬件指定的一個特定的協(xié)議,如果硬件設(shè)備遵從這些特定的協(xié)議,那么驅(qū)動程序就會完全的信任它并接受來自它的任何輸入。不幸的是設(shè)備常常不能按照這樣的規(guī)章行事,某些故障是由于磨損或者電磁干擾引起的,導(dǎo)致往驅(qū)動輸入的數(shù)據(jù)發(fā)生改變,由于驅(qū)動在Linux內(nèi)核中,就可能導(dǎo)致不可預(yù)料的系統(tǒng)故障。我們將驅(qū)動程序中由于硬件的瞬時故障而可能導(dǎo)致驅(qū)動出現(xiàn)問題的代碼稱為敏感代碼。微軟windows服務(wù)器的研究證明:(l)設(shè)備故障是引起系統(tǒng)崩潰的主要原因;(2)短暫性的硬件設(shè)備故障是正常的現(xiàn)象;(3)驅(qū)動程序容忍硬件設(shè)備故障能提高系統(tǒng)的可靠性。沒有解決這些問題,操作系統(tǒng)的可靠性就會由于設(shè)備及驅(qū)動的可靠性而被限制。
針對設(shè)備瞬時故障如何自動分析和檢測驅(qū)動程序的敏感代碼,我們主要是通過驗證來自設(shè)備的所有輸入,并且報告所有存在的故障以使得管理員能夠主動管理硬件錯誤。本文提出通過代碼分析工具分析設(shè)備驅(qū)動程序代碼,找到驅(qū)動中使用來自設(shè)備輸入的位置,即敏感代碼在驅(qū)動程序中的位置。如果驅(qū)動程序使用了沒有通過正確檢查的設(shè)備輸入數(shù)據(jù)并且該數(shù)據(jù)不正確,我們就通過修改驅(qū)動程序以插入驗證代碼,實現(xiàn)驅(qū)動容忍硬件瞬時故障的目的。我們實現(xiàn)了當(dāng)瞬時故障發(fā)生并導(dǎo)致驅(qū)動出現(xiàn)問題的時候,使用系統(tǒng)日志的方式報告相關(guān)的硬件故障。為了修復(fù)相應(yīng)的硬件故障所造成的驅(qū)動甚至內(nèi)核錯誤,我們引入了一個通用的恢復(fù)服務(wù),這個服務(wù)可以重置設(shè)備。我們依賴于使用隱匿驅(qū)動程序來提供這種修復(fù)的服務(wù),從而能夠針對設(shè)備故障實現(xiàn)驅(qū)動的恢復(fù)機制。
本文提出面向硬件瞬時故障的驅(qū)動程序敏感代碼的自動分析方法,實現(xiàn)了自動分析工具原型。通過執(zhí)行自動分析工具表明,該方法可以準(zhǔn)確檢測到驅(qū)動程序中的敏感代碼,并實現(xiàn)驅(qū)動程序的加固,提高驅(qū)動及系統(tǒng)的可靠性。
1 硬件瞬時故障及敏感代碼
1.1 硬件瞬時故障
現(xiàn)代的CMOS設(shè)備傾向于發(fā)生內(nèi)部錯誤,并且在當(dāng)晶體管萎縮的情況下這種錯誤會更加嚴(yán)重。以前的研究表明某些設(shè)備會發(fā)生短暫的比特位反轉(zhuǎn)錯誤,即單個比特位從1變?yōu)?或從0變成1;永久性的門級故障,即在一段較長的時間內(nèi)某一比特保持固定值;橋接故障,即相鄰比特對發(fā)生電力干擾從而在比特間產(chǎn)生邏輯與門、邏輯或門。環(huán)境條件的改變?nèi)珉姶鸥蓴_或者輻射都能導(dǎo)致產(chǎn)生短暫性故障。設(shè)備的磨損和老化也可能導(dǎo)致門級故障或者橋接性的錯誤。
設(shè)備驅(qū)動程序訪問來自設(shè)備的輸入的時候會偵查故障,如PCI驅(qū)動,通過內(nèi)存或I/O端口執(zhí)行I/O操作,設(shè)備驅(qū)動可能會在I/O中讀取到設(shè)備中的錯誤的值;如USB驅(qū)動,使用請求/響應(yīng)協(xié)議,設(shè)備故障可能導(dǎo)致響應(yīng)包中包含錯誤的數(shù)據(jù)。很多硬件故障表現(xiàn)為在設(shè)備寄存器中存放了被篡改的值,如設(shè)備控制器內(nèi)部的單比特反轉(zhuǎn)可能傳播到某些內(nèi)部寄存器,而設(shè)備驅(qū)動程序讀取到這個內(nèi)部寄存器中被篡改的值的時候就可能會發(fā)生故障。門級故障也可能存在上述同樣的問題。當(dāng)硬件設(shè)備不能在規(guī)定的時間內(nèi)響應(yīng),在設(shè)備固件中的錯誤表現(xiàn)就可能會是不正確的輸出數(shù)據(jù)或超時故障。
1.2 敏感代碼
敏感代碼即驅(qū)動程序中由于硬件的瞬時故障導(dǎo)致驅(qū)動出現(xiàn)問題的代碼。各類硬件紛繁復(fù)雜質(zhì)量層次不齊,驅(qū)動可能由于物理設(shè)備出現(xiàn)偶發(fā)性的瞬時故障而影響驅(qū)動及系統(tǒng)的安全可靠性。驅(qū)動對外設(shè)的訪問主要是通過I/O端口,I/O端口即外設(shè)寄存器,是接口電路中能被CPU直接訪問的寄存器地址。幾乎每一種外設(shè)都是通過讀寫設(shè)備上的寄存器來進行工作的。Linux下訪問I/O端口的方式主要有兩種I/O映射方式和內(nèi)存映射方式。I/O映射方式是直接使用I/O端口操作函數(shù),即使用inb(),outb()等函數(shù)進行端口訪問,內(nèi)存訪問方式是將I/O端口映射為內(nèi)存進行訪問,即使用I/O內(nèi)存的函數(shù)進行端口訪問。當(dāng)發(fā)生硬件瞬時故障的時候可能會篡改I/O端口操作函數(shù)、I/O內(nèi)存函數(shù)的返回值,導(dǎo)致驅(qū)動從I/O端口讀取到的數(shù)據(jù)是不正確的值。當(dāng)該數(shù)據(jù)被應(yīng)用到驅(qū)動代碼中不恰當(dāng)?shù)奈恢萌缱鳛檠h(huán)條件或數(shù)組下標(biāo)時,就可能導(dǎo)致驅(qū)動出現(xiàn)無限輪詢或數(shù)組越界錯誤,從而影響驅(qū)動運行的正確性,降低驅(qū)動及系統(tǒng)的可靠性。因此,我們將驅(qū)動代碼中使用I/O端口操作函數(shù),并將這些I/O端口函數(shù)直接或間接應(yīng)用在循環(huán)條件或數(shù)組下標(biāo)中的代碼稱之為敏感代碼。
2 設(shè)備驅(qū)動敏感代碼自動分析方法的設(shè)計
大部分操作系統(tǒng)供應(yīng)商向設(shè)備驅(qū)動程序編寫者提出建議:如何固化驅(qū)動程序能夠容忍硬件故障,(1)驗證:我們認為從設(shè)備中獲取的所有的輸入都是可疑的,都需要進行驗證才能確保數(shù)據(jù)在正確的范圍內(nèi);(2)超時:當(dāng)設(shè)備一直沒有響應(yīng)的時候,對于所有與設(shè)備的交互都應(yīng)當(dāng)有響應(yīng)的措施來應(yīng)對超時從而防止永久性的等待;(3)報告:所有可疑的行為或者操作都需要報告給操作系統(tǒng)服務(wù)器,從而方便對硬件故障的集中偵查和管理;(4)恢復(fù):設(shè)備驅(qū)動程序應(yīng)當(dāng)能從任何的設(shè)備故障中恢復(fù),如果需要可以通過重置設(shè)備來達到恢復(fù)的目的。
我們的目標(biāo)主要就是能自動完成上述建議??傮w設(shè)計方案如圖1所示,首先,我們試圖使得驅(qū)動程序能夠容忍設(shè)備故障并能夠從設(shè)備故障中恢復(fù),從而防止了設(shè)備故障導(dǎo)致系統(tǒng)崩潰。我們主要針對的是短暫性的故障,即當(dāng)重置設(shè)備后這樣的故障不會再重復(fù)發(fā)生。其次,我們讓設(shè)備驅(qū)動程序報告設(shè)備故障,使得系統(tǒng)管理員能夠知道存在的短暫性故障并及時的處理故障設(shè)備。自動分析方法設(shè)計的過程主要是(l)分析驅(qū)動與設(shè)備交互的原理從而確定I/O端口及I/O內(nèi)存操作函數(shù),(2)分析驅(qū)動程序中直接或間接使用I/O端口操作函數(shù)的位置即找到所有受I/O影響的變量,(3)標(biāo)注敏感代碼即被修改的變量被使用在循環(huán)條件或數(shù)組下表的位置。由于短暫性的硬件故障是偶發(fā)性的,我們需要用到簡單的故障注入工具進行模擬硬件故障,從而達到驗證實驗的目的。
2.1 110端口及I/O內(nèi)存操作函數(shù)
Linux操作系統(tǒng)內(nèi)核主要有主內(nèi)核、內(nèi)存管理、網(wǎng)絡(luò)、文件系統(tǒng)及其設(shè)備驅(qū)動等目錄。其中驅(qū)動設(shè)備通常不會完全集成到內(nèi)核代碼中,且對應(yīng)于設(shè)備的驅(qū)動程序也通常是由第三方編寫實現(xiàn),因此容易在與內(nèi)核模塊通信、系統(tǒng)調(diào)用等方面產(chǎn)生錯誤,從而波及到系統(tǒng)的其他內(nèi)核模塊導(dǎo)致系統(tǒng)崩潰。實踐證明,在導(dǎo)致系統(tǒng)故障的代碼中,有50%以上的錯誤是由設(shè)備驅(qū)動程序引起的。
在Linux系統(tǒng)中,主機與外界交換信息是通過輸入輸出設(shè)備進行的,輸入輸出設(shè)備與系統(tǒng)的交互式是使用驅(qū)動這個中間媒介,驅(qū)動通過訪問I/O端口實現(xiàn)與硬件設(shè)備的通信。由于CPU對外設(shè)端口物理地址的編址有兩種方式:I/O映射方式和內(nèi)存映射方式,所以驅(qū)動訪問I/O端口也有兩種途徑:其一為I/O映射方式即是直接使用I/O端口操作函數(shù);其二是內(nèi)存映射方式即將I/O端口映射為內(nèi)存進行訪問。這兩種方式都要使用相應(yīng)的I/O端口及I/O內(nèi)存操作函數(shù)對數(shù)據(jù)進行讀寫。I/O端口操作函數(shù)主要包括inb(),inb_p(),insb(),outb(),outb_p()等。I/O內(nèi)存操作函數(shù)主要有ioread8(),ioport_map(),readb(),readl()等。當(dāng)硬件發(fā)生瞬時故障,可能影響這些函數(shù)的返回值,使得驅(qū)動讀取到錯誤的值而使驅(qū)動出現(xiàn)運行錯誤,影響驅(qū)動甚至系統(tǒng)的可靠性。
2.2 自動分析方法
設(shè)備驅(qū)動程序依賴于硬件的正確性以確保自身的正確性,我們通過對驅(qū)動程序代碼進行靜態(tài)分析找到驅(qū)動程序中使用源于設(shè)備的數(shù)據(jù)的位置,并且驗證數(shù)據(jù)的有效性,防止在執(zhí)行代碼之前讀取到非有效的數(shù)據(jù)而導(dǎo)致不可預(yù)料的系統(tǒng)錯誤。靜態(tài)分析過程的輸入主要是整個Linux源碼中的驅(qū)動代碼,即/Linux/drivers和/Linux/sound下的所有文件,輸出是驅(qū)動程序源碼中直接或間接使用I/O和內(nèi)存操作函數(shù)的位置和敏感代碼,即可能潛在的故障源列表。
自動分析方法主要是對系統(tǒng)驅(qū)動代碼進行掃描,首先針對驅(qū)動的每一個文件進行詞法分析,分析出所有變量、常量、函數(shù)、界符等。然后對驅(qū)動文件進行語法分析,找出所有的使用I/O端口操作函數(shù)和I/O內(nèi)存函數(shù)的位置,并標(biāo)注被I/O操作函數(shù)直接或間接修改的變量。最后找出被修改的變量被應(yīng)用在循環(huán)條件或數(shù)組下標(biāo)的位置,即找到驅(qū)動中與硬件瞬時故障相關(guān)的敏感代碼。
針對自動分析結(jié)果所找到的敏感代碼,我們的處理機制是在敏感代碼處插入超時、越界檢查和引入自動修復(fù)機制。當(dāng)發(fā)生設(shè)備瞬時故障并引起驅(qū)動程序發(fā)生無限輪詢或數(shù)組越界錯誤時,則會喚起通用的恢復(fù)服務(wù),即隱匿驅(qū)動程序,對設(shè)備進行重置,從而達到恢復(fù)的目的。
3 原型實現(xiàn)及驗證
該原型實現(xiàn)的開發(fā)平臺是Ubuntu12.04,在Sourceinsight和Gedit下實現(xiàn)代碼的編寫,開發(fā)語言為C語言,使用Makefile和gcc4.8.1實現(xiàn)編譯功能,使用gdb代碼調(diào)試工具對自動分析工具進行調(diào)試運行。
3.1 原型實現(xiàn)
本文提出的加固驅(qū)動程序主要是排除硬件依賴性故障,固化驅(qū)動程序的工作流程如圖2可分為三個部分,分別為分析驅(qū)動源碼找到驅(qū)動程序使用源于設(shè)備的數(shù)據(jù)的位置、驗證驅(qū)動程序獲取硬件數(shù)據(jù)的有效性、插入代碼對潛在的故障進行修復(fù)。找到驅(qū)動程序中使用1/0操作函數(shù)的位置主要是對驅(qū)動程序代碼進行詞法分析和語法分析用以識別各種類型的語句,檢測出與硬件通信相關(guān)的I/0操作函數(shù)的使用位置并進行標(biāo)注。驗證相關(guān)硬件數(shù)據(jù)的有效性是對從硬件獲取的數(shù)據(jù)進行有效性檢查,如:添加計時器,檢查數(shù)據(jù)范圍等。插入代碼進行修復(fù)是當(dāng)硬件依賴故障偶然性的發(fā)生時我們插入代碼,引入通用的自動修復(fù)機制,對硬件進行重置從而達到容忍硬件故障的目的。為實現(xiàn)對Linux內(nèi)核源碼中的所有文件應(yīng)用自動分析工具,我們通過編寫shell腳本,實現(xiàn)對所有驅(qū)動文件進行遍歷,在遍歷過程中執(zhí)行我們的分析過程。
敏感代碼檢測分析流程如圖3所示。主要有四個部分組成:驅(qū)動程序代碼的預(yù)處理、詞法分析、語法分析、靜態(tài)分析輸出敏感代碼。
3.1.1 設(shè)備驅(qū)動源程序的預(yù)處理
預(yù)處理驅(qū)動程序是分析代碼的第一步,它主要處理C語言中的各種預(yù)處理語句和注釋。處理的預(yù)處理語句主要包括#define、#error、#include、#if、#else、#ifdef、#line等。同時在預(yù)處理階段刪除“//”和以“/*”開頭以“*/”結(jié)尾的注釋,以方便后續(xù)代碼分析。
預(yù)處理后生成與分析驅(qū)動文件所對應(yīng)的*.tmp文件。處理后的文件中沒有注釋行,并且完成了宏定義的替換,被include包含的文件也被插入到相應(yīng)的位置。
3.1.2 詞法分析
詞法分析主要是對經(jīng)過預(yù)處理的程序代碼進行分析,得出相關(guān)單詞符號如關(guān)鍵字(int、struct)、變量、常量(十進制、十六進制等)、運算符(+、-、*、/等)、界符(,、;、(等)等,將這些單詞符號放入到相應(yīng)的符號表中。該詞法分析主要檢測的是變量,以方便后續(xù)靜態(tài)分析找到被I/0操作函數(shù)影響的變量。
經(jīng)過詞法分析將相關(guān)的單詞符號填入到符號表中,用于記錄源程序中各種單詞符號的屬性和特征。本文變量和函數(shù)的符號表的定義如下:
(l)變量標(biāo)識符的符號表否為I/O操作函數(shù)*/
}FuncTable:
3.1.3 語法分析
語法分析主要是在完成詞法分析的基礎(chǔ)上對代碼進行語法結(jié)構(gòu)的分析。該分析過程用于獲取與變量和函數(shù)相關(guān)的信息存入到符號表中,為后續(xù)的靜態(tài)分析做準(zhǔn)備。
(l)提取變量相關(guān)信息,將驅(qū)動代碼中出現(xiàn)的每一個變量的行號都記錄下來,存放在變量符號表的定義變量和使用變量的字段中。
(2)提取函數(shù)相關(guān)信息,標(biāo)識每個函數(shù)所定義和使用的變量,并記錄下函數(shù)體內(nèi)所引用的函數(shù)名等。
3.1.4 敏感代碼的檢測
通過上述的分析過程,我們能準(zhǔn)確的標(biāo)識出驅(qū)動源碼中所有的標(biāo)識符及其引用流程,我們靜態(tài)分析的過程包括兩步,第一步是標(biāo)識出驅(qū)動程序中直接或間接使用I/0端口函數(shù)和I/0內(nèi)存函數(shù)的位置,并找到被這些函數(shù)修改的變量標(biāo)注在變量符號表的tainted字段中。第二步是找出被修改的變量或I/0操作函數(shù)應(yīng)用在循環(huán)條件和數(shù)組下標(biāo)的行號,將其標(biāo)注為敏感代碼輸出到Taintedfor.txt中。
當(dāng)被修改的變量被應(yīng)用在驅(qū)動程序的循環(huán)條件中,而由于偶發(fā)性的硬件故障而導(dǎo)致該變量從硬件讀取來的數(shù)據(jù)不是預(yù)期的值,那就可能導(dǎo)致驅(qū)動進去死循環(huán)永遠都不能跳出來。由于驅(qū)動和系統(tǒng)內(nèi)核有著千絲萬縷的聯(lián)系,驅(qū)動的無限輪詢就可能導(dǎo)致不可預(yù)料的系統(tǒng)故障。當(dāng)被修改的變量被應(yīng)用在全局或局部數(shù)組變量的下標(biāo)中,由于數(shù)組下標(biāo)有范圍界限,若因為偶發(fā)性的硬件故障而導(dǎo)致從硬件獲取的數(shù)據(jù)值不在該數(shù)組的合法范圍內(nèi),驅(qū)動就會因為存在越界錯誤而導(dǎo)致系統(tǒng)問題。
3.1.5 敏感代碼的修復(fù)與報告
針對上述分析出的潛在的故障因素,我們需要對其進行修復(fù)。對于無限輪詢故障,主要是在驅(qū)動中插入代碼打破無限輪詢的條件?;诙啻螌︱?qū)動代碼的延時測試和其他設(shè)備所使用的延時,我們使用最大的延時。我們在循環(huán)內(nèi)添加計時器,并設(shè)置最大延時時間。當(dāng)在循環(huán)體內(nèi)循環(huán)的時間超過我們設(shè)置的最大延時時間時,我們就認為該循環(huán)陷入了無限輪詢,此時我們引入通用的恢復(fù)服務(wù)隱匿驅(qū)動程序?qū)τ布M行重置,重新獲取硬件相關(guān)的信息。對于數(shù)組越界問題,我們主要是根據(jù)驅(qū)動代碼上下文,在被修改變量用在數(shù)組下標(biāo)之前的位置處對該變量進行條件判斷,若變量值在數(shù)組范圍外,則引入通用的恢復(fù)服務(wù),對故障進行恢復(fù)。
在對無限輪詢和數(shù)組越界的驅(qū)動錯誤進行修復(fù)后,當(dāng)確實出現(xiàn)硬件故障的時候我們使用printk函數(shù)實現(xiàn)系統(tǒng)日志通知系統(tǒng)管理員發(fā)生了硬件故障,以便于系統(tǒng)管理員對故障進行管理和維護。
3.2 實驗驗證
3.2.1 敏感代碼自動檢測結(jié)果分析
我們靜態(tài)分析的對象主要是整個Linux內(nèi)核驅(qū)動,內(nèi)核版本為Linux2.6.18。通過分析drivers和sound目錄下的6000多個源程序文件,這些文件包括的驅(qū)動類主要有網(wǎng)卡驅(qū)動、聲卡驅(qū)動、視頻驅(qū)動、SCSI驅(qū)動和其它類驅(qū)動,從靜態(tài)分析的輸出文件中發(fā)現(xiàn)了大量的潛在的無限輪詢和數(shù)組越界錯誤。分析結(jié)果表明驅(qū)動的硬件依賴性故障是普遍存在的,只有盡量避免這些潛在的錯誤才能提高操作系統(tǒng)的可靠性。
使用隨機抽樣方法檢查驅(qū)動代碼分析結(jié)果表明:誤報率低于9%。對于無限輪詢錯誤,我們檢查了100個例子,只是發(fā)現(xiàn)了10個誤報,誤報原因主要是該驅(qū)動自身已經(jīng)實現(xiàn)了檢查和修復(fù)方法,但這種誤報并不會對驅(qū)動造成損害,唯一可能的損害就是增加了少量的不必要的開銷。
3.2.2 敏感代碼修復(fù)與故障報告
通過使用自動分析工具對驅(qū)動源碼進行分析,我們能得到所有驅(qū)動類中潛在的硬件依賴性故障。由于對驅(qū)動進行測試依賴于硬件,我們不可能擁有內(nèi)核驅(qū)動所對應(yīng)的所有的硬件,所以我們主要對已經(jīng)存在的硬件進行驗證,如電腦本機的網(wǎng)卡和聲卡。由于短暫性的硬件故障是偶發(fā)性的,我們無法預(yù)期什么時候會發(fā)生,所以我們引入了故障注入工具,模擬硬件故障的發(fā)生。通過故障注入工具模擬硬件故障,我們測試了固化前的驅(qū)動和固化后的本機網(wǎng)卡驅(qū)動。在測試過程中,我們發(fā)現(xiàn)對于固化后的驅(qū)動代碼示例如下圖4所示,當(dāng)發(fā)生了硬件瞬時故障的時候能夠喚起通用的恢復(fù)機制對硬件進行重置,驅(qū)動程序再次讀取相關(guān)信息可以正常運行,而對于固化前的驅(qū)動,由于發(fā)生了短暫性的硬件故障,導(dǎo)致了驅(qū)動不能正常運行下去。正是由于我們插入的修復(fù)代碼和引入驅(qū)動的恢復(fù)機制,當(dāng)發(fā)生硬件故障時候,我們的驅(qū)動程序能夠容忍硬件瞬時故障,從而實現(xiàn)在軟件中容忍硬件故障的目的。
對于故障的報告分析,我們主要是報告設(shè)備超時(驅(qū)動代碼發(fā)生無限輪洵)和報告驅(qū)動代碼數(shù)組越界。由于Linux沒有故障管理服務(wù),我們使用printk來實現(xiàn)系統(tǒng)日志。系統(tǒng)管理員可以通過在終端輸入命令dmesg或者進入Linux系統(tǒng)日志目錄進行查看。對于設(shè)備超時的故障報告主要是當(dāng)由于硬件瞬時故障而導(dǎo)致驅(qū)動程序發(fā)生無限輪詢錯誤的時候通過printk函數(shù)以infinite loop為標(biāo)識寫系統(tǒng)日志。系統(tǒng)管理員通過infinite loop為標(biāo)識查看是否發(fā)生該類故障。對于數(shù)組越界的錯誤報告主要是當(dāng)驅(qū)動代碼由于硬件故障而發(fā)生數(shù)組越界錯誤的時候通過printk函數(shù)以Array out of range為標(biāo)識寫系統(tǒng)日志。系統(tǒng)管理員通過Arrav out of range查看是否發(fā)生數(shù)組越界故障。通過dmesg查看系統(tǒng)日志發(fā)現(xiàn),我們能正確的報告發(fā)生的相關(guān)驅(qū)動故障,從而方便管理員對故障進行管理和維護。
4 測試評估
4.1 功能測試評估
為了評估自動分析工具的功能準(zhǔn)確性,我們定義誤檢率和漏檢率。誤檢率即某處不是受硬件瞬時故障影響的敏感代碼,而自動分析工具卻標(biāo)注其為敏感代碼,在整個掃描過程中出現(xiàn)這種誤報的概率。某處是受硬件瞬時故障影響的敏感代碼,但自動分析工具卻沒有標(biāo)注其為敏感代碼,這種漏報的概率稱為漏報率。
本文主要是對2.6.18的內(nèi)核版本應(yīng)用我們的自動分析工具,驗證了這種分析方法能夠正確的查找到所有驅(qū)動模塊的敏感代碼,按照驅(qū)動類劃分查詢到的敏感代碼數(shù)量如下表1所示。
通過靜態(tài)分析和有效性檢查,我們對整個Linux內(nèi)核驅(qū)動代碼進行全盤分析掃描,主要是查找兩類硬件依賴故障即無限輪詢和數(shù)組越界錯誤。對于短暫性硬件故障導(dǎo)致驅(qū)動程序的無限輪詢,在網(wǎng)卡驅(qū)動類中查找到110個潛在的錯誤,在scsi驅(qū)動類290個潛在的錯誤,在整個Linux驅(qū)動中總體查找到740個錯誤。對于靜態(tài)數(shù)組越界的敏感代碼,我們在Linux驅(qū)動中共查找到43個潛在的錯誤。上述錯誤充分說明潛在的硬件依賴性錯誤在內(nèi)核驅(qū)動代碼中是普遍存在的且是亟待的問題。
通過對2.6.18和3.2.1內(nèi)核版本的驅(qū)動源碼使用自動分析工具進行比較,內(nèi)核版本為3.2.1的內(nèi)核源碼所檢測到的敏感代碼比2.6.18少,并通過抽樣檢查其誤報率和漏報率均較小且差別不大。由于內(nèi)核版本為3.2.1是2.6.18的升級,所以檢測到的敏感代碼少是合理的。比較結(jié)果證明,我們的自動分析工具能夠?qū)Σ煌瑑?nèi)核版本的驅(qū)動的敏感代碼進行準(zhǔn)確的分析。
我們針對本機的網(wǎng)卡驅(qū)動通過引用故障注入工具模擬短暫性的硬件故障,對修改前和修改后的驅(qū)動進行測試,修改前的網(wǎng)卡驅(qū)動會產(chǎn)生無限輪詢錯誤導(dǎo)致本機網(wǎng)卡驅(qū)動出現(xiàn)無法修復(fù)的問題,而修改后的驅(qū)動能正確的容忍硬件依賴性故障,喚起通用的驅(qū)動恢復(fù)服務(wù)并告知系統(tǒng)管理員發(fā)生了短暫性的硬件故障,達到我們預(yù)期的效果。
4.2 性能評估測試
性能評估主要是評估檢測敏感代碼系統(tǒng)能力及故障恢復(fù)性能,識別出系統(tǒng)存在的弱點并驗證該系統(tǒng)的穩(wěn)定性。本文采用系統(tǒng)性能測試,對系統(tǒng)性能進行全面的評估,主要包括宏觀性能測試和微觀性能測試。宏觀性能測試主要是對檢測敏感代碼系統(tǒng)的耗時和準(zhǔn)確性進行評估。微觀性能分析主要是對自動分析工具進行CPU利用率評估。
本文所采用的測試是在Ubuntu 12.04系統(tǒng)下完成,該系統(tǒng)中Linux內(nèi)核版為3.11.0-26,GCC編譯器版本4.8.1,計算機硬件配置為CPU Pentium Dual-Core,內(nèi)存2G,硬盤200G。
本文宏觀性能測試主要測試檢測敏感代碼系統(tǒng)的耗時及其準(zhǔn)確性。檢測耗時主要方法是使用UNIXdate命令。在對Linux驅(qū)動源碼進行遍歷掃描的腳本中,增加驅(qū)動分析開始時間及結(jié)束時間,通過計算得出分析檢測驅(qū)動代碼所消耗的時間為4700s。對檢測到的敏感代碼的準(zhǔn)確性我們主要是采用加權(quán)隨機抽樣的方式,通過對自動檢測敏感代碼的結(jié)果和手動抽樣檢查進行比較,其檢測到的敏感代碼的準(zhǔn)確率較高。
微觀性能評估主要是對自動分析工具進行CPU利用率評估,檢測方法主要是利用Linux操作系統(tǒng)的ps命令獲取該分析工具的CPU利用率。在對內(nèi)核驅(qū)動代碼進行自動分析的過程中,我們使用ps命令獲取其CPU利用率為2.2%,結(jié)果表明,該工具性能開銷較小,符合我們的設(shè)計要求。
5 結(jié)論
系統(tǒng)的可靠性由于設(shè)備及對應(yīng)驅(qū)動的可靠性而受到限制,Linux系統(tǒng)出現(xiàn)的很多故障都是由于硬件瞬時故障導(dǎo)致的。為解決該問題,本文提出一種在驅(qū)動軟件中容忍硬件瞬時故障的機制,討論了面向硬件瞬時故障的驅(qū)動程序敏感代碼的自動分析方法,通過對Linux驅(qū)動源碼進行預(yù)處理、詞法分析、語法分析和靜態(tài)分析,查找出可能產(chǎn)生無限輪詢和靜態(tài)數(shù)組越界的敏感代碼并進行標(biāo)注。為修復(fù)該類敏感代碼可能引起的驅(qū)動問題,我們通過插入時間檢查和范圍檢查,并引入了一個通用的恢復(fù)服務(wù)隱匿驅(qū)動程序?qū)Πl(fā)生短暫性硬件故障的設(shè)備進行重置,驅(qū)動重新讀取寄存器中的硬件數(shù)據(jù)以達到修復(fù)的目的。同時,當(dāng)發(fā)生短暫的硬件依賴性故障的時候,我們通過系統(tǒng)日志的方式通知管理員硬件發(fā)生問題,方便系統(tǒng)管理員對系統(tǒng)進行管理和維護。由于偶發(fā)性的硬件故障比較罕見的發(fā)生,為測試實驗結(jié)果,我們使用了故障注入工具來模擬我們期望的硬件故障,通過測試,經(jīng)加固后的驅(qū)動程序能夠很好的容忍硬件瞬時故障,從而很好的實現(xiàn)了在軟件中容忍硬件故障的目的。