宏"access_ok"最近取消的第一个参数如何替换?

How to replace the recently abolished first parameter of macro "access_ok"?

正在尝试将老式驱动程序从内核 2.6 合并到最新的内核 5.8。

并遇到以下错误:

macro "access_ok" passed 3 arguments, but takes just 2

access_ok是在asm/uaccess.h

中定义的宏

这是代码片段:

#include <asm/uaccess.h>

if (_IOC_DIR(cmd) & _IOC_READ)
    err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
    err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
if (err) return -EFAULT;

我做了一些谷歌搜索,但他们都告诉我切换到支持接受 3 个参数的 access_ok 的较低版本内核,显然这没有解决我的问题。

所以我想知道我可以用哪个宏替换 access_ok

根据 Torvalds' replytype 参数已从 access_ok() 函数(或宏)中删除,您唯一需要做的就是将提到的代码片段修改为最新的内核(现在是 5.8),就是简单地删除第一个参数(例如 VERIFY_WRITEVERIFY_READ

这里是修改后的片段

#include <asm/uaccess.h>

if (_IOC_DIR(cmd) & _IOC_READ)
    err = !access_ok((void __user *)arg, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
    err = !access_ok((void __user *)arg, _IOC_SIZE(cmd));
if (err) return -EFAULT;

我包含以下兼容性代码:

#include <linux/version.h>

/* 
 * <linux/uaccess.h> was added in kernel version 2.6.18, and should be
 * included in preference to <asm/uaccess.h>.  In particular, copy_to_user()
 * and copy_from_user() were moved to <linux/uaccess.h> in kernel version
 * 4.12.
 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
#include <linux/uaccess.h>
#else
#include <asm/uaccess.h>
#endif

/*
 * Kernel 5.0 removed VERIFY_READ and VERIFY_WRITE and removed the first
 * parameter of access_ok() which was set to VERIFY_READ or VERIFY_WRITE.
 * That has been redundant since kernel 2.5.70, and even then it was only
 * checked for kernels that support old 386 processors.
 *
 * Get rid of the first parameter and always pass VERIFY_WRITE for kernels
 * prior to 5.0.  This will fail for old 386 processors on pre-2.5.70
 * kernels if the memory region is not in fact writeable.
 */
#ifdef VERIFY_WRITE
/* Pre 5.0 kernel. */
static inline int _kcompat_access_ok(unsigned long addr, size_t size)
{
    /* Always use VERIFY_WRITE.  Most architectures ignore it. */
    return access_ok(VERIFY_WRITE, addr, size);
}
/* Redefine access_ok() to remove first parameter. */
#undef access_ok
#define access_ok(addr, size) _kcompat_access_ok((unsigned long)(addr), (size))
#endif

然后将代码中所有旧的三参数调用更改为 access_ok 以省略第一个参数。

对于仍然需要删除参数的 5.0 之前的内核,此兼容性代码始终将其设置为 VERIFY_WRITE。这并不重要,因为参数值自内核版本 2.5.70 以来一直是多余的,即便如此,它也只检查支持旧 386 处理器的内核。