91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

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

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

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

Linux內(nèi)核態(tài)缺頁(yè)會(huì)發(fā)生什么 - 玩轉(zhuǎn)Exception fixup表

Linux閱碼場(chǎng) ? 來源:Linuxer ? 2020-06-03 15:08 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

近日,我在寫內(nèi)核模塊的時(shí)候犯了一個(gè)低級(jí)錯(cuò)誤:

直接access用戶態(tài)的內(nèi)存而沒有使用copy_to_user/copy_from_user!

在內(nèi)核看來,用戶態(tài)提供的虛擬地址是不可信的,所以在一旦在內(nèi)核態(tài)訪問用戶態(tài)內(nèi)存發(fā)生缺頁(yè)中斷,處理起來是非常棘手的。

Linux內(nèi)核的做法是提供了一張 異常處理表 ,使用專有的函數(shù)來訪問用戶態(tài)內(nèi)存。類似 try-catch塊一般。具體詳情可參見copy_to_user/copy_from_user的實(shí)現(xiàn)以及內(nèi)核文檔Documentation/x86/exception-tables.txt的描述。

本來簡(jiǎn)單看下這個(gè)異常處理表能怎么玩。

首先,我們可以寫一片代碼,將內(nèi)核的異常處理表dump下來:

// show_extable.c#include #include int (*_lookup_symbol_name)(unsigned long, char *);unsigned long (*_get_symbol_pos)(unsigned long, void *, void *);unsigned long start_ex, end_ex; int init_module(void){ unsigned long i; unsigned long orig, fixup, originsn, fixinsn, offset, size; char name[128], fixname[128]; _lookup_symbol_name = (void *)kallsyms_lookup_name("lookup_symbol_name"); _get_symbol_pos = (void *)kallsyms_lookup_name("get_symbol_pos"); start_ex = (unsigned long)kallsyms_lookup_name("__start___ex_table"); end_ex = (unsigned long)kallsyms_lookup_name("__stop___ex_table"); // 按照exception_table_entry的sizeof從start遍歷到end。 for(i = start_ex; i < end_ex; i += 2*sizeof(unsigned long)) { orig = i; // 取出exception_table_entry的insn字段地址。 fixup = i + sizeof(unsigned int); // 取出fixup字段地址。 originsn = orig + *(unsigned int *)orig; // 根據(jù)相對(duì)偏移字段求出絕對(duì)地址 originsn |= 0xffffffff00000000; fixinsn = fixup + *(unsigned int *)fixup; fixinsn |= 0xffffffff00000000; _get_symbol_pos(originsn, &size, &offset); _lookup_symbol_name(originsn, name); _lookup_symbol_name(fixinsn, fixname); printk("[%lx]%s+0x%lx/0x%lx [%lx]%s ", originsn, name, offset, size, fixinsn, fixname); } return -1;}MODULE_LICENSE("GPL");

我們看下輸出:

# ___sys_recvmsg+0x253位置發(fā)生異常,跳轉(zhuǎn)到ffffffff81649396處理異常。[ 7655.267616] [ffffffff8150d7a3]___sys_recvmsg+0x253/0x2b0 [ffffffff81649396]bad_to_user...# create_elf_tables+0x3cf位置處如果發(fā)生異常,跳轉(zhuǎn)到ffffffff81648a07地址執(zhí)行異常處理。[ 7655.267727] [ffffffff8163250e]create_elf_tables+0x3cf/0x509 [ffffffff81648a1b]bad_gs

一般而言,類似bad_to_user,bad_from_user之類的異常處理函數(shù)都是直接返回用戶一個(gè)錯(cuò)誤碼,比如Bad address之類,并不是直接用戶程序直接段錯(cuò)誤,這一點(diǎn)和用戶態(tài)訪問非法地址直接發(fā)送SIGSEGV有所不同。比如:

#include int main(int argc, char **argv){ int fd; int ret; char *buf = (char *)0x56; // 顯然是一個(gè)非法地址。 fd = open("/proc/sys/net/nf_conntrack_max", O_RDWR | O_CREAT, S_IRWXU); perror("open"); ret = read(fd, buf, 100); perror("read");}

執(zhí)行之:

[root@localhost test]# ./a.outopen: Successread: Bad address # 沒有段錯(cuò)誤,只是一個(gè)普通錯(cuò)誤。

