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


(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 韎
popl %esi
movl PCPU(CURPCB),韝
movl $0,PCB_ONFAULT(韝)
movl $EFAULT,陎
ret

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

注意,此时的核心栈与拷贝成功时的核心栈是相同的,这是因为前述trap()函数
修改%eip后,程序只是将本来应该继续执行拷贝错误语句改为执行copyin_fault,
异常处理程序返回后的核心栈并没有变化 。因此,内核将顺着copyin()后的代码执行,
就好象根本没有发生过异常一样 。

参考文献:
[1] Sinan "noir" Eren, "Smashing The Kernel Stack For Fun And Profit", phrack60-06

推荐阅读