在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

揭露內核黑科技 - 熱補丁技術真容

Linux閱碼場 ? 來源:Linuxer ? 2020-06-28 09:46 ? 次閱讀

內核熱補丁是一種無需重啟操作系統,動態為內核打補丁的技術。系統管理員基于該技術,可以在不重啟系統的情況下,修復內核BUG或安全漏洞,可以在最大程度上減少系統宕機時間,增加系統的可用性。

一直很好奇內核熱補丁這個黑科技,今天終于可以揭露它的真容了。當然這章的內容強烈依賴于前一章探秘ftrace[1]。有需要的小伙伴請自取。

從一個例子開始

作為一個小白,當然是從一個例子開始入手會比較簡單。感謝內核社區開發著貼心的服務,在內核代碼中,就有熱補丁的例子在samples/livepatch目錄下。

我們來看一個非常簡單的例子,因為太簡單了,我干脆就把整個代碼都貼上來了。

我想,有一些內核開發經驗的小伙伴,從這個例子中就可以猜出這個代碼的作用。

將函數cmdline_proc_show替換成livepatch_cmdline_proc_show

怎么樣,是不是炒雞簡單?

來點難的

上面的代碼實在是太沒有難度了,讓我們來點挑戰。看看這個klp_enable_patch究竟做了點什么。

怎么樣,是不是有點傻眼了?這么多調用都是點啥?別急,其實這么多調用大多是花架子。如果你了解了klp_patch這個數據結構,我想一切都迎刃而解了。

klp_patch的數據結構

所以說大學時候學習算法和數據結構是非常有道理的,只可惜當年我壓根就沒有好好學習,以至于工作后不得不拼命補課。瞧,這時候又能用上了。

想要了解上面列出的klp_enable_patch這個函數的邏輯,還是要從klp_patch這個結構體入手。

大家可以對照這例子代碼中的klp_patch和這個圖來幫助理解。

這個klp_patch就好像是一個二維數組

第一維是klp_object

第二維是klp_func

最后落實到klp_func標注了要替換的目標函數和替換成的新的函數。

知道了這個后,再回過去看剛才那一坨初始化的代碼是不是會簡單點?其實就是做了幾個循環,把這個二維數組上所有的klp_object和klp_patch都初始化好。所有的初始化,大部分是創建對應的kobj,這樣在/sys/kernel/livepatch/目錄下就能控制每個熱補丁點了。

真正的干貨

到此為止,看了半天其實都沒有看到熱不定究竟是怎么打到內核代碼上的。別急,小編這就給您娓娓道來。

在前面初始化的代碼中,大家有沒有看到一個函數–klp_patch_func?這個函數會對每個klp_func數據執行一遍。對了,魔鬼就在這里。

這幾個可以說都是重量級的選手,讓我慢慢給您一一講解。

klp_get_ftrace_location

這個函數呢,就是要給出被替換的函數地址。首先我們在定義中并沒有給出這個old_func的地址,所以第一步是要算出這個old_func。這部分工作在函數klp_init_object_loaded中通過klp_find_object_symbol查找symbol來得到。

ops->fops.func = klp_ftrace_handler

這是什么呢?對了,如果你對ftrace還有印象,這就是我們會替換掉ftrace探針的那個函數。也就是說,當我們的想要修改的函數被執行到時,這個klp_ftrace_handler就會被調用起來干活了。

ftrace_set_filter_ip

在探秘ftrace中,我們并沒有展開這個ftrace_ops結構體。那這里我們就來展開看一下。

每個ftrace_ops上都有兩個哈希表,還記得我們操作ftrace時候有兩個文件 set_ftrace_filter / set_ftrace_notrace么?這兩個文件分別用來控制我們想跟蹤那個函數和不想跟蹤那個函數。這兩個集合在代碼中就對應了ftrace_ops中的兩個哈希表 filter_hash / notrace_hash。

所以 ftrace_set_filter_ip 就是用來將我們想要補丁的函數加到這個哈希表上的。

register_ftrace_function

這個函數的功效在探秘ftrace中已經描述過了一部分,這里我們將從另一個角度再次闡述。

register_ftrace_function函數的功效之一是將ftrace_ops結構體添加到全局鏈表ftrace_ops_list上,這么做有什么用呢?我們來看一下被ftrace插入到代碼中的函數ftrace_ops_list_func。

