亚洲精品久久久久久久久久久,亚洲国产精品一区二区制服,亚洲精品午夜精品,国产成人精品综合在线观看,最近2019中文字幕一页二页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

揭露內(nèi)核黑科技 - 熱補(bǔ)丁技術(shù)真容

Linux閱碼場 ? 來源:Linuxer ? 2020-06-28 09:46 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

內(nèi)核熱補(bǔ)丁是一種無需重啟操作系統(tǒng),動態(tài)為內(nèi)核打補(bǔ)丁的技術(shù)。系統(tǒng)管理員基于該技術(shù),可以在不重啟系統(tǒng)的情況下,修復(fù)內(nèi)核BUG或安全漏洞,可以在最大程度上減少系統(tǒng)宕機(jī)時間,增加系統(tǒng)的可用性。

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

從一個例子開始

作為一個小白,當(dāng)然是從一個例子開始入手會比較簡單。感謝內(nèi)核社區(qū)開發(fā)著貼心的服務(wù),在內(nèi)核代碼中,就有熱補(bǔ)丁的例子在samples/livepatch目錄下。

我們來看一個非常簡單的例子,因?yàn)樘唵瘟?,我干脆就把整個代碼都貼上來了。

我想,有一些內(nèi)核開發(fā)經(jīng)驗(yàn)的小伙伴,從這個例子中就可以猜出這個代碼的作用。

將函數(shù)cmdline_proc_show替換成livepatch_cmdline_proc_show

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

來點(diǎn)難的

上面的代碼實(shí)在是太沒有難度了,讓我們來點(diǎn)挑戰(zhàn)??纯催@個klp_enable_patch究竟做了點(diǎn)什么。

怎么樣,是不是有點(diǎn)傻眼了?這么多調(diào)用都是點(diǎn)啥?別急,其實(shí)這么多調(diào)用大多是花架子。如果你了解了klp_patch這個數(shù)據(jù)結(jié)構(gòu),我想一切都迎刃而解了。

klp_patch的數(shù)據(jù)結(jié)構(gòu)

所以說大學(xué)時候?qū)W習(xí)算法和數(shù)據(jù)結(jié)構(gòu)是非常有道理的,只可惜當(dāng)年我壓根就沒有好好學(xué)習(xí),以至于工作后不得不拼命補(bǔ)課。瞧,這時候又能用上了。

想要了解上面列出的klp_enable_patch這個函數(shù)的邏輯,還是要從klp_patch這個結(jié)構(gòu)體入手。

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

這個klp_patch就好像是一個二維數(shù)組

第一維是klp_object

第二維是klp_func

最后落實(shí)到klp_func標(biāo)注了要替換的目標(biāo)函數(shù)和替換成的新的函數(shù)。

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

真正的干貨

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

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

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

klp_get_ftrace_location

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

ops->fops.func = klp_ftrace_handler

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

ftrace_set_filter_ip

在探秘ftrace中,我們并沒有展開這個ftrace_ops結(jié)構(gòu)體。那這里我們就來展開看一下。

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

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

register_ftrace_function

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

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

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

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

驚人一躍

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

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

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

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

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

因?yàn)閗lp在設(shè)置ftrace_ops時添加了FTRACE_OPS_FL_SAVE_REGS,所以對應(yīng)的探針是ftrace_reg_caller。經(jīng)過一番刨根問底,終于發(fā)現(xiàn)了秘密。

在探針執(zhí)行ftrace_ops_list_func的前,會將調(diào)用探針的rip保存到堆棧上的regs參數(shù)中。然后在返回探針前,將rges->ip上的內(nèi)容再恢復(fù)到函數(shù)返回地址上。此時如果有klp的探針函數(shù),那么這個值就改變?yōu)榱宋覀兿敫淖兂傻暮瘮?shù)了。

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

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

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

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

補(bǔ)充知識 – 函數(shù)返回地址

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

那先說一下原理:

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

這么說有點(diǎn)抽象了,咱們可以用gdb做一個簡單的實(shí)驗(yàn)。

實(shí)驗(yàn)代碼

一個再簡單不過的add函數(shù)。

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

驗(yàn)證返回地址在堆棧上

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

