设当前进程代码段的特权级即 16 位段寄存器
cs
最低两位为
C
P
L
CPL
CPL,目标段的段选择子即 16 位段寄存器的最低两位为
R
P
L
RPL
RPL,目标段的段描述符中的特权级位为
D
P
L
DPL
DPL。
一、访问数据段
若 m a x { C P L , R P L } ≤ D P L max\{CPL, RPL\} \leq DPL max{CPL,RPL}≤DPL,则允许访问目标数据段。
二、访问堆栈段
若 C P L = = R P L = = D P L CPL == RPL == DPL CPL==RPL==DPL,则允许访问目标堆栈段。
三、通过普通跳转访问代码段
普通跳转是指,jmp
或 call
后跟着 48 位全指针(16 位代码段段寄存器的值加 32 位偏移地址),16 位代码段段寄存器的值中包含着代码段描述符在全局描述符表中的下标即该段寄存器本身的特权级
R
P
L
RPL
RPL,代码段描述符中含有代码段的段基址,将段基址和 32 位偏移地址加起来可得本次跳转的目标物理地址。
设 C 为目标段段描述符的一致位 C。若 C = = 0 C==0 C==0,则目标段为非一致性代码段,若 C = = 1 C==1 C==1,则目标段为一致性代码段。
若 ( C = = 0 ⋀ C P L = = D P L ⋀ R P L ≤ C P L ) ⋁ ( C = = 1 ⋀ C P L ≥ D P L ) (C == 0 \bigwedge CPL==DPL \bigwedge RPL\leq CPL) \ \bigvee \ (C == 1 \bigwedge CPL \geq DPL) (C==0⋀CPL==DPL⋀RPL≤CPL) ⋁ (C==1⋀CPL≥DPL),则允许访问目标代码段。
四、通过调用门跳转访问代码段
调用门跳转是指,jmp
或 call
后跟着 48 位全指针(16 位调用门选择子加 32 位偏移地址),且 16 位调用门选择子中包含着调用门描述符的索引和该选择子的特权级
R
P
L
g
a
t
e
RPL_{gate}
RPLgate,此时 32 位偏移地址舍弃不用,且目标代码段的特权级即上文提及的
R
P
L
RPL
RPL 舍弃不用。
设调用门选择子的特权级为 R P L g a t e RPL_{gate} RPLgate,调用门描述符中的特权级为 D P L g a t e DPL_{gate} DPLgate。
call
指令:若
C
P
L
≤
D
P
L
g
a
t
e
⋀
R
P
L
g
a
t
e
≤
D
P
L
g
a
t
e
⋀
D
P
L
≤
C
P
L
CPL \leq DPL_{gate} \bigwedge RPL_{gate} \leq DPL_{gate} \bigwedge DPL \leq CPL
CPL≤DPLgate⋀RPLgate≤DPLgate⋀DPL≤CPL,不管目标段是否为一致性代码段,都允许访问。
jump
指令:若
C
P
L
≤
D
P
L
g
a
t
e
⋀
R
P
L
g
a
t
e
≤
D
P
L
g
a
t
e
⋀
(
(
C
=
=
0
⋀
D
P
L
≤
C
P
L
)
⋁
(
C
=
=
1
⋀
D
P
L
=
=
C
P
L
)
)
CPL \leq DPL_{gate} \bigwedge RPL_{gate} \leq DPL_{gate} \bigwedge \ (\ (C==0 \bigwedge DPL \leq CPL)\ \bigvee \ (C==1 \bigwedge DPL == CPL))
CPL≤DPLgate⋀RPLgate≤DPLgate⋀ ( (C==0⋀DPL≤CPL) ⋁ (C==1⋀DPL==CPL)),则允许访问目标代码段。
五、参考资料链接
《Intel 64 and IA-32 Architectures Software Developer’s Manual》