centos核心錯誤 Linux核心適配的一則小記

2021-10-13 23:36:12 字數 2264 閱讀 3428

我們的產品包含多個核心驅動模組,隨著linux核心的不斷演進,既有的驅動**可能因為使用了一些被新版本核心所廢棄的函式或者資料結構,導致不能編譯通過,或者執行時出錯。這時,我們就需要修改我們的驅動**,以便其能在新版本的核心上正常工作,這個過程通常被稱為「適配」。

最近就接到了乙個客戶在centos 7上適配5.7.x核心的需求,在此之前,我們適配過的最高核心版本是5.4.x。經過與makefile的一番較勁,編譯總算通過了,可是一執行新編譯的驅動,系統立刻卡住,失去響應。

從"comm"後面跟的名字看,確實是我們產品中操作這個驅動的應用層程序的名稱。這裡顯然是在做乙個"open"操作,沒有debuginfo,不知道具體開啟的是哪個檔案,不過從"proc_reg_open"來看,應該是在訪問"/proc"目錄下的某個檔案。

我們的驅動會在procfs檔案系統中註冊一些引數,以便於觀察該驅動的狀態,以及動態地調整一部分配置。為了確定是由訪問這些引數引起的異常,嘗試手動載入對應的驅動,然後去訪問"/proc"目錄下我們驅動生成的檔案,果然在"cat"其中乙個檔案時,復現了這個問題。

call trace給出的錯誤提示是訪問了乙個空指標,並且是在呼叫mutex_lock()的時候。沒有5.7.x版本的debuginfo,那就退而求其次,借助乙個擁有除錯資訊、並且版本盡可能接近的核心來輔助分析。在基於4.18核心的centos 8上,先來用crash工具看一下"mutex_lock"的反彙編:

結合對應原始碼可以推斷,多半就是因為這裡的"lock"被判定為了空指標:

bool __mutex_trylock_fast(struct mutex *lock)

;

這個有趣的"union"啊,當我們的驅動還是用"file_operations"去註冊時,編譯階段是不會報錯的,但到了執行階段,根據"pde->proc_ops->proc_open",實際是按照"proc_ops"來呼叫的:

根據c語言"union"的元素共享記憶體位址的屬性,本來是想調"proc_open",結果位址指向的是"llseek",可不就走到seq_lseek()裡去了嘛,沒有"seq_open"進行初始化就呼叫了"seq_lseek",可不就是會出現指標訪問的位址異常麼。

看似詭異的一段call trace,原來隱藏著這樣的玄機。表象上是mutex lock的時候訪問到了空指標,root cause卻是因為前面2級函式中結構體中元素的變化,以及"union"的特殊性。

那核心開發者為什麼要做出這樣乙個**的改動呢?進入linux的github,用"blame"模式看下這個改動是由哪次commit引入的:

根據這次提交的說明,之前procfs一直通過"file_operations"來讓模組掛接自定義的函式,而"file_operations"本身是設計給vfs用的,但進入procfs的呼叫路徑後,其實跟vfs已經沒有什麼直接的關係了。

借用人家的結構體來用看起來是省事,但每當vfs擴充套件自己的"file_operations"時,procfs也必須跟著擴充套件。vfs裡大部分的operations對procfs來說都是用不到的,這樣白白增加空間占用,實在說不過去。

currently core /proc code uses "struct file_operations" for custom hooks,

however, vfs doesn't directly call them. every time vfs expands

file_operations hook set, /proc code bloats for no reason.

introduce "struct proc_ops" which contains only those hooks which /proc

allows to call into (open, release, read, write, ioctl, mmap, poll). it

doesn't contain module pointer as well.

所以呢,procfs的維護者終於決定設計一套適合自己的operations函式,實際用到哪些,才會包含哪些,也就是這個新的"proc_ops"結構體啦。

參考:

公升級Linux核心錯誤

因為要使用ntfs 3g 核心至少2.6.22才不會有warning提示 的寫功能,所以將自己機器上的linux debian 核心從2.6.18公升級到目前最新的2.6.25.9 最後還是要生成initrd檔案的,可以使用yaird命令 這裡記錄一下公升級過程中碰到的兩個導致linux啟動pani...

centos解除安裝核心 Linux核心解除安裝和禁止更新

注意 對於可以用好幾條命令實現的,第一條命令已經驗證,其他的命令參考自網上,沒有進行驗證。檢視linux系統核心的命令有下面幾條 dpkg get selections grep linux image dpkg get selections grep linxu headers dpkg list...

linux 核心模組除錯錯誤

各位,我在編譯核心模組時有乙個錯誤調了很久也沒解決,請那位仁兄幫忙看看,666 static init int cbac init void 667 689 690 cbac requires early initialization in order to label 691 all proces...