access_ok函数是什么原理?
一、 问题描述
access_ok函数是什么原理?
问题
二、问题分析
我们在内核空间和用户空间进行数据拷贝的时候必须判断用户空间地址是否合法。主要通过偶函数access_ok来判断。
1. Linux用户空间与内核地址空间
Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间,两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当内核空间使用用户空间指针时,对应的数据可能不在内存中。
通常32位Linux内核地址空间划分0~3G为用户空间,3~4G为内核空间。注意这里是32位内核地址空间划分,64位内核地址空间划分是不同的。
进程寻址空间0~4G
进程在用户态只能访问0~3G,只有进入内核态才能访问3G~4G
进程通过系统调用进入内核态
每个进程虚拟空间的3G~4G部分是相同的
进程从用户态进入内核态不会引起CR3的改变但会引起堆栈的改变
2. access_ok详解
原型:
access_ok ( type,addr,size);
功能:
access_ok — 检查用户空间指针是否有效注意,根据体系结构的不同,这个函数可能只是检查指针是否在用户空间范围内,在调用这个函数之后,内存访问函数可能仍然返回 -EFAULT
参数说明:
typeType of access: VERIFY_READ or VERIFY_WRITE.请注意,VERIFY_WRITE是VERIFY_READ的超集——如果写入一个块是安全的,那么从它读取总是安全的。addr要检查的块的开始的用户空间指针size要检查的块的大小
返回值:
此函数检查用户空间中的内存块是否可用。如果可用,则返回真(非0值),否则返回假 (0) 。
2. 源码分析#define access_ok(type, addr, size) (__range_ok(addr, size) == 0)
We use 33-bit arithmetic here...
#define __range_ok(addr, size) ({
unsigned long flag, roksum;
__chk_user_ptr(addr);
__asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0"
: "=&r" (flag), "=&r" (roksum)
: "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit)
: "cc");
flag; })
static inline void __chk_user_ptr(const volatile void *p, size_t size)
{
assert(p >= __user_addr_min && p + size <= __user_addr_max);
}
其中__range_ok详解如下:参数对应:
flag -------- %0
roksum -------- %1
addr -------- %2
size -------- %3
汇编指令详解
adds %1, %2, %3
等价于:
rosum = addr + size
这个操作会影响状态位(目的是影响是进位标志C)。
以下的两个指令都带有条件CC,也就是当C=0的时候才执行;如果上面的加法指令进位了(C=1),则以下的指令都不执行,flag就为初始值current_thread_info()->addr_limit(非0),并返回。如果没有进位(C=0),就执行下面的指令:
sbcccs %1, %1, %0
该指令等价于
rosum = rosum - flag - 1
也就是(addr + size) - (current_thread_info()->addr_limit) - 1,操作影响符号位。.
如果(addr + size) >= (current_thread_info()->addr_limit) - 1,则C=1如果(addr + size) < (current_thread_info()->addr_limit) - 1,则C=0当C=0的时候执行以下指令,否则跳过(flag非零)。
movcc %0, #0
等价于
flag = 0,给flag赋值0。
综上所述:__range_ok宏等价于:
如果(addr + size) >= (current_thread_info()->addr_limit) - 1,返回非零值
如果(addr + size) < (current_thread_info()->addr_limit),返回零
而access_ok就是检验将要操作的用户空间的地址范围是否在当前进程的用户地址空间限制中。这个宏的功能很简单,完全可以用C实现,不是必须使用汇编。 由于这两个函数使用频繁,就使用汇编来实现部分功能来增加效率。
3. 使用实例
我们在内核拷贝数据到用户空间或者从用户空间拷贝数据到内核空间,都需要判断用户空间地址是否在用户空间。
static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
{
if (access_ok(VERIFY_READ, from, n))
n = __copy_from_user(to, from, n);
else security hole - plug it
memset(to, 0, n);
return n;
}
static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
n = __copy_to_user(to, from, n);
return n;
}
图片新闻
最新活动更多
-
11月22日立即报名>> 【线下论坛】华邦电子与莱迪思联合技术论坛
-
即日-11.30免费预约申请>>> 燧石技术-红外热成像系列产品试用活动
-
11月30日立即试用>> 【有奖试用】爱德克IDEC-九大王牌安全产品
-
即日-12.26火热报名中>> OFweek2024中国智造CIO在线峰会
-
限时免费下载立即下载 >>> 2024“机器人+”行业应用创新发展蓝皮书
-
即日-2025.8.1立即下载>> 《2024智能制造产业高端化、智能化、绿色化发展蓝皮书》
推荐专题
- 1 格力联手优傲!协作机器人领域风云将起?
- 2 同源共创 模式革新 | 华天软件皇冠CAD(CrownCAD)2025新品发布会圆满举行
- 3 回顾 | OFweek 2024智能制造与半导体、印刷包装融合创新大会圆满落幕!
- 4 上海国际嵌入式展暨大会(embedded world China )与多家国际知名项目达成合作
- 5 iEi威强电新品丨IMBA-AM5:工业计算的强劲引擎
- 6 史上首次,大众终于熬不住开启40亿降本计划!关3个工厂,裁员万名...
- 7 守护绿色学习空间,EK超低温热泵服务对外经济贸易大学图书馆
- 8 颜值高 有“门”道|贝特威汽车门板内饰AI视觉检测解决方案
- 9 现场直击 | 维科网带你逛 VisionChina2024(深圳),领略机器视觉盛宴!
- 10 观众登记启动 优解制造未来,锁定2025 ITES深圳工业展
发表评论
请输入评论内容...
请输入评论/评论长度6~500个字
暂无评论
暂无评论