可以看到,每一個被ftrace改變的函數,如果在有多個ftrace_ops的情況下,會通過ftrace_ops_test()來判斷當前函數是否符合這個ftrace_ops。如果符合才會執行op->func。(注意,這個func就是剛才設置的klp_ftrace_handler了。

而這個ftrace_ops_test()是怎么做判斷的呢?對了,我想你已經猜到了,咱不是有兩個哈希表么?

驚人一躍

到此為止,我們還是圍繞著熱補丁怎么利用ftrace的框架,讓自己在特定的探針上執行,還沒有真正看到所謂的補丁是怎么打上去的。是時候來揭開這層面紗了。

通過上述的操作,klp成功的在某個探針上嵌入了函數klp_ftrace_handler。那就看看這個函數吧。

klp_ftrace_handler(ip, parent_ip, fops, regs) klp_arch_set_pc(regs, func->new_func) regs->ip = ip;

怎么樣,是不是有點吃驚,所謂的熱補丁就是這么一個語句?理論上講到這里,意思上也明白了,但是我依然想要弄清楚這個究竟是怎么一回事兒。

這一切還是要從ftrace的探針開始說起。

因為klp在設置ftrace_ops時添加了FTRACE_OPS_FL_SAVE_REGS,所以對應的探針是ftrace_reg_caller。經過一番刨根問底,終于發現了秘密。

在探針執行ftrace_ops_list_func的前,會將調用探針的rip保存到堆棧上的regs參數中。然后在返回探針前,將rges->ip上的內容再恢復到函數返回地址上。此時如果有klp的探針函數,那么這個值就改變為了我們想改變成的函數了。

怎么樣,原來黑科技是這么玩的!

這事兒有點抽象,讓我畫一個簡易的堆棧示意一下。

一切的秘密都在這個堆棧上的return address里了。

到這里我才反應過來,原來黑科技就是黑客用的科技啊 :)

補充知識 – 函數返回地址

上面的這個黑科技運用到了一個x86架構下,如何保存函數返回是運行的地址的原理。也就是指令callq/retq是如何改變堆棧的。

那先說一下原理:

callq指令在跳轉到目標代碼前,會將自身的下一條指令的地址放到堆棧上。retq執行返回時,會從堆棧上取出目標地址然后跳轉到那里。

這么說有點抽象了,咱們可以用gdb做一個簡單的實驗。

實驗代碼

一個再簡單不過的add函數。

#include int add(int a, int b){ return a + b;} int main(){ int a = 3; a = a + 3; add(a, 2); return 0;}

驗證返回地址在堆棧上

使用gdb在add返回前停住,然后用下面的指令查看狀態。

(gdb) disassembleDump of assembler code for function add: 0x00000000004004ed <+0>: push %rbp 0x00000000004004ee <+1>: mov %rsp,%rbp 0x00000000004004f1 <+4>: mov %edi,-0x4(%rbp) 0x00000000004004f4 <+7>: mov %esi,-0x8(%rbp) 0x00000000004004f7 <+10>: mov -0x8(%rbp),%eax 0x00000000004004fa <+13>: mov -0x4(%rbp),%edx 0x00000000004004fd <+16>: add %edx,%eax 0x00000000004004ff <+18>: pop %rbp=> 0x0000000000400500 <+19>: retqEnd of assembler dump.(gdb) info registers rsprsp 0x7fffffffe2e8 0x7fffffffe2e8(gdb) x/1xw 0x7fffffffe2e80x7fffffffe2e8: 0x00400523

首先我們看到在執行retq前,堆棧上的內容是0x00400523。

接著我們再執行一次stepi

(gdb) stepimain () at main.c:1313 return 0;(gdb) info registers rsprsp 0x7fffffffe2f0 0x7fffffffe2f0(gdb) info registers riprip0x4005230x400523此時我們看到堆棧變化了,而且rip的值和剛才堆棧上的值是一樣的。

然后再反匯編一下,看到此時正要執行的指令就是callq后面的一條指令。

(gdb) disassembleDump of assembler code for function main: 0x0000000000400501 <+0>: push %rbp 0x0000000000400502 <+1>: mov %rsp,%rbp 0x0000000000400505 <+4>: sub $0x10,%rsp 0x0000000000400509 <+8>: movl $0x3,-0x4(%rbp) 0x0000000000400510 <+15>: addl $0x3,-0x4(%rbp) 0x0000000000400514 <+19>: mov -0x4(%rbp),%eax 0x0000000000400517 <+22>: mov $0x2,%esi 0x000000000040051c <+27>: mov %eax,%edi 0x000000000040051e <+29>: callq 0x4004ed => 0x0000000000400523 <+34>: mov $0x0,%eax 0x0000000000400528 <+39>: leaveq 0x0000000000400529 <+40>: retqEnd of assembler dump.

修改返回地址

接下來我們還能模擬熱補丁,來修改這個返回值。(當然比較簡陋些。)

我們在add函數執行retq前停住,用gdb改變堆棧上的值,讓他指向mov的下一條指令leaveq。

