系统调用跳转表 sys_call_table[] 一个函数指针数组
所有表中不支持的系统调用号,全部指向sys_ni_call()(仅返回出错代码-ENOSYS)
宏调用GET_CURRENT(%ebx)使%ebx指向当前进程的task_struct,然后检查%eax中的系统调用号是否超出范围。
task_struct结构中有字段flags,其中有一标志位PT_TRACESYS,一个进程可通过系统调用ptrace()将一个子进程的该标志位设置为1,从而跟中该子进程的系统调用(系统命令strace即如此)。
------------------------
系统调用返回时,会检查返回值(%eax),若处于-1~-4095之间,则表示出错,转向__syscall_error()(libc.a)
在__syscall_error()中
1. %eax 取负值 ---> 堆栈
2. __errno_location() 全局errono地址 ---> %eax
3. 堆栈 : 出错代码 ---> %ecx
---> 全局errono
4. -1 改写 ---> %eax
-----------------------------------------------------------
以sethostname调用做例子
asmlinkage long sys_sethostname(char* name, int len)
{
...
/*
sethostname是特权用户才可进行的操作,所以一开始就做权限检查
capable(CAP_SYS_ADMIN)检查当前进程是否有CAP_SYS_ADMIN的授权
*/
if( !capable(CAP_SYS_ADMIN) )
return -EPERM;
//检查字符串长度
if( len < 0 || len > __NEW_UTS_LEN )
return -EINVAL;
//sethostname要操作的是临界区,这里在操作前,必须加信号量,防止race condition出现
down_write(&uts_sem);
...
up_write(&uts_sem);
/*
在以上的临界区操作中,使用了宏调用copy_from_user(to,from,n):
copy_from_user(system_utsname.nodename, name, len)
*/
阅读(820) | 评论(0) | 转发(0) |