分享
 
 
 

FreeBSD 5内核源代码分析之copyin()实现原理

王朝system·作者佚名  2006-11-23
窄屏简体版  字體: |||超大  

在内核中,用户态和内核态之间的数据拷贝主要通过copyin()和copyout()

两个函数完成。与普通的数据拷贝不同,用户态和内核态之间的数据拷贝必须

考虑到用户给出的地址是否有效,即该地址是否有真正的地址映射。同时又要

考虑到效率。因此也不可能对用户给出地址的每个字节检查一遍。

FreeBSD和linux一样(linux中是copy_from_user()和copy_to_user()),

都是先拷贝,出错以后再进行错误处理,有着异曲同工之妙。

本文所有代码,如未注明,均来自sys/i386/i386/support.s

copyin()由汇编语言写成,我们逐句来看。

代码:

/*

* copyin(from_user, to_kernel, len) - MP SAFE

*/

ENTRY(copyin)

MEXITCOUNT

jmp *copyin_vector

copyin()有三个参数,from_user为用户态数据地址,to_kernel为内核缓冲区地址,

len为数据长度。它们分别位于堆栈的位置是:

代码:

from_user: 12(%esp)

to_kernel: 16(%esp)

len: 20(%esp)

这里copyin_vector定义为

代码:

.globl copyin_vector

copyin_vector:

.long generic_copyin

定义一个数据copyin_vector,其值是generic_copyin

这里*copyin_vector的值就是generic_copyin,因此将跳转到generic_copyin。

代码:

ENTRY(generic_copyin)

movl PCPU(CURPCB),%eax

movl $copyin_fault,PCB_ONFAULT(%eax)

先将curpcb地址存入%eax,然后将curpcb->pcb_onfault置为copyin_fault,

这里copyin_fault也是一个程序标号,拷贝出错时将跳转到这里。下面我们将看到。

代码:

pushl %esi

pushl %edi

movl 12(%esp),%esi /* caddr_t from */

movl 16(%esp),%edi /* caddr_t to */

movl 20(%esp),%ecx /* size_t len */

分别将from_user, to_kernel, len存入寄存器%esi, %edi, %ecx

代码:

/*

* make sure address is valid

*/

movl %esi,%edx

addl %ecx,%edx

jc copyin_fault

这几句看from_user+len是否有整数溢出。

代码:

cmpl $VM_MAXUSER_ADDRESS,%edx

ja copyin_fault

相加之和是否在用户有效地址空间内。

代码:

#if defined(I586_CPU) && defined(DEV_NPX)

ALIGN_TEXT

slow_copyin:

#endif

movb %cl,%al

shrl $2,%ecx /* copy longword-wise */

cld

rep

movsl

先以4字节为单位拷贝。

代码:

movb %al,%cl

andb $3,%cl /* copy remaining bytes */

rep

movsb

再拷贝剩余的字节(最多3字节),如果有的话。

代码:

#if defined(I586_CPU) && defined(DEV_NPX)

ALIGN_TEXT

done_copyin:

#endif

popl %edi

popl %esi

xorl %eax,%eax

movl PCPU(CURPCB),%edx

movl %eax,PCB_ONFAULT(%edx)

ret

拷贝完成,恢复寄存器,并清除curpcb->pcb_onfault,返回。

由于%eax用做函数返回值,这就是说,如果成功拷贝就返回0

事情总是有意外发生,如果用户给出的地址段

[from_user, from_user+len]

有问题的话,copyin()将发生异常,进入异常处理函数,

代码:

(sys/i386/i386/trap.c)

---------------------------

/*

* Exception, fault, and trap interface to the FreeBSD kernel.

* This common code is called from assembly language IDT gate entry

* routines that prepare a suitable stack frame, and restore this

* frame after the exception has been processed.

*/

void

trap(frame)

struct trapframe frame;

{

struct thread *td = curthread;

struct proc *p = td->td_proc;

......

type = frame.tf_trapno;

......

if(it is user trap){

......

}else{ /* kernel trap */

......

switch (type) {

......

case T_PROTFLT: /* general protection fault */

case T_STKFLT: /* stack fault */

......

/* FALL THROUGH */

case T_SEGNPFLT: /* segment not present fault */

......

if (PCPU_GET(curpcb) != NULL &&

PCPU_GET(curpcb)->pcb_onfault != NULL) {

frame.tf_eip =

(int)PCPU_GET(curpcb)->pcb_onfault;

goto out;

}

break;

......

} /* end switch */

......

} /* end else */

......

out:

return;

}

对于copyin()产生的错误,"general protection fault"或"stack fault"

或"segment not present fault",都由这段代码处理。

由于在进入copyin()时设置了curpcb->pcb_onfault,这里将异常处理程序退出时

继续运行的eip指针设置为copyin_fault,于是,当异常返回后,程序控制将到达

copyin_fault。

代码:

ALIGN_TEXT

copyin_fault:

popl %edi

popl %esi

movl PCPU(CURPCB),%edx

movl $0,PCB_ONFAULT(%edx)

movl $EFAULT,%eax

ret

在这里,恢复寄存器,清除curpcb->pcb_onfault,返回EFAULT.

注意,此时的核心栈与拷贝成功时的核心栈是相同的,这是因为前述trap()函数

修改%eip后,程序只是将本来应该继续执行拷贝错误语句改为执行copyin_fault,

异常处理程序返回后的核心栈并没有变化。因此,内核将顺着copyin()后的代码执行,

就好象根本没有发生过异常一样。

参考文献:

[1] Sinan "noir" Eren, "Smashing The Kernel Stack For Fun And Profit", phrack60-06

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有