(gdb) disassembleDump of assembler code for function add: 0x00000000004004ed <+0>: push %rbp 0x00000000004004ee <+1>: mov %rsp,%rbp 0x00000000004004f1 <+4>: mov %edi,-0x4(%rbp) 0x00000000004004f4 <+7>: mov %esi,-0x8(%rbp) 0x00000000004004f7 <+10>: mov -0x8(%rbp),%eax 0x00000000004004fa <+13>: mov -0x4(%rbp),%edx 0x00000000004004fd <+16>: add %edx,%eax 0x00000000004004ff <+18>: pop %rbp=> 0x0000000000400500 <+19>: retqEnd of assembler dump.(gdb) info registers rsprsp 0x7fffffffe2e8 0x7fffffffe2e8(gdb) x/1xw 0x7fffffffe2e80x7fffffffe2e8: 0x00400523(gdb) set *((int *) 0x7fffffffe2e8) = 0x00400528(gdb) x/1xw 0x7fffffffe2e80x7fffffffe2e8: 0x00400528然后我們再執行stepi

(gdb) stepimain () at main.c:1414 }(gdb) info registers riprip 0x400528 0x400528 (gdb) disassembleDump of assembler code for function main: 0x0000000000400501 <+0>: push %rbp 0x0000000000400502 <+1>: mov %rsp,%rbp 0x0000000000400505 <+4>: sub $0x10,%rsp 0x0000000000400509 <+8>: movl $0x3,-0x4(%rbp) 0x0000000000400510 <+15>: addl $0x3,-0x4(%rbp) 0x0000000000400514 <+19>: mov -0x4(%rbp),%eax 0x0000000000400517 <+22>: mov $0x2,%esi 0x000000000040051c <+27>: mov %eax,%edi 0x000000000040051e <+29>: callq 0x4004ed 0x0000000000400523 <+34>: mov $0x0,%eax=> 0x0000000000400528 <+39>: leaveq 0x0000000000400529 <+40>: retqEnd of assembler dump.

瞧,這下是不是直接走到了leaveq,而不是剛才的mov?我們輕松的黑了一把。

好了,到這里就真的結束了,希望大家有所收獲。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內核
    +關注

    關注

    3

    文章

    1410

    瀏覽量

    41118
  • 補丁
    +關注

    關注

    0

    文章

    27

    瀏覽量

    8651
  • 黑科技
    +關注

    關注

    14

    文章

    129

    瀏覽量

    37804

