Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux kernel 传递给put_user()的指针类型是否重要?_Linux Kernel_Linux Device Driver - Fatal编程技术网

Linux kernel 传递给put_user()的指针类型是否重要?

Linux kernel 传递给put_user()的指针类型是否重要?,linux-kernel,linux-device-driver,Linux Kernel,Linux Device Driver,我在为连接到旧PowerPC的自定义硬件的字符设备驱动程序编写IOCTL时发现了一个奇怪的问题。以下是我的代码的抽象: u32 mydev_data; ... static long mydev_ioctl(struct file * file, unsigned int cmd, unsigned long arg) { void __user *user_arg = (void __user *)arg; long result; switch(cmd) {

我在为连接到旧PowerPC的自定义硬件的字符设备驱动程序编写IOCTL时发现了一个奇怪的问题。以下是我的代码的抽象:

u32 mydev_data;

...

static long mydev_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
{
    void __user *user_arg = (void __user *)arg;
    long result;

    switch(cmd) {

    case MYDEV_GETDATA:
        result = put_user(mydev_data, user_arg);
        break;

    ...
    }

    return result;
}
现在,它返回垃圾。但是,当我更换线路时

result = put_user(mydev_data, user_arg);

问题消失了


这是怎么回事?由于user_arg被标记为u user*,唯一的区别是void与unsigned long。但我认为指针类型在这里并不重要。显然我错了,但有人能解释一下原因吗?

如果你看一下
put\u user
宏的定义,你会发现它根据大小复制数据,执行
sizeof(*ptr)
来确定要复制多少字节
sizeof(void)==1
,但
sizeof(unsigned long)
更大

#define __put_user_check(x, ptr, size)                                  \
({                                                                      \
        long __pu_err = -EFAULT;                                        \
        __typeof__(*(ptr)) __user *__pu_addr = (ptr);                   \
        might_sleep();                                                  \
        if (access_ok(VERIFY_WRITE, __pu_addr, size))                   \
                __put_user_size((x), __pu_addr, (size), __pu_err);      \
        __pu_err;                                                       \
})

#define put_user(x, ptr) \
  __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
#define __put_user_check(x, ptr, size)                                  \
({                                                                      \
        long __pu_err = -EFAULT;                                        \
        __typeof__(*(ptr)) __user *__pu_addr = (ptr);                   \
        might_sleep();                                                  \
        if (access_ok(VERIFY_WRITE, __pu_addr, size))                   \
                __put_user_size((x), __pu_addr, (size), __pu_err);      \
        __pu_err;                                                       \
})

#define put_user(x, ptr) \
  __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))