Q:一直知道内核和用户态的数据交互前都需要 校验地址的合法性,一般都用copy_from/to_user完成数据拷贝,那么为什么要这样呢??
A:看了一些blog以及Stack Overflow 主要说的是安全性:
One, the kernel is capable of writing to any memory. User process‘s can‘t. copy_to_user needs to check dst to ensure it is accessible and writable by the current process.
Two, depending on the architecture, you can‘t simply copy data from kernel to user-space. You might need to do some special setup first, invalidate certain caches, or use special operations.
而内核可以访问任意内存。copy_to_user需要 通过当前进程来 检查目标的可写权限 (而用户 进程无法检查内核空间目标地址的 写权限 )
同时:检查指针所指的内存是否有效
设想一下:我们在写file_opeteration的write函数时:write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)/read(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
1、buf地址不合法
2、buf地址合法,内核还没有给它映射物理地址
3、如果buf是个一个内核地址, read的时候不就是内核到内核的拷贝么??
所以为了解决上述问题就有了copy_xx_user-----------
- 地址检查,不合法返回
- copy_xx_user 使用精心布置的访存汇编实现,并指这个汇编指令所在的地址全部登记起来(称为extable表)。出现2时------>会发生缺页异常,进入内核do_page_fault流程;然后检查出错的PC地址是不是早已在extable登记好的,如果是,同表示该缺页异常是copy_from_user/copy_to_user函数产生的。最后才检查该地址是否为该进程的合法地址,如果是则分配物理页并处理,否则就是非法地址,把进程给杀死(发送sigsegv信号)
1、为什么会产生page fault?
2、发生缺页的上下文是否可以位于内核态
有可能在内核态,但这种情况下,发生缺页的地址只能位于用户态地址空间,而且也只能为exceptions table中预先定义好的异常,如果exceptions table中没有预先定义的处理,或者缺页的地址位于内核态地址空间,则表示错误,进入oops流程。通常属于异常,会导致oops。、、-----copy_xx_user干的就是这事
/*
* If we‘re in an interrupt, have no user context or are running
* in an atomic region then we must not take the fault:
*/
if (unlikely(in_atomic() || !mm)) {mm 为空表示内核线程
bad_area_nosemaphore(regs, error_code, address);
return;
}
3、发生缺页的地址是否可以位于内核态地址空间----
有可能,发生缺页的内核态地址仅可能位于vmalloc区;在使用Vmalloc分配物理内存时,确实进行了映射,创建了页表项。
但是,其修改的仅为内核的主内核页表,并没有更新相关进程的页表;进程访问时,相关进程的页表中并没有Vmalloc分配内存相应的页表项,所以会触发page fault
都知道的copy_from_user
原文:https://www.cnblogs.com/codestack/p/13019491.html