我一直在做一些研究,我有点困惑这个宏。 希望有人可以给我一些指导。 我有一些IOCTL代码(我继承,不能写),它做的第一件事,如果检查access_ok()
上移动,以从用户空间复制以上数据之前:
#define __lddk_copy_from_user(a,b,c) copy_from_user(a,b,c)
#define __lddk_copy_to_user(a,b,c) copy_to_user(a,b,c)
long can_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch(cmd) {
case COMMAND:
if(! access_ok(VERIFY_READ, (void *)arg, sizeof(Message_par_t)))
return(retval);
if(! access_ok(VERIFY_WRITE, (void *)arg, sizeof(Message_par_t)))
return(retval);
argp = &Command;
__lddk_copy_from_user( (void *) argp,(Command_par_t *) arg, sizeof(Command_par_t));
因此,代码工作得很好,但我不知道它的需要。 第一个问题来自于access_ok的回归这样的描述:
- 该函数返回非零值,如果该地区有可能访问(访问虽然仍可能导致-EFAULT)。 该功能只是简单地检查这个地址很可能在用户空间,而不是内核。
因此,这意味着它确实没有什么更多的则确保我们检查,对在用户空间可能是初始化指针? 因为我们知道,我们不能进入不是用户空间调用其它此功能,除非我们开了一个有效的文件描述符该设备可能不会发生,这是真正需要的? 难道真的更加安全则只是确保我们没有得到一个空指针?
第二个问题来自于这样的描述:
- 类型参数可以被指定为VERIFY_READ或VERIFY_WRITE。 所述VERIFY_WRITE符号还识别所述存储区域是否可读以及可写的。
这是否意味着我的代码中的第一次检查是多余的? 如果我们要检查是否有可写的区域,我们得到可读的赠品?
我使用x86架构所以access_ok()和__range_no_ok()的definations是那些由/usr/src/linux-3.1.10-1.16/arch/x86/include/asm/uaccess.h如下:
#define access_ok(type, addr, size) (likely(__range_not_ok(addr, size) == 0))
#define __range_not_ok(addr, size) \
({ \
unsigned long flag, roksum; \
__chk_user_ptr(addr); \
asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0" \
: "=&r" (flag), "=r" (roksum) \
: "1" (addr), "g" ((long)(size)), \
"rm" (current_thread_info()->addr_limit.seg)); \
flag; \
})