原文標題:揭露內核黑科技 - 熱補丁技術真容

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    詳解儲能系統啟動技術

    儲能系統的“啟動”是指在電力系統發生大規模停電或故障后,利用儲能系統作為備用電源,重新啟動電網的過程。在這種情況下,電網處于完全停電的狀態,即所謂的“”狀態,而儲能系統則提供了必要的電能來逐步恢復電網的正常運行。
    的頭像 發表于 05-29 10:16 ?192次閱讀
    詳解儲能系統<b class='flag-5'>黑</b>啟動<b class='flag-5'>技術</b>

    用DevEco Studio增量補丁修復功能,讓鴻蒙應用的調試效率大增

    DevEco Studio中得到了很好的解答,而增量補丁修復便是其中的核心特性之一。今天,我們要深入探討鴻蒙應用增量補丁修復及其兩個能夠大幅加速開發進度的強大功能——Hot Reload和Apply
    發表于 04-14 17:35

    用DevEco Studio增量補丁修復功能,讓鴻蒙應用的調試效率大增

    DevEco Studio中得到了很好的解答,而增量補丁修復便是其中的核心特性之一。今天,我們要深入探討鴻蒙應用增量補丁修復及其兩個能夠大幅加速開發進度的強大功能——Hot Reload和Apply
    發表于 04-14 14:47

    解鎖樹莓派新玩法:Ubuntu 實時內核安裝指南

    警告:這只是我在業余時間進行的一個個人項目,并未得到Canonical的認可或支持。你即將安裝的內核可能不會收到任何補丁或安全更新。它未經徹底測試,可能會使你的系統無法使用,甚至損壞你的數據。請自行承擔風險。
    的頭像 發表于 03-25 09:40 ?235次閱讀
    解鎖樹莓派新玩法:Ubuntu 實時<b class='flag-5'>內核</b>安裝指南

    樹莓派4 性能大比拼:標準Linux與實時Linux 4.19內核的延遲測試

    引言本文是對我之前關于RaspberryPi3同一主題的帖子的更新。與之前的帖子一樣,我使用的是隨Raspbian鏡像提供的標準內核,以及應用了RT補丁的相似內核版本。對于實時版,我
    的頭像 發表于 03-25 09:39 ?259次閱讀
    樹莓派4 性能大比拼:標準Linux與實時Linux 4.19<b class='flag-5'>內核</b>的延遲測試

    技術分享】迅為RK3568開發板使用TFTP加載內核設備樹

    技術分享】迅為RK3568開發板使用TFTP加載內核設備樹
    的頭像 發表于 02-21 14:04 ?588次閱讀
    【<b class='flag-5'>技術</b>分享】迅為RK3568開發板使用TFTP加載<b class='flag-5'>內核</b>設備樹

    南亞科技與補丁科技攜手開發定制超高帶寬內存

    Memory)的開發。 此次合作將充分融合南亞科技在10nm級DRAM技術領域的深厚積累,以及補丁科技在定制內存產品設計方面的卓越能力。雙方將強強聯手,共同打造出針對AI與邊緣應用需求的高附加值、高性能、低功耗的定制超高帶寬內存解決方案。 這一戰略合作的達成,標志著南亞
    的頭像 發表于 12-20 14:28 ?555次閱讀

    嵌入式工程師都在找的【Linux內核調試技術】建議收藏!

    在嵌入式系統的開發中,Linux內核調試是一個至關重要的環節。 隨著處理器技術的不斷進步和嵌入式領域的蓬勃發展,掌握有效的內核調試技術成為了開發者們的一項必備技能。本文將介紹幾種常見
    發表于 11-28 15:37

    TVP5150AM1補丁代碼下載指南

    電子發燒友網站提供《TVP5150AM1補丁代碼下載指南.pdf》資料免費下載
    發表于 09-30 14:11 ?0次下載
    TVP5150AM1<b class='flag-5'>補丁</b>代碼下載指南

    TVP5147M1補丁代碼下載指南

    電子發燒友網站提供《TVP5147M1補丁代碼下載指南.pdf》資料免費下載
    發表于 09-30 11:27 ?0次下載
    TVP5147M1<b class='flag-5'>補丁</b>代碼下載指南

    TVP5160補丁代碼下載指南

    電子發燒友網站提供《TVP5160補丁代碼下載指南.pdf》資料免費下載
    發表于 09-30 11:01 ?0次下載
    TVP5160<b class='flag-5'>補丁</b>代碼下載指南

    TVP5158補丁代碼下載指南

    電子發燒友網站提供《TVP5158補丁代碼下載指南.pdf》資料免費下載
    發表于 09-30 10:48 ?0次下載
    TVP5158<b class='flag-5'>補丁</b>代碼下載指南

    TVP5151補丁代碼下載指南

    電子發燒友網站提供《TVP5151補丁代碼下載指南.pdf》資料免費下載
    發表于 09-30 09:37 ?0次下載
    TVP5151<b class='flag-5'>補丁</b>代碼下載指南

    迅為RK3588開發板!神話悟空,啟動?

    和討論,提高會議效率。 (3)教育培訓:教師可以使用投屏將教學內容從平板或電腦傳輸到教室的電子白板或投影設備上,增強課堂互動性和教學效果,方便學生理解和參與。 雖然視頻中的《神話:悟空》是通過投屏技術
    發表于 09-23 10:48

    Linux內核測試技術

    內核測試技術是實現這一目標的關鍵手段。本文將詳細介紹 Linux 內核測試的各種技術,包括單元測試、集成測試、功能測試和性能測試等,并討論不同測試方法的優缺點及其適用場景。
    的頭像 發表于 08-13 13:42 ?921次閱讀
    Linux<b class='flag-5'>內核</b>測試<b class='flag-5'>技術</b>
    主站蜘蛛池模板: 欧美亚洲网站 | 美女黄色一级毛片 | 尻逼尻逼 | 欧美成人免费观看bbb | 久久天天躁狠狠躁夜夜爽蜜月 | 国产在线播放成人免费 | 狠狠狠色丁香婷婷综合久久五月 | 女人爽到喷水的视频大全在线观看 | 91噜噜噜| 日本在线观看一区 | 欧美亚洲专区 | 亚洲婷婷六月 | vip影视免费观看 | cijilu刺激 国产免费的 | 午夜小视频在线 | 高清视频免费观看 | 国产三级日本三级日产三 | 国产大乳孕妇喷奶水在线观看 | 天堂在线网站 | 三区在线观看 | 起碰免费视频 | 天堂网在线看 | 国产精品网址你懂的 | 七月婷婷精品视频在线观看 | 手机在线黄色网址 | 国产精品va在线观看不 | 国产白白白在线永久播放 | 亚洲综合五月天婷 | 日本不卡免费高清一级视频 | 泰剧天堂| 日韩一级欧美一级 | 老子影院午夜精品欧美视频 | 亚洲午夜日韩高清一区 | 成人最新午夜免费视频 | 最新版天堂中文在线官网 | 久热国产精品视频 | 日本欧美色图 | 久久永久视频 | 一区二区三区伦理高清 | 亚洲色妞 | 亚洲特黄大黄一级毛片 |