高清视频在线观看免费播放器-伊人日本-色九月综合-18禁止看的免费污网站-免费观看性行为视频的网站-天天碰天天操-久久精品国产欧美日韩99热-中文字幕在线视频不卡-国产偷人妻精品一区二区在线-国内精品久-伊人影院在线看-密臀av一区-久久综合五月丁香久久激情-福利一区福利二区-gg国产精品国内免费观看-国产精品 高清 尿 小便 嘘嘘

當前位置: 首頁 >綜合 > 正文

世界實時:Linux內核加載ELF文件源碼分析,你學會了嗎?

2023-05-08 08:10:28 來源:FreeBuf.COM
一、源碼版本

1)版本:V6.3-rc7,x862)elf文件加載源碼:fs/binfmt_elf.c

二、Linux可執行文件注冊

Linux支持多種不同格式的可執行程序,這些可執行 程序的加載方式由linux\binfmts.h文件中的linux_binfmt結構體進行定義:


(資料圖片僅供參考)

struct linux_binfmt { struct list_head lh; struct module *module; int (*load_binary)(struct linux_binprm *); int (*load_shlib)(struct file *);#ifdef CONFIG_COREDUMP int (*core_dump)(struct coredump_params *cprm); unsigned long min_coredump; /* minimal dump size */#endif} __randomize_layout;

結構體定義了可執行程序的3中不同的加載模式:

加載模式

備注

load_binary

讀取可執行文件內容并加載當前進程建立新的執行環境

load_shlib

動態加載共享庫到已有進程

core_dump

存放當前進程的執行上下文到core文件中

每一種系統支持的可執行文件都對應一個linux_binfmt對象,統一注冊在一個鏈表中,通過register_binfmt和unregister_binfmt函數編輯鏈表。在執行可執行程序時,內核通過list_for_each_enrty遍歷鏈表中注冊的linux_binfmt對象,使用正確的加載方式進行加載。elf文件的linux_binfmt對象結構如下,該結構體定義了elf文件由load_elf_binary函數加載:

static struct linux_binfmt elf_format = { .module = THIS_MODULE, .load_binary = load_elf_binary, .load_shlib = load_elf_library,#ifdef CONFIG_COREDUMP .core_dump = elf_core_dump, .min_coredump = ELF_EXEC_PAGESIZE,#endif};三、load_elf_binary函數分析1、文件格式校驗

struct elfhdr *elf_ex = (struct elfhdr *)bprm->buf; retval = -ENOEXEC;/* First of all, some simple consistency checks */if (memcmp(elf_ex->e_ident, ELFMAG, SELFMAG) != 0) goto out; if (elf_ex->e_type != ET_EXEC && elf_ex->e_type != ET_DYN) goto out; if (!elf_check_arch(elf_ex)) goto out; if (elf_check_fdpic(elf_ex)) goto out; if (!bprm->file->f_op->mmap) goto out;

程序首先讀取了e_ident中的魔數并進行了校驗,elf_ident是ELF文件最頭部的一個長度為16字節的數組,不區分架構和系統位數。e_ident起始的4個字節固定為\0x7fELF,通過校驗該位可以確定是否為elf文件。然后識別文件是否為可執行文件或動態鏈接文件,ELF文件當前主要有4種格式,分別為可重定位文件(ET_REL)、可執行文件(ET_EXEC)、共享目標文件(ET_DYN)和core文件(ET_CORE)。load_elf_binary函數只負責解析exec和dyn文件。最后還解析了文件依賴的系統架構等必要項。

2、讀取程序頭

static struct elf_phdr *load_elf_phdrs(const struct elfhdr *elf_ex, struct file *elf_file){ struct elf_phdr *elf_phdata = NULL; int retval = -1; unsigned int size; /* * If the size of this structure has changed, then punt, since * we will be doing the wrong thing. */ if (elf_ex->e_phentsize != sizeof(struct elf_phdr)) goto out; /* Sanity check the number of program headers... */ /* ...and their total size. */ size = sizeof(struct elf_phdr) * elf_ex->e_phnum; if (size == 0 || size > 65536 || size > ELF_MIN_ALIGN) goto out; elf_phdata = kmalloc(size, GFP_KERNEL); if (!elf_phdata) goto out; /* Read in the program headers */ retval = elf_read(elf_file, elf_phdata, size, elf_ex->e_phoff); out: if (retval) { kfree(elf_phdata); elf_phdata = NULL; } return elf_phdata;}

程序頭是描述與程序執行直接相關的目標文件結構信息,用于在文件中定位各個段的映像,同時包含其他一些用來為程序創建進程映像所必須的信息。

3、讀取解釋器段

elf_ppnt = elf_phdata; for (i = 0; i < elf_ex->e_phnum; i++, elf_ppnt++) { char *elf_interpreter; if (elf_ppnt->p_type == PT_GNU_PROPERTY) { elf_property_phdata = elf_ppnt; continue; } if (elf_ppnt->p_type != PT_INTERP) continue; /* * This is the program interpreter used for shared libraries - * for now assume that this is an a.out format binary. */ retval = -ENOEXEC; if (elf_ppnt->p_filesz > PATH_MAX || elf_ppnt->p_filesz < 2) goto out_free_ph; retval = -ENOMEM; elf_interpreter = kmalloc(elf_ppnt->p_filesz, GFP_KERNEL); if (!elf_interpreter) goto out_free_ph; retval = elf_read(bprm->file, elf_interpreter, elf_ppnt->p_filesz, elf_ppnt->p_offset); if (retval < 0) goto out_free_interp; /* make sure path is NULL terminated */ retval = -ENOEXEC; if (elf_interpreter[elf_ppnt->p_filesz - 1] != "\0") goto out_free_interp; interpreter = open_exec(elf_interpreter); kfree(elf_interpreter); retval = PTR_ERR(interpreter); if (IS_ERR(interpreter)) goto out_free_ph; /* * If the binary is not readable then enforce mm->dumpable = 0 * regardless of the interpreter"s permissions. */ would_dump(bprm, interpreter); interp_elf_ex = kmalloc(sizeof(*interp_elf_ex), GFP_KERNEL); if (!interp_elf_ex) { retval = -ENOMEM; goto out_free_file; } /* Get the exec headers */ retval = elf_read(interpreter, interp_elf_ex, sizeof(*interp_elf_ex), 0); if (retval < 0) goto out_free_dentry; break; out_free_interp: kfree(elf_interpreter); goto out_free_ph; }

如果程序需要動態鏈接,則需要加載解釋器段(PT_INTERP),程序遍歷所有的程序頭,識別到解釋器段后,讀取該段的內容。解釋器段實際上是標明解釋器程序文件路徑的字符串,內核根據字符串指向的文件,使用open_exec函數打開解釋器。

4、??蓤绦袑傩约捌渌ㄖ菩畔@取

elf_ppnt = elf_phdata; for (i = 0; i < elf_ex->e_phnum; i++, elf_ppnt++) switch (elf_ppnt->p_type) { case PT_GNU_STACK: if (elf_ppnt->p_flags & PF_X) executable_stack = EXSTACK_ENABLE_X; else executable_stack = EXSTACK_DISABLE_X; break; case PT_LOPROC ... PT_HIPROC: retval = arch_elf_pt_proc(elf_ex, elf_ppnt, bprm->file, false, &arch_state); if (retval) goto out_free_dentry; break; }

同樣通過for循環遍歷,如果識別到棧屬性段(PT_GNU_STACK),根據程序頭中的p_flags標志位判定棧的可執行屬性。如果識別到處理器專用語義段(PT_LOPROC至PT_HIPROC之間),則調用arch_elf_pt_proc函數完成相應的配置。

5、讀取解釋器

if (interpreter) { retval = -ELIBBAD; /* Not an ELF interpreter */ if (memcmp(interp_elf_ex->e_ident, ELFMAG, SELFMAG) != 0) goto out_free_dentry; /* Verify the interpreter has a valid arch */ if (!elf_check_arch(interp_elf_ex) || elf_check_fdpic(interp_elf_ex)) goto out_free_dentry; /* Load the interpreter program headers */ interp_elf_phdata = load_elf_phdrs(interp_elf_ex, interpreter); if (!interp_elf_phdata) goto out_free_dentry;

解釋器也是一個elf文件,這里讀取解釋器以便于后續操作

6、加載程序段

for(i = 0, elf_ppnt = elf_phdata; i < elf_ex->e_phnum; i++, elf_ppnt++) { int elf_prot, elf_flags; unsigned long k, vaddr; unsigned long total_size = 0; unsigned long alignment; if (elf_ppnt->p_type != PT_LOAD) continue;

加載所有類型為PT_LOAD的段,當處理第1個PT_LOAD段時,如果文件為dyn類型,還需要對其進行地址隨機化。隨機化時還需要區分解釋器或者其他普通so文件,對于解釋器,為避免程序發生沖突,程序固定從ELF_ET_DYN_BASE開始計算偏移進行加載。

if (!first_pt_load) { elf_flags |= MAP_FIXED;} else if (elf_ex->e_type == ET_EXEC) { elf_flags |= MAP_FIXED_NOREPLACE;} else if (elf_ex->e_type == ET_DYN) { if (interpreter) { load_bias = ELF_ET_DYN_BASE; if (current->flags & PF_RANDOMIZE) load_bias += arch_mmap_rnd(); alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum); if (alignment) load_bias &= ~(alignment - 1); elf_flags |= MAP_FIXED_NOREPLACE; } else load_bias = 0; load_bias = ELF_PAGESTART(load_bias - vaddr); total_size = total_mapping_size(elf_phdata, elf_ex->e_phnum); if (!total_size) { retval = -EINVAL; goto out_free_dentry; }}

一切就緒后,通過elf_map函數建立用戶空間虛擬地址空間與目標映像文件中段的映射

error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags, total_size);7、裝載程序入口地址

if (interpreter) { elf_entry = load_elf_interp(interp_elf_ex, interpreter, load_bias, interp_elf_phdata, &arch_state); if (!IS_ERR_VALUE(elf_entry)) { /* * load_elf_interp() returns relocation * adjustment */ interp_load_addr = elf_entry; elf_entry += interp_elf_ex->e_entry; } if (BAD_ADDR(elf_entry)) { retval = IS_ERR_VALUE(elf_entry) ? (int)elf_entry : -EINVAL; goto out_free_dentry; } reloc_func_desc = interp_load_addr; allow_write_access(interpreter); fput(interpreter); kfree(interp_elf_ex); kfree(interp_elf_phdata); } else { elf_entry = e_entry; if (BAD_ADDR(elf_entry)) { retval = -EINVAL; goto out_free_dentry; } }

對于需要解釋器的程序,需要先通過load_elf_interp函數裝入解釋器的映像,并將程序入口點設置為解釋器的入口地址,對于不需要解釋器的文件,直接讀取elf_header中的入口點虛擬地址即可。

8、添加參數和環境變量等配置信息

retval = create_elf_tables(bprm, elf_ex, interp_load_addr, e_entry, phdr_addr);if (retval < 0) goto out; mm = current->mm;mm->end_code = end_code;mm->start_code = start_code;mm->start_data = start_data;

本文作者:jixiaokui,轉載請注明來自

標簽:

返回頂部
高清视频在线观看免费播放器-伊人日本-色九月综合-18禁止看的免费污网站-免费观看性行为视频的网站-天天碰天天操-久久精品国产欧美日韩99热-中文字幕在线视频不卡-国产偷人妻精品一区二区在线-国内精品久-伊人影院在线看-密臀av一区-久久综合五月丁香久久激情-福利一区福利二区-gg国产精品国内免费观看-国产精品 高清 尿 小便 嘘嘘
  • <cite id="ecweg"><pre id="ecweg"></pre></cite>
    <rt id="ecweg"><acronym id="ecweg"></acronym></rt>
  • <rt id="ecweg"></rt>
    国产中文字幕乱人伦在线观看| 国产情侣av自拍| 可以在线看黄的网站| 精品一区二区成人免费视频| 成人污网站在线观看| 波多野结衣之无限发射| 久草资源站在线观看| 人人干人人干人人| 中文字幕黄色大片| 欧美乱大交xxxxx潮喷l头像| 日本xxxxxxx免费视频| 99久久99精品| 波多野结衣之无限发射| 亚洲色图 在线视频| 永久免费看av| www.涩涩涩| 欧美a级免费视频| 天天操天天爽天天射| 中文字幕乱码免费| 黄色影院一级片| 日韩av加勒比| 日韩中文字幕二区| 天堂av在线中文| 女人另类性混交zo| 欧美黄网在线观看| 激情文学亚洲色图| 日韩少妇内射免费播放18禁裸乳| 久久黄色片网站| 欧美污视频网站| 黄黄视频在线观看| 中文字幕在线导航| 日韩精品―中文字幕| 天天操夜夜操很很操| 成人一区二区三| 日韩视频在线视频| 小说区视频区图片区| 男女视频网站在线观看| 肉色超薄丝袜脚交| www.涩涩涩| 人妻少妇被粗大爽9797pw| 日韩精品久久一区二区| www亚洲国产| 中文字幕第17页| 欧美性猛交久久久乱大交小说| 成人在线观看你懂的| 99er在线视频| 公共露出暴露狂另类av| 欧美性猛交xxxx乱大交91| 午夜dv内射一区二区| aa在线免费观看| 久久综合色视频| 精品无码一区二区三区在线| 日本免费成人网| 久久视频免费在线| 亚洲中文字幕无码一区二区三区| 女人高潮一级片| 免费在线观看污污视频| 国产卡一卡二在线| 成人在线观看毛片| www.亚洲成人网| 欧美黑人经典片免费观看| 人妻夜夜添夜夜无码av| 青青草国产精品视频| 大陆极品少妇内射aaaaa| 成人免费观看视频在线观看| 成 年 人 黄 色 大 片大 全| 国产青青在线视频| 日韩精品一区二区三区不卡 | 麻豆一区二区三区视频| 日韩一级理论片| 亚洲五月激情网| 日本一级黄视频| 91精品91久久久中77777老牛| 黄色动漫网站入口| 亚洲36d大奶网| 911av视频| 欧美图片激情小说| 欧美aⅴ在线观看| www.夜夜爽| 一本二本三本亚洲码 | 一本岛在线视频| 中文字幕精品一区二区三区在线| 国产盗摄视频在线观看| a级免费在线观看| www.欧美日本| av噜噜在线观看| 人体内射精一区二区三区| 欧美 日韩精品| 国产又粗又硬又长| 女人天堂av手机在线| 欧美日韩精品区别| 久久久久久久久久网| 久热在线视频观看| 精品这里只有精品| 在线免费看v片| 久久久久久久午夜| aaaaaaaa毛片| 成人在线免费播放视频| 国产91porn| a在线观看免费视频| 国产二区视频在线| 五月天婷婷在线观看视频| 成人午夜视频在线观看免费| 欧美日韩理论片| 99视频精品免费| 成人黄色av片| 蜜臀av性久久久久蜜臀av| www.色就是色| 少妇无码av无码专区在线观看| 日本黄色a视频| 一区二区成人网| 黄色av网址在线播放| 日本丰满大乳奶| 亚洲一区二区三区四区精品| wwwxxx黄色片| www.99热这里只有精品| www.亚洲成人网| 国产又大又长又粗又黄| 国产美女18xxxx免费视频| 超碰影院在线观看| 国产综合中文字幕| 成人免费观看在线| 男同互操gay射视频在线看| 在线观看国产一级片| 99视频在线视频| 91香蕉视频导航| 欧美日韩怡红院| youjizzxxxx18| 亚洲精品视频导航| 午夜两性免费视频| 亚洲一二三区av| 在线看的黄色网址| 九九热99视频| 天堂av手机在线| 日本77777| 中文字幕av久久| 国产大尺度在线观看| 少妇熟女一区二区| 91嫩草国产丨精品入口麻豆| 真人做人试看60分钟免费| 男人日女人的bb| 国产免费黄色小视频| 男女午夜激情视频| 999在线免费视频| chinese少妇国语对白| 天天插天天操天天射| 日韩成人精品视频在线观看| 午夜啪啪免费视频| 精品人妻大屁股白浆无码| 欧美,日韩,国产在线| 成人午夜激情av| 777一区二区| 久久久99精品视频| a√天堂在线观看| 狠狠热免费视频| 99热一区二区三区| 日韩在线观看a| 国内自拍视频一区| 中文字幕55页| 精品少妇人妻av免费久久洗澡| www.色就是色| www.国产二区| 久久综合久久色| 青娱乐国产精品视频| 国产婷婷一区二区三区| 九九热精品在线播放| 久久这里只有精品18| 欧美一级特黄a| 美女黄色免费看| 欧美精品久久久久久久久25p| 国产一二三四区在线观看| 美女av免费在线观看| 日日干日日操日日射| 自拍日韩亚洲一区在线| 手机av在线免费| 男人靠女人免费视频网站| 国产九九在线观看| 性欧美大战久久久久久久| 日韩va在线观看| 日韩a在线播放| 日韩精品综合在线| 天天色天天干天天色| 国产视频一区二区三区在线播放| 国产成人生活片| 第一区免费在线观看| 青青在线视频免费| 欧美成人高潮一二区在线看| www.久久com| 亚洲xxx在线观看| 青青在线免费观看视频| 精品久久一二三| 人妻激情另类乱人伦人妻 | 国产精品久久久久9999爆乳| 狠狠躁狠狠躁视频专区| 夫妻免费无码v看片| 日本男女交配视频| 亚洲视频在线不卡| 久久精品视频在线观看免费| 日本成人在线免费视频| 欧美在线观看成人|