access_ok和get_user和put_user简介
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简介相关推荐
- linux put函数,Linux内核中的get_user和put_user
当标号1处发生缺页异常时,系统将调用do_page_fault提交物理页面,然后跳到__get_user_bad继续执行.get_user函数如果成果执行则返回1,否则返回-EFAULT. put_u ...
- linux get_user,linux内核中的get_user和put_user
内核版本:2.6.14 CPU平台:arm本文引用地址:http://www.eepw.com.cn/article/201611/319994.htm 在内核空间和用户空间交换数据时,get_use ...
- linux设备驱动读书笔记
linux设备驱动读书笔记 设备驱动简介 机制:提供什么能力 策略:如何使用这些能力 在编写驱动时, 程序员应当编写内核代码来存取硬件, 但是不能强加特别的策略给用户, 因为不同的用户有不同的需求. ...
- linux设备驱动读书笔记(转)
linux设备驱动读书笔记 设备驱动简介 机制:提供什么能力 策略:如何使用这些能力 在编写驱动时, 程序员应当编写内核代码来存取硬件, 但是不能强加特别的策略给用户, 因为不同的用户有不同的需求. ...
- linux驱动程序ioctl函数用法
一. 什么是ioctl ioctl是设备驱动程序中对设备的I/O通道进行管理的函数.所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率.马达的转速等等.它的调用个数如 ...
- linux copy_from/to_user原理
转载地址:http://www.poluoluo.com/server/201107/138420.html 在研究dahdi驱动的时候,见到了一些get_user,put_user的函数,不知道其来 ...
- 使用 Linux 系统调用的内核命令
探究 SCI 并添加自己的调用 M. Jones 2010 年 9 月 21 日发布 WeiboGoogle+用电子邮件发送本页面 1 系统调用就是用户空间应用程序和内核提供的服务之间的一个接口.由于 ...
- Linux驱动编程 step-by-step (六) 用户地址检测 简单模块调试 以及一些杂项
用户地址检测 简单模块调试 以及一些杂项 检测用户空间地址的有效性 上一节中提到在read write时候要检测用户空间传递的参数地址是否是有效地址,有的内核函数会自行检测,但是在调用轻量级的内核函数 ...
- linux 内核将两个设备相关联,linux用户空间和内核空间交换数据
转载地址:http://www.poluoluo.com/server/201107/138420.html 在研究dahdi驱动的时候,见到了一些get_user,put_user的函数,不知道其来 ...
最新文章
- python程序员总结的一些基本语法
- 在docker中构建普通java程序_Docker入门-构建第一个Java程序
- Linux 系统的硬链接和软链接详解
- 奇怪的微信内置浏览器IOS版和Anroid 版
- stringr | 文本处理方法(Ⅰ-1):字符串处理函数(上)
- selenium python grid
- DRF基类APIView的子类GenericAPIView
- 高效获得准确的中国地图数据并进行可视化
- 圈子论坛社区小程序,交友,博客,社交,陌生人社交,即时聊天 前后端开源PHP
- Notepad++ 6.9 官方中文版
- [转]Linux下的虚拟光驱和虚拟软驱
- CSS揭秘读书笔记-第一章 引言
- 如何新建一个css到html,新建一个css样式
- 服务器:CPU虚拟化_服务器虚拟化技术
- 阶的估计I 无穷小量与强函数2 Taylor公式 基本初等函数与三角函数的阶
- css加空格的方法,css如何加空格
- Json数据转换成Map对象
- 2021年熔化焊接与热切割试题及解析及熔化焊接与热切割模拟试题
- 数据库事务脏读、幻读、不可重复读的解决方法
- 详细讲解:零知识证明 之 ZCash 完整的匿名交易流程
热门文章
- java 重量级锁_轻量级锁和重量级锁的区别分别有哪些?java锁机制教程
- Python注释规范
- Github 爆火!21 岁理工男开源的十六进制编辑器爆赞
- 读书笔记: nodejs API 参考
- 寻声定位 matlab,一种自动调节范围大的寻声定位拍摄设备的制作方法
- Cocos2d-x 3.2 大富翁游戏项目开发-第二十六部分 人物技能
- 基于GLSurfaceView实现自定义Camera
- 用ajax修改成功怎么返回页面,jquery操作ajax返回的页面元素
- java kill 进程命令_Windows使用Java调用taskkill命令结束进程
- java轻松玩转Excel之EasyExcel