以下討論的內容是以i
平台為基礎的
Linux將
G的地址劃分為用戶空間和內核空間兩部分
在Linux內核的低版本中(
X)
通常
G為用戶空間
G
G為內核空間
這個分界點是可以可以改動的
正是這個分界點的存在
限制了Linux可用的最大內存為
G
而且要通過重編內核
調整這個分界點才能達到
實際上還可以有更好的方法來解決這個問題
由於內核空間與用戶空間互不重合
所以可以用段機制提供的保護功能來保護內核級代碼
以下為
X的部分代碼
/usr/src/linux/arch/i
/kernel/entry
S
A:
quad
xc
c
a
ffff /*
x
kernel
GB code at
xC
*
B:
quad
xc
c
ffff /*
x
kernel
GB data at
xC
*
C:
quad
x
cbfa
ffff /*
x
user
GB code at
x
*
D:
quad
x
cbf
ffff /*
x
b user
GB data at
x
*
A
B為內核代碼段及數據段的描述符
C
D為用戶代碼及數據段的描述符從以上
我們可以清楚的看到A
B的特權級為
而C
D的特權級為
當內核存取用戶空間的內容時
他借助於fs寄存器
同過將FS寄存器的內容置為D來達到訪問用戶空間的目的
X版的 內核對此進行了改動
這樣內核空間擴張到了
G
所以可以直接進行拷貝了
quad
x
cf
a
ffff /*
x
kernel
GB code at
x
*
quad
x
cf
ffff /*
x
kernel
GB data at
x
*
quad
x
cffa
ffff /*
x
user
GB code at
x
*
quad
x
cff
ffff /*
x
b user
GB data at
x
*
從表面上看內核的基地址變為了
但實際上
內核通常仍在虛址
G以上
其中奧妙在與 不同的連接描述文件
X
=
xC
+
x
;
_text =
; /* Text and read
only data */
text : {
*(
text)
*(
fixup)
*(
gnu
warning)
} =
x
text
lock : { *(
text
lock) } /* out
of
line lock text */
rodata : { *(
rodata) }
kstrtab : { *(
kstrtab) }
X
faint
內核被刪除了
(
不管怎莫說
請大家相信我
X的起址為
x
這樣一來
二者就相等了
都是
xC
+
x
用戶空間在
X中從直觀上變為
G
讓人迷惑
其不是可以直接訪問內核了?其實不然
同過使用頁機制提供的保護
阻止了用戶程序訪問內核空間
這樣
存取用戶空間實際上已不需要FS
GS的支持
但在內核中仍保留set_fs(X)等宏上你設的值用來驗證隨後的操作是否合適
是否超過設定的X
此處X不再是一個段描述符
而是一個具體的值
此處就有一個陷阱
如果你將Set_fs的值設置為Kernel_DS
而沒有將其該回去
當用戶通過系統調用將一個Buffer的地址(應該在用戶空間)設置為一個內核空間
而內核在訪問該地址前認為默認當前的閥值仍為User_DS
事情就大大?了
From:http://tw.wingwit.com/Article/program/Oracle/201311/16958.html