access_ok

access_ok()
用来代替老版本的 verify_area()
检查用户空间指针是否可用

函数原型:

access_ok (type, addr, size);

变量说明:
type : 访问类型,其值可为 VERIFY_READ 或 VERIFY_WRITE 。
addr : 用户空间的指针变量,指向一个要检查的内存块开始处。
size : 要检查内存块大小

注意:
VERIFY_WRITE 是 VERIFY_READ 的超集
如果可以安全写内存块,那么肯定能读到内存块。

返回值:
此函数检查用户空间中的内存块是否可用。
如果可用,则返回真(非0值),否则返回假 (0) 。

代码示例:

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;

参考:https://blog.csdn.net/dfz87292/article/details/102394781?utm_term=accessok%E5%87%BD%E6%95%B0&utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2allsobaiduweb~default-0-102394781&spm=3001.4430
//=======================================================================

kernel get_user 示例

在内核空间和用户空间交换数据时, get_user 和 put_user 是两个两用的函数。
相对于 copy_to_user 和 copy_from_user ,主要用于完成一些简单类型变量(char、int、long等)的拷贝任务,
对于一些复合类型的变量,比如数据结构或者数组类型,get_user 和 put_user 函数还是无法胜任,
这两个函数内部将对指针指向的对象长度进行检查,在 arm 平台上只支持长度为1,2,4,8的变量。

struct Demo {int index;int count;
};// arg1 是用户空间传递下来的地址
struct Demo __user *demo1 = (struct Demo __user *)arg1;
// index 用来承接用户空间的对应值
int index;if (get_user(index, &demo1->index))return -EFAULT;// arg2 是用户空间传递下来的地址
int count = 2;
struct Demo __user *demo2 = (struct Demo __user *)arg2;if (put_user(count, &demo2->count))return -EFAULT;

//=======================================================================

put_user 和 get_user 具体分析

#define put_user(x, ptr)                 \
({                              \void __user *__p = (ptr);             \might_fault();                     \access_ok(VERIFY_WRITE, __p, sizeof(*ptr)) ?       \__put_user((x), ((__typeof__(*(ptr)) __user *)__p)) :  \-EFAULT;                   \
})#define __put_user(x, ptr) \
({                              \__typeof__(*(ptr)) __x = (x);             \int __pu_err = -EFAULT;                   \__chk_user_ptr(ptr);                                    \switch (sizeof (*(ptr))) {                \case 1:                            \case 2:                            \case 4:                            \case 8:                            \__pu_err = __put_user_fn(sizeof (*(ptr)), \ptr, &__x);        \break;                     \default:                       \__put_user_bad();              \break;                     \}                          \__pu_err;                      \
})static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
{return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0;
}
#define get_user(x, ptr)                 \
({                              \const void __user *__p = (ptr);               \might_fault();                     \access_ok(VERIFY_READ, __p, sizeof(*ptr)) ?        \__get_user((x), (__typeof__(*(ptr)) __user *)__p) :\((x) = (__typeof__(*(ptr)))0,-EFAULT);        \
})static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
{return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0;
}#define __get_user(x, ptr)                 \
({                              \int __gu_err = -EFAULT;                   \__chk_user_ptr(ptr);                   \switch (sizeof(*(ptr))) {              \case 1: {                      \unsigned char __x = 0;                \__gu_err = __get_user_fn(sizeof (*(ptr)), \ptr, &__x);        \(x) = *(__force __typeof__(*(ptr)) *) &__x;   \break;                     \};                         \case 2: {                      \unsigned short __x = 0;               \__gu_err = __get_user_fn(sizeof (*(ptr)), \ptr, &__x);        \(x) = *(__force __typeof__(*(ptr)) *) &__x;   \break;                     \};                         \case 4: {                      \unsigned int __x = 0;             \__gu_err = __get_user_fn(sizeof (*(ptr)), \ptr, &__x);        \(x) = *(__force __typeof__(*(ptr)) *) &__x;   \break;                     \};                         \case 8: {                      \unsigned long long __x = 0;           \__gu_err = __get_user_fn(sizeof (*(ptr)), \ptr, &__x);        \(x) = *(__force __typeof__(*(ptr)) *) &__x;   \break;                     \};                         \default:                       \__get_user_bad();              \break;                     \}                          \__gu_err;                      \
})

小彩蛋

static inline void uaccess_disable(void)
{__uaccess_disable(ARM64_HAS_PAN);
}static inline void uaccess_enable(void)
{__uaccess_enable(ARM64_HAS_PAN);
}

