copy_{from/to}_user的实现
内核空间无法访问用户态地址。但是内核代码段中。include/asm-generic/uaccess.h#L7978 #ifndef __copy_from_user
79 static inline __must_check long __copy_from_user(void *to,
80 const void __user * from, unsigned long n)
81 {
82 if (__builtin_constant_p(n)) {
83 switch(n) {
84 case 1:
85 *(u8 *)to = *(u8 __force *)from;
86 return 0;
87 case 2:
88 *(u16 *)to = *(u16 __force *)from;
89 return 0;
90 case 4:
91 *(u32 *)to = *(u32 __force *)from;
92 return 0;
93 #ifdef CONFIG_64BIT
94 case 8:
95 *(u64 *)to = *(u64 __force *)from;
96 return 0;
97 #endif
98 default:
99 break;
100 }
101 }
102
103 memcpy(to, (const void __force *)from, n);
104 return 0;
105 }
106 #endif
除了权限检查之外就是直接拷贝,网上看到了一些关于exception的说法,但是还是不能系统的理解。
朋友,我建议你把这个问题好好再表述一遍。 内核空间无法访问用户态地址。
内核代码可以访问用户空间。
具体哪些空间可以访问,需要看MMU配置。 这一段是generic的实现,在具体的架构上应该不是这份代码。 如果user传来的from是恶意地址,比如NULL,那么在内核执行generic版本的__copy_from_user就会产生crash(严格的说是保护错误/异常)。
所以真正的copy_from_user会把函数的调用位置记在一个表里(exception表),
等到非法访问产生异常的时候,在异常处理函数里检查错误的指令是否在exception表里,
如果是,修改表示eip到fixcode;
异常处理返回后,fixcode得到执行,返回错误-EFAULT给调用者。
具体参见ULK3的第10章,最后一部分。
页:
[1]