您现在的位置是:Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款 > 

02 ss訂閱鏈接轉換買粉絲(如何進入大數據領域,學習路線是什么?)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款2024-05-31 03:32:53【】1人已围观

简介YSENTER調用方式的glibc2.3.3為例,分析一下系統調用的具體實現。內核在啟動時做的準備前面說到的這段入口代碼,根據調用方式分為兩個文件,支持sysenter指令的代碼包含在文件arch/i

YSENTER 調用方式的 glibc2.3.3 為例,分析一下系統調用的具體實現。

內核在啟動時做的準備

前面說到的這段入口代碼,根據調用方式分為兩個文件,支持 sysenter 指令的代碼包含在文件 arch/i386/kernel/vsyscall-sysenter.S 中,支持int中斷的代碼包含在arch/i386/kernel/vsyscall-int80.S中,入口名都是 __kernel_vsyscall,這兩個文件編譯出的二進制代碼由arch/i386/kernel/vsyscall.S所包含,并導出起始地址和結束地址。

2.6 內核在啟動的時候,調用了新增的函數sysenter_setup(參見arch/i386/kernel/sysenter.c),在這個函數中,內核將虛擬內存空間的頂端一個固定地址頁面(從0xffffe000開始到0xffffeffff的4k大小)映射到一個空閑的物理內存頁面。然后通過之前執行CPUID的指令得到的數據,檢測CPU是否支持sysenter/sysexit指令。如果CPU不支持,那么將采用INT調用方式的入口代碼拷貝到這個頁面中,然后返回。相反,如果CPU支持SYSETER/SYSEXIT指令,則將采用SYSENTER調用方式的入口代碼拷貝到這個頁面中。使用宏 on_each_cpu在每個CPU上執行enable_sep_cpu這個函數。

在enable_sep_cpu函數中,內核將當前CPU的TSS結構中的ss1設置為當前內核使用的代碼段,esp1設置為該TSS結構中保留的一個256字節大小的堆棧。在X86中,TSS結構中ss1和esp1本來是用于保存Ring 1進程的堆棧段和堆棧指針的。由于內核在啟動時,并不能預知調用sysenter指令進入Ring 0后esp的確切值,而應用程序又無權調用wrmsr指令動態設置,所以此時就借用esp1指向一個固定的緩沖區來填充這個MSR寄存器,由于Ring 1根本沒被啟用,所以并不會對系統造成任何影響。在下面的文章中會介紹進入Ring 0之后,內核如何修復ESP來指向正確的Ring 0堆棧。關于TSS結構更細節的應用可參考代碼include/asm-i386/processor.h)。

然后,內核通過wrmsr(msr,val1,val2)宏調用wrmsr指令對當前CPU設置MSR寄存器,可以看出調用宏的第三個參數即edx都被設置為0。其中SYSENTER_CS_MSR的值被設置為當前內核用的所在代碼段;SYSENTER_ESP_MSR被設置為esp1,即指向當前CPU的 TSS結構中的堆棧;SYSENTER_EIP_MSR則被設置為內核中處理sysenter指令的接口函數sysenter_entry(參見 arch/i386/kernel/entry.S)。這樣,sysenter指令的準備工作就完成了。

通過內核在啟動時進行這樣的設置,在每個進程的進程空間中,都能訪問到內核所映射的這個代碼頁面,當然這個頁面對于應用程序來說是只讀的。我們通過新版的ldd工具查看任意一個可執行程序,可以看到下面的結果:

[root@test]# file dynamic

dynamic: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),

for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped

[root@test]# ldd dynamic

linux-gate.so.1 => (0xffffe000)

libc.so.6 => /lib/tls/libc.so.6 (0x4002c000)

/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

這個所謂的"linux-gate.so.1"的內容就是內核映射的代碼,系統中其實并不存在這樣一個鏈接庫文件,它的名字是由ldd自己起的,而在老版本的ldd中,雖然能夠檢測到這段代碼,但是由于沒有命名而且在系統中找不到對應鏈接庫文件,所以會有一些顯示上的問題。有關這個問題的背景,可以參考下面這個買粉絲: 買粉絲://sources.redhat.買粉絲/ml/libc-alpha/2003-09/msg00263.買粉絲。

