I do some research, and I'm a little confused by this macro. Hope someone can give me some advice. I have ioctl code (which I inherited, but did not write), and the first thing it does is to check if access_ok() before proceeding to copy data from user space:
So the code works fine, but I'm not sure if it is needed. The first question comes from this description of return_ok return:
- The function returns a nonzero value if the region is likely to be available (although access can still result in -EFAULT). This function simply checks that the address is likely in user space, and not in the kernel.
So, does this mean that it really does nothing to make sure that the pointer we are checking is possibly initialized in user space? Since we know that we could not enter this function, except for calling the user space, and this could not happen if we did not open the actual file descriptor of this device, is this really necessary? Is this really safer than just making sure we don't get a NULL pointer?
The second question comes from this description:
- A type argument can be specified as VERIFY_READ or VERIFY_WRITE. The VERIFY_WRITE symbol also determines whether a memory area can be read as well as written.
Does this mean that the first check of my code is redundant? If we are going to check the writable area, will we get readability like a freebie?
I am using x86 architecture, so the definitions of access_ok () and __range_no_ok () are the names 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; \ })