(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

首先我們看到在執(zhí)行retq前,堆棧上的內(nèi)容是0x00400523。

接著我們再執(zhí)行一次stepi。

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

然后再反匯編一下,看到此時正要執(zhí)行的指令就是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.

修改返回地址

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

我們在add函數(shù)執(zhí)行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然后我們再執(zhí)行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?我們輕松的黑了一把。

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

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    4

    文章

    1433

    瀏覽量

    42377
  • 補(bǔ)丁
    +關(guān)注

    關(guān)注

    0

    文章

    27

    瀏覽量

    8749
  • 黑科技
    +關(guān)注

    關(guān)注

    14

    文章

    132

    瀏覽量

    38348

原文標(biāo)題:揭露內(nèi)核黑科技 - 熱補(bǔ)丁技術(shù)真容

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

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    【米爾RK3506國產(chǎn)開發(fā)板評測】3、實(shí)時補(bǔ)丁以及EtherCAT IGH移植

    的指令格式如下 patch -p1 < path/to/patch-x.y.z Rockchip SDK中的doc/Real-Time-Performance目錄下有相關(guān)的實(shí)時內(nèi)核補(bǔ)丁
    發(fā)表于 10-27 10:09

    從微秒級響應(yīng)到確定性延遲:深入解析米爾全志T536核心板的實(shí)時性技術(shù)突破

    樹實(shí)現(xiàn)O(log n)調(diào)度復(fù)雜度,追求整體吞吐量最大化。 實(shí)時缺陷:內(nèi)核不可搶占、自旋鎖阻塞、中斷屏蔽窗口等因素導(dǎo)致延遲不可預(yù)測。 2.2 標(biāo)準(zhǔn)內(nèi)核+軟隔離方案核心技術(shù):在標(biāo)準(zhǔn)Li
    發(fā)表于 10-22 17:25

    深入解析米爾全志T536核心板的實(shí)時性技術(shù)突破

    內(nèi)核補(bǔ)丁方案核心技術(shù):將Linux內(nèi)核改造成完全可搶占,用RT-mutex替代自旋鎖,實(shí)現(xiàn)優(yōu)先級繼承。優(yōu)勢:兼容性好,無需修改應(yīng)用程序。挑戰(zhàn):需要重新編譯
    發(fā)表于 10-17 17:41

    國產(chǎn)!全志T113-i 雙核Cortex-A7@1.2GHz 工業(yè)開發(fā)板—Linux-RT應(yīng)用開發(fā)案例

    PREEMPT機(jī)制進(jìn)行補(bǔ)丁。PREEMPT_RT補(bǔ)丁的關(guān)鍵是最小化不可搶占的內(nèi)核代碼量,同時最小化必須更改的代碼量,以便提供這種附加的可搶占性。PREEMPT_RT補(bǔ)丁利用Linux
    的頭像 發(fā)表于 07-30 10:33 ?480次閱讀
    國產(chǎn)!全志T113-i 雙核Cortex-A7@1.2GHz 工業(yè)開發(fā)板—Linux-RT應(yīng)用開發(fā)案例

    迅為RK3568開發(fā)板OpeHarmony學(xué)習(xí)開發(fā)手冊1.1-內(nèi)核移植優(yōu)化

    在上一小節(jié)的內(nèi)核移植過程中,我們重新創(chuàng)建了內(nèi)核補(bǔ)丁文件。然而,對于頻繁修改內(nèi)核源代碼進(jìn)行開發(fā)的情況來說,每次都制作內(nèi)核
    發(fā)表于 07-26 10:37

    NFC:重塑近場交互的技術(shù)內(nèi)核與場景革命

    聯(lián)動,這項(xiàng)基于 13.56MHz 頻段的短距通信技術(shù),正以 “安全閉環(huán) + 極簡交互” 的核心優(yōu)勢,重構(gòu)多行業(yè)的服務(wù)鏈路。 一、技術(shù)內(nèi)核:短距交互的底層邏輯與獨(dú)特價值 NFC 技術(shù)脫胎
    的頭像 發(fā)表于 07-23 11:19 ?1498次閱讀

    強(qiáng)實(shí)時運(yùn)動控制內(nèi)核MotionRT750(一):驅(qū)動安裝、內(nèi)核配置與使用

    強(qiáng)實(shí)時運(yùn)動控制內(nèi)核MotionRT750的驅(qū)動安裝與內(nèi)核配置
    的頭像 發(fā)表于 07-03 15:48 ?3327次閱讀
    強(qiáng)實(shí)時運(yùn)動控制<b class='flag-5'>內(nèi)核</b>MotionRT750(一):驅(qū)動安裝、<b class='flag-5'>內(nèi)核</b>配置與使用

    詳解儲能系統(tǒng)啟動技術(shù)

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

    用DevEco Studio增量補(bǔ)丁修復(fù)功能,讓鴻蒙應(yīng)用的調(diào)試效率大增

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

    用DevEco Studio增量補(bǔ)丁修復(fù)功能,讓鴻蒙應(yīng)用的調(diào)試效率大增

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

    解鎖樹莓派新玩法:Ubuntu 實(shí)時內(nèi)核安裝指南

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

    樹莓派4 性能大比拼:標(biāo)準(zhǔn)Linux與實(shí)時Linux 4.19內(nèi)核的延遲測試

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

    技術(shù)分享】迅為RK3568開發(fā)板使用TFTP加載內(nèi)核設(shè)備樹

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

    南亞科技與補(bǔ)丁科技攜手開發(fā)定制超高帶寬內(nèi)存

    Memory)的開發(fā)。 此次合作將充分融合南亞科技在10nm級DRAM技術(shù)領(lǐng)域的深厚積累,以及補(bǔ)丁科技在定制內(nèi)存產(chǎn)品設(shè)計方面的卓越能力。雙方將強(qiáng)強(qiáng)聯(lián)手,共同打造出針對AI與邊緣應(yīng)用需求的高附加值、高性能、低功耗的定制超高帶寬內(nèi)存解決方案。 這一戰(zhàn)略合作的達(dá)成,標(biāo)志著南亞
    的頭像 發(fā)表于 12-20 14:28 ?865次閱讀

    嵌入式工程師都在找的【Linux內(nèi)核調(diào)試技術(shù)】建議收藏!

    在嵌入式系統(tǒng)的開發(fā)中,Linux內(nèi)核調(diào)試是一個至關(guān)重要的環(huán)節(jié)。 隨著處理器技術(shù)的不斷進(jìn)步和嵌入式領(lǐng)域的蓬勃發(fā)展,掌握有效的內(nèi)核調(diào)試技術(shù)成為了開發(fā)者們的一項(xiàng)必備技能。本文將介紹幾種常見
    發(fā)表于 11-28 15:37