access_ok和get_user和put_user简介相关推荐

  1. linux put函数,Linux内核中的get_user和put_user

    当标号1处发生缺页异常时,系统将调用do_page_fault提交物理页面,然后跳到__get_user_bad继续执行.get_user函数如果成果执行则返回1,否则返回-EFAULT. put_u ...

  2. linux get_user,linux内核中的get_user和put_user

    内核版本:2.6.14 CPU平台:arm本文引用地址:http://www.eepw.com.cn/article/201611/319994.htm 在内核空间和用户空间交换数据时,get_use ...

  3. linux设备驱动读书笔记

    linux设备驱动读书笔记 设备驱动简介 机制:提供什么能力 策略:如何使用这些能力 在编写驱动时, 程序员应当编写内核代码来存取硬件, 但是不能强加特别的策略给用户, 因为不同的用户有不同的需求. ...

  4. linux设备驱动读书笔记(转)

    linux设备驱动读书笔记 设备驱动简介 机制:提供什么能力 策略:如何使用这些能力 在编写驱动时, 程序员应当编写内核代码来存取硬件, 但是不能强加特别的策略给用户, 因为不同的用户有不同的需求. ...

  5. linux驱动程序ioctl函数用法

    一. 什么是ioctl     ioctl是设备驱动程序中对设备的I/O通道进行管理的函数.所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率.马达的转速等等.它的调用个数如 ...

  6. linux copy_from/to_user原理

    转载地址:http://www.poluoluo.com/server/201107/138420.html 在研究dahdi驱动的时候,见到了一些get_user,put_user的函数,不知道其来 ...

  7. 使用 Linux 系统调用的内核命令

    探究 SCI 并添加自己的调用 M. Jones 2010 年 9 月 21 日发布 WeiboGoogle+用电子邮件发送本页面 1 系统调用就是用户空间应用程序和内核提供的服务之间的一个接口.由于 ...

  8. Linux驱动编程 step-by-step (六) 用户地址检测 简单模块调试 以及一些杂项

    用户地址检测 简单模块调试 以及一些杂项 检测用户空间地址的有效性 上一节中提到在read write时候要检测用户空间传递的参数地址是否是有效地址,有的内核函数会自行检测,但是在调用轻量级的内核函数 ...

  9. linux 内核将两个设备相关联,linux用户空间和内核空间交换数据

    转载地址:http://www.poluoluo.com/server/201107/138420.html 在研究dahdi驱动的时候,见到了一些get_user,put_user的函数,不知道其来 ...

最新文章

  1. python程序员总结的一些基本语法
  2. 在docker中构建普通java程序_Docker入门-构建第一个Java程序
  3. Linux 系统的硬链接和软链接详解
  4. 奇怪的微信内置浏览器IOS版和Anroid 版
  5. stringr | 文本处理方法(Ⅰ-1):字符串处理函数(上)
  6. selenium python grid
  7. DRF基类APIView的子类GenericAPIView
  8. 高效获得准确的中国地图数据并进行可视化
  9. 圈子论坛社区小程序,交友,博客,社交,陌生人社交,即时聊天 前后端开源PHP
  10. Notepad++ 6.9 官方中文版
  11. [转]Linux下的虚拟光驱和虚拟软驱
  12. CSS揭秘读书笔记-第一章 引言
  13. 如何新建一个css到html,新建一个css样式
  14. 服务器:CPU虚拟化_服务器虚拟化技术
  15. 阶的估计I 无穷小量与强函数2 Taylor公式 基本初等函数与三角函数的阶
  16. css加空格的方法,css如何加空格
  17. Json数据转换成Map对象
  18. 2021年熔化焊接与热切割试题及解析及熔化焊接与热切割模拟试题
  19. 数据库事务脏读、幻读、不可重复读的解决方法
  20. 详细讲解:零知识证明 之 ZCash 完整的匿名交易流程

热门文章

  1. java 重量级锁_轻量级锁和重量级锁的区别分别有哪些?java锁机制教程
  2. Python注释规范
  3. Github 爆火!21 岁理工男开源的十六进制编辑器爆赞
  4. 读书笔记: nodejs API 参考
  5. 寻声定位 matlab,一种自动调节范围大的寻声定位拍摄设备的制作方法
  6. Cocos2d-x 3.2 大富翁游戏项目开发-第二十六部分 人物技能
  7. 基于GLSurfaceView实现自定义Camera
  8. 用ajax修改成功怎么返回页面,jquery操作ajax返回的页面元素
  9. java kill 进程命令_Windows使用Java调用taskkill命令结束进程
  10. java轻松玩转Excel之EasyExcel