由用戶態經庫函數進入內核態

為了配合內核使用新的系統調用方式,glibc中要做一定的修改。新的glibc-2.3.2(及其以后版本中)中已經包含了這個改動,在glibc源代碼的sysdeps/unix/sysv/linux/i386/sysdep.h文件中,處理系統調用的宏INTERNAL_SYSCALL在不同的編譯選項下有不同的結果。在打開支持sysenter/sysexit指令的選項I386_USE_SYSENTER下,系統調用會有兩種方式,在靜態鏈接(編譯時加上-static選項)情況下,采用"call *_dl_sysinfo"指令;在動態鏈接情況下,采用"call *%gs:0x10"指令。這兩種情況由glibc庫采用哪種方法鏈接,實際上最終都相當于調用某個固定地址的代碼。下面我們通過一個小小的程序,配合 gdb來驗證。

首先是一個靜態編譯的程序,代碼很簡單:

main()

{

getuid();

}

將代碼加上static選項用gcc靜態編譯,然后用gdb裝載并反編譯main函數。

[root@test opt]# gcc test.c -o ./static -static

[root@test opt]# gdb ./static

(gdb) disassemble main

0x08048204 <main+0>: push %ebp

0x08048205 <main+1>: mov %esp,%ebp

0x08048207 <main+3>: sub $0x8,%esp

0x0804820a <main+6>: and $0xfffffff0,%esp

0x0804820d <main+9>: mov $0x0,%eax

0x08048212 <main+14>: sub %eax,%esp

0x08048214 <main+16>: call 0x804cb20 <__getuid>

0x08048219 <main+21>: leave

0x0804821a <main+22>: ret

可以看出,main函數中調用了__getuid函數,接著反編譯__getuid函數。

(gdb) disassemble 0x804cb20

0x0804cb20 <__getuid+0>: push %ebp

0x0804cb21 <__getuid+1>: mov 0x80aa028,%eax

0x0804cb26 <__getuid+6>: mov %esp,%ebp

0x0804cb28 <__getuid+8>: test %eax,%eax

0x0804cb2a <__getuid+10>: jle 0x804cb40 <__getuid+32>

0x0804cb2c <__getuid+12>: mov $0x18,%eax

0x0804cb31 <__getuid+17>: call *0x80aa054

0x0804cb37 <__getuid+23>: pop %ebp

0x0804cb38 <__getuid+24>: ret

上面只是__getuid函數的一部分。可以看到__getuid將eax寄存器賦值為getuid系統調用的功能號0x18然后調用了另一個函數,這個函數的入口在哪里呢?接著查看位于地址0x80aa054的值。

(gdb) X 0x80aa054

0x80aa054 <_dl_sysinfo>: 0x0804d7f6

看起來不像是指向內核映射頁面內的代碼,但是,可以確認,__dl_sysinfo指針的指向的地址就是0x80aa054。下面,我們試著啟動這個程序,然后停在程序第一條語句,再查看這個地方的值。

(gdb) b main

Breakpoint 1 at 0x804820a

(gdb) r

Starting program: /opt/static

Breakpoint 1, 0x0804820a in main ()

(gdb) X 0x80aa054

0x80aa054 <_dl_sysinfo>: 0xffffe400

可以看到,_dl_sysinfo指針指向的數值已經發生了變化,指向了0xffffe400,如果我們繼續運行程序,__getuid函數將會調用地址0xffffe400處的代碼。

接下來,我們將上面的代碼編譯成動態鏈接的方式,即默認方式,用gdb裝載并反編譯main函數

[root@test opt]# gcc test.c -o ./dynamic

[root@test opt]# gdb ./dynamic

(gdb) disassemble main

0x08048204 <main+0>: push %ebp

0x08048205 <main+1>: mov %esp,%ebp

0x08048207 <main+3>: sub $0x8,%esp

0x0804820a <main+6>: and $0xfffffff0,%esp

0x0804820d <main+9>: mov $0x0,%eax

0x08048212 <main+14>: sub %eax,%esp

0x08048214 <main+16>: call 0x8048288

0x08048219 &l

很赞哦!(26)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款的名片

职业:程序员,设计师

现居:安徽亳州蒙城县

工作室:小组

Email:[email protected]