使用linux宏access_ok()有什么意义? [英] What is the point of using the linux macro access_ok()

查看:943
本文介绍了使用linux宏access_ok()有什么意义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在做一些研究,对此宏有些困惑.希望有人能给我一些指导.我有一些ioctl代码(我已经继承了,没有写过),并且在进入从用户空间复制数据之前先检查access_ok()是否是它要做的第一件事:

I've been doing some research and I'm a little confused about this macro. Hopefully someone can give me some guidance. I have some ioctl code (which I've inherited, not written) and the first thing it does if check if access_ok() before moving on to copying data over from user space:

#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返回的描述:

So the code works just fine, but I'm not sure it's needed. The first question comes from this description of access_ok's return:

  • 如果该区域可能是可访问的,则该函数返回非零值(尽管访问可能仍会导致-EFAULT).此函数只是检查该地址是否可能在用户空间中,而不是在内核中.

因此,这意味着它实际上什么也没做,然后确保要检查的指针已在用户空间中可能初始化了?既然我们知道除了用户空间调用我们就无法进入此函数,并且除非我们为该设备打开有效的文件描述符就不会发生,这真的需要吗?只是确保我们没有得到NULL指针,真的更安全吗?

So this means that it really does nothing more then make sure the pointer we're checking against is probably initialized in user space? Since we know that we couldn't come into this function other than a user space call, and it couldn't happen unless we opened a valid file descriptor to this device, is this really needed? Is it really any safer then just making sure we didn't get a NULL pointer?

第二个问题来自此描述:

Second question comes from this description:

  • 可以将type参数指定为VERIFY_READ或VERIFY_WRITE. VERIFY_WRITE符号还标识存储区域是否可读和可写.

这是否意味着我的代码中的第一笔检查是多余的?如果我们要检查可写区域,那么我们可以免费阅读吗?

Does this mean the first check in my code is redundant? If we're going to check for a writable area we get readable as a freebie?

我使用的是x86体系结构,因此access_ok()和__range_no_ok()的定义来自/usr/src/linux-3.1.10-1.16/arch/x86/include/asm/uaccess.h中的定义:

I'm using a x86 architecture so the definations of access_ok() and __range_no_ok() are those from /usr/src/linux-3.1.10-1.16/arch/x86/include/asm/uaccess.h as follows:

#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;                               \
})

推荐答案

如果__lddk_copy_from_user()简单地调用copy_from_user(),则access_ok()检查是多余的,因为copy_from_user()自行执行这些检查.

If __lddk_copy_from_user() simply calls copy_from_user(), then the access_ok() checks are redundant, because copy_from_user() performs these checks itself.

access_ok()检查确保用户空间应用程序不要求内核读取或写入内核地址(它们是完整性/安全性检查).仅仅因为用户空间提供了一个指针并不意味着它绝对是用户空间指针-在许多情况下,内核指针"只是意味着它指向虚拟地址空间的特定区域内.

The access_ok() checks ensure that the userspace application isn't asking the kernel to read from or write to kernel addresses (they're an integrity/security check). Just because a pointer was supplied by userspace doesn't mean that it's definitely a userspace pointer - in many cases "kernel pointer" simply means that it's pointing within a particular region of the virtual address space.

另外,用VERIFY_WRITE调用access_ok()意味着VERIFY_READ,因此,如果您选中前者,则也不需要检查后者.

Additionally, calling access_ok() with VERIFY_WRITE implies VERIFY_READ, so if you check the former you do not need to also check the latter.


此提交在2019年access_ok()不再具有type参数,因此VERIFY_WRITEVERIFY_READ的关系不大.


As of this commit in 2019, access_ok() no long has the type argument, so the VERIFY_WRITE versus VERIFY_READ point is moot.

这篇关于使用linux宏access_ok()有什么意义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