我們能不能將其行為修改成和用戶態(tài)訪問非法地址一致呢?簡(jiǎn)單,替換掉bad_to_user即可,代碼如下:

// fix_ex.c#include #include #include int (*_lookup_symbol_name)(unsigned long, char *);unsigned long (*_get_symbol_pos)(unsigned long, void *, void *);unsigned long start_ex, end_ex;void *_bad_from_user, *_bad_to_user; void kill_user_from(void){ printk("經(jīng)理!rush tighten beat electric discourse! "); force_sig(SIGSEGV, current);} void kill_user_to(void){ printk("經(jīng)理!rush tighten beat electric discourse! SB 皮鞋 "); force_sig(SIGSEGV, current);} unsigned int old, new; int (*_lookup_symbol_name)(unsigned long, char *);unsigned long (*_get_symbol_pos)(unsigned long, void *, void *); int hook_fixup(void *origfunc1, void *origfunc2, void *newfunc1, void *newfunc2){ unsigned long i; unsigned long fixup, fixinsn; char fixname[128]; for(i = start_ex; i < end_ex; i += 2*sizeof(unsigned long)) { fixup = i + sizeof(unsigned int); fixinsn = fixup + *(unsigned int *)fixup; fixinsn |= 0xffffffff00000000; _lookup_symbol_name(fixinsn, fixname); if (!strcmp(fixname, origfunc1) || !strcmp(fixname, origfunc2)) { unsigned long new; unsigned int newfix; if (!strcmp(fixname, origfunc1)) { new = (unsigned long)newfunc1; } else { new = (unsigned long)newfunc2; } new -= fixup; newfix = (unsigned int)new; *(unsigned int *)fixup = newfix; } } return 0;} int init_module(void){ _lookup_symbol_name = (void *)kallsyms_lookup_name("lookup_symbol_name"); _get_symbol_pos = (void *)kallsyms_lookup_name("get_symbol_pos"); _bad_from_user = (void *)kallsyms_lookup_name("bad_from_user"); _bad_to_user = (void *)kallsyms_lookup_name("bad_to_user"); start_ex = (unsigned long)kallsyms_lookup_name("__start___ex_table"); end_ex = (unsigned long)kallsyms_lookup_name("__stop___ex_table"); hook_fixup("bad_from_user", "bad_to_user", kill_user_from, kill_user_to); return 0;}void cleanup_module(void){ hook_fixup("kill_user_from", "kill_user_to", _bad_from_user, _bad_to_user);} MODULE_LICENSE("GPL");

編譯,加載,重新執(zhí)行我們的a.out:

[root@localhost test]# insmod ./fix_ex.ko[root@localhost test]# ./a.outopen: Success段錯(cuò)誤[root@localhost test]# dmesg[ 8686.091738] 經(jīng)理!rush tighten beat electric discourse! SB 皮鞋[root@localhost test]#

發(fā)生了段錯(cuò)誤,并且打印出了讓經(jīng)理趕緊打電話的句子。

其實(shí),我的目的并不是這樣的,我真正的意思是,Linux的異常處理鏈表,又是一個(gè)藏污納垢的好地方,我們可以在上面的hook函數(shù)中藏一些代碼,比如說inline hook之類的,然后呢?然后靜悄悄地等待用戶態(tài)進(jìn)程的bug導(dǎo)致異常處理被執(zhí)行。將代碼注入的時(shí)間線拉長(zhǎng),從而更難讓運(yùn)維和經(jīng)理注意到。

讓代碼注入的時(shí)間點(diǎn)和模塊插入的時(shí)間點(diǎn)分開,讓事情更加混亂。不過,注意好隱藏模塊或者oneshot哦。

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

    關(guān)注

    7

    文章

    2837

    瀏覽量

    53282
  • Linux
    +關(guān)注

    關(guān)注

    88

    文章

    11758

    瀏覽量

    219006
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4417

    瀏覽量

    67499

原文標(biāo)題:Linux內(nèi)核態(tài)缺頁(yè)會(huì)發(fā)生什么 - 玩轉(zhuǎn)Exception fixup表

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

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

掃碼添加小助手

加入工程師交流群

    評(píng)論

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

    Linux內(nèi)核的“心跳”:jiffies如何為系統(tǒng)計(jì)時(shí)?

    Linux 內(nèi)核的世界里,有一個(gè)默默工作的 "計(jì)時(shí)器"——jiffies。它不像我們手機(jī)上的時(shí)鐘那樣顯示年月日,卻掌控著內(nèi)核中絕大多數(shù)時(shí)間相關(guān)的操作:從進(jìn)程調(diào)度到設(shè)備驅(qū)動(dòng)的定時(shí)檢查,都離不開它的身影。
    的頭像 發(fā)表于 02-04 16:27 ?814次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>的“心跳”:jiffies如何為系統(tǒng)計(jì)時(shí)?

    深入RK3588內(nèi)核:rockchip_linux_defconfig的作用與調(diào)試價(jià)值

    在 RK3588 芯片的 Linux 開發(fā)中,有一個(gè)文件始終是開發(fā)者繞不開的核心 ——kernel/arch/arm64/configs/rockchip_linux_defconfig。無論是首次
    的頭像 發(fā)表于 02-03 15:56 ?1154次閱讀
    深入RK3588<b class='flag-5'>內(nèi)核</b>:rockchip_<b class='flag-5'>linux</b>_defconfig的作用與調(diào)試價(jià)值

    Linux系統(tǒng)內(nèi)核參數(shù)調(diào)優(yōu)實(shí)戰(zhàn)指南

    Linux 內(nèi)核參數(shù)調(diào)優(yōu)是系統(tǒng)性能優(yōu)化的核心環(huán)節(jié)。隨著云原生架構(gòu)的普及和硬件性能的飛速提升,默認(rèn)的內(nèi)核參數(shù)配置往往無法充分發(fā)揮系統(tǒng)潛力。在高并發(fā) Web 服務(wù)、大數(shù)據(jù)處理、容器化部署等場(chǎng)景下,合理的
    的頭像 發(fā)表于 01-28 14:27 ?426次閱讀

    【「Linux 設(shè)備驅(qū)動(dòng)開發(fā)(第 2 版)」閱讀體驗(yàn)】+讀深入理解Linux內(nèi)核內(nèi)存分配

    時(shí)復(fù)用”,在fork()系統(tǒng)調(diào)用中廣泛使用;中斷上下文中發(fā)生缺頁(yè)中斷會(huì)導(dǎo)致雙重故障中斷,通常會(huì)使內(nèi)核崩潰等。經(jīng)過這段時(shí)間的閱讀,收獲頗豐,此書有不少關(guān)于內(nèi)核開發(fā)的新內(nèi)容值得本人深入學(xué)
    發(fā)表于 01-16 20:05

    【「Linux 設(shè)備驅(qū)動(dòng)開發(fā)(第 2 版)」閱讀體驗(yàn)】Linux內(nèi)核開發(fā)基礎(chǔ)

    感謝電子發(fā)燒友論壇提供的《Linux設(shè)備驅(qū)動(dòng)開發(fā)(第2版)》閱讀機(jī)會(huì),測(cè)評(píng)將從Linux內(nèi)核開發(fā)基礎(chǔ)、Linux內(nèi)核平臺(tái)抽象和設(shè)備驅(qū)動(dòng)程序、
    發(fā)表于 01-12 22:45

    深入Linux內(nèi)核:進(jìn)程調(diào)度的核心邏輯與實(shí)現(xiàn)細(xì)節(jié)

    ,背后都離不開內(nèi)核調(diào)度算法的精準(zhǔn)操控。今天,我們就從優(yōu)先級(jí)、調(diào)度算法、時(shí)間片分配到底層實(shí)現(xiàn),全方位拆解Linux內(nèi)核進(jìn)程調(diào)度的核心邏輯。 一、進(jìn)程調(diào)度的“身份標(biāo)識(shí)”:優(yōu)先級(jí)與分類 要理解調(diào)度邏輯,首先得搞懂:進(jìn)程憑什么“插隊(duì)”?
    的頭像 發(fā)表于 12-24 07:05 ?4299次閱讀
    深入<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>:進(jìn)程調(diào)度的核心邏輯與實(shí)現(xiàn)細(xì)節(jié)

    Linux內(nèi)核日志玩明白了嗎?printk調(diào)試神器全解析

    前言:做Linux驅(qū)動(dòng)開發(fā)或內(nèi)核調(diào)試的朋友,一定對(duì)printk不陌生,但你真的會(huì)用它嗎?為什么同樣是調(diào)試RK3588內(nèi)核,別人能精準(zhǔn)捕捉關(guān)鍵錯(cuò)誤,你卻被海量日志淹沒?今天就帶大家吃透printk
    的頭像 發(fā)表于 12-19 08:32 ?860次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>日志玩明白了嗎?printk調(diào)試神器全解析

    基于 DR1M90 的 Linux-RT 內(nèi)核開發(fā):從編譯配置到 GPIO / 按鍵應(yīng)用實(shí)現(xiàn)(1)

    本手冊(cè)由創(chuàng)龍科技研發(fā),針對(duì) DR1M90,詳述 Linux-RT 實(shí)時(shí)內(nèi)核開發(fā):含實(shí)時(shí)性測(cè)試(LinuxLinux-RT 對(duì)比、CPU 空載 / 滿負(fù)荷 / 隔離狀態(tài)測(cè)試)、
    的頭像 發(fā)表于 12-02 10:38 ?1175次閱讀
    基于 DR1M90 的 <b class='flag-5'>Linux</b>-RT <b class='flag-5'>內(nèi)核</b>開發(fā):從編譯配置到 GPIO / 按鍵應(yīng)用實(shí)現(xiàn)(1)

    Linux內(nèi)核模塊的加載機(jī)制

    Linux內(nèi)核模塊通常是.ko文件,也就是Kernel Object的縮寫。這些文件是ELF格式的,但和用戶空間的程序不同,它們包含的是特定于內(nèi)核的信息。比如,模塊的元數(shù)據(jù),像作者、許可證、描述等
    發(fā)表于 11-25 06:59

    Linux內(nèi)核printk日志級(jí)別全解析:從參數(shù)解讀到實(shí)操配置

    一、開篇:一個(gè)命令引出的核心問題 在?Linux?終端執(zhí)行?cat /proc/sys/kernel/printk,你可能會(huì)看到這樣的輸出: 這串?dāng)?shù)字不是隨機(jī)的,而是內(nèi)核日志系統(tǒng)的“核心配置開關(guān)
    的頭像 發(fā)表于 11-20 15:54 ?1696次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>printk日志級(jí)別全解析:從參數(shù)解讀到實(shí)操配置

    探索操作系統(tǒng)底層的關(guān)鍵接口

      在linux中,將程序的運(yùn)行空間分為內(nèi)核空間與用戶空間(內(nèi)核態(tài)和用戶態(tài)),在邏輯上它們之間是相互隔離的,因此用戶程序不能訪問
    的頭像 發(fā)表于 11-08 12:42 ?743次閱讀

    deepin亮相2025中國(guó)Linux內(nèi)核開發(fā)者大會(huì)

    11 月 1 日,第二十屆中國(guó) Linux 內(nèi)核開發(fā)者大會(huì)(CLK)在深圳舉辦。CLK 作為國(guó)內(nèi) Linux 內(nèi)核領(lǐng)域極具影響力的峰會(huì),由清華大學(xué)、Intel、華為、阿里云、富士通南大
    的頭像 發(fā)表于 11-05 17:59 ?815次閱讀

    Linux內(nèi)核參數(shù)調(diào)優(yōu)方案

    在高并發(fā)微服務(wù)環(huán)境中,網(wǎng)絡(luò)性能往往成為K8s集群的瓶頸。本文將深入探討如何通過精細(xì)化的Linux內(nèi)核參數(shù)調(diào)優(yōu),讓你的K8s節(jié)點(diǎn)網(wǎng)絡(luò)性能提升30%以上。
    的頭像 發(fā)表于 08-06 17:50 ?947次閱讀

    如何配置和驗(yàn)證Linux內(nèi)核參數(shù)

    Linux系統(tǒng)運(yùn)維和性能優(yōu)化中,內(nèi)核參數(shù)(sysctl)的配置至關(guān)重要。合理的參數(shù)調(diào)整可以顯著提升網(wǎng)絡(luò)性能、系統(tǒng)穩(wěn)定性及資源利用率。然而,僅僅修改參數(shù)是不夠的,如何驗(yàn)證這些參數(shù)是否生效同樣關(guān)鍵。
    的頭像 發(fā)表于 05-29 17:40 ?1150次閱讀

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

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