#ifdef __CHECKER__
# define __user __attribute__((noderef, address_space(1)))
# define __kernel /* default address space */
#else
# define __user
# define __kernel
#endif

noderef告诉编译器,不应该解除该指针的引用,因为在当前地址空间中它是没有意义的。

这里的CHECKER表示是否使用了Sprase(就是一种静态分析工具,用来分析内核源码中的BUG)。是不是想研究一下了?呵呵。可以参见http://sparse.wiki.kernel.org/index.php/Main_Page

所以对于这种变量,在kernel中使用要用到copy_to_user和copy_from_user。

  • 在Linux中的實例:(net/rds/page.c)
  • int rds_page_copy_user(struct page *page, unsigned long offset,
                   void __user *ptr, unsigned long bytes,
                   int to_user)
    {
        unsigned long ret;
        void *addr;
    
        if (to_user)
            rds_stats_add(s_copy_to_user, bytes);
        else
            rds_stats_add(s_copy_from_user, bytes);
    
        addr = kmap_atomic(page, KM_USER0);
        if (to_user)
            ret = __copy_to_user_inatomic(ptr, addr + offset, bytes);
        else
            ret = __copy_from_user_inatomic(addr + offset, ptr, bytes);
        kunmap_atomic(addr, KM_USER0);
    
        if (ret) {
            addr = kmap(page);
            if (to_user)
                ret = copy_to_user(ptr, addr + offset, bytes);
            else
                ret = copy_from_user(addr + offset, ptr, bytes);
            kunmap(page);
            if (ret)
                return -EFAULT;
        }
    
        return 0;
  • Vulnerability Details

    On Linux, recvmsg() style socket calls are performed using iovec structs, which allow a user to specify a base address and size for a buffer used to receive socket data. Each packet family is responsible for defining functions that copy socket data, which is received by the kernel, back to user space to allow user programs to process and handle received network data.

    When performing this copying of data to user space, the RDS protocol failed to verify that the base address of a user-provided iovec struct pointed to a valid userspace address before using the__copy_to_user_inatomic() function to copy the data. As a result, by providing a kernel address as an iovec base and issuing a recvmsg() style socket call, a local user could write arbitrary data into kernel memory. This can be leveraged to escalate privileges to root.

    Proof-of-Concept Exploit

    VSR has developed a proof-of-concept exploit [4] to both demonstrate the severity of this issue as well as allow users and administrators to verify the existence of the vulnerability. The exploit leverages the ability to write into kernel memory to reset the kernel's security operations structure and gain root privileges. The exploit requires that kernel symbol resolution is available to unprivileged users, via /proc/kallsyms or similar, as is the case on most stock distributions. It has been tested on both 32-bit and 64-bit x86 platforms. While this exploit has been reliable during testing, it is not advised to run kernel exploits on production systems, as there is a risk of causing system instability and crashing the affected machine.