arm64 UAO/PAN 特性对用户空间边界读写的影响(copy_from/to_user)

本文详细解释了UAO和PAN特性如何通过限制地址空间范围和特权访问,增强Linuxarm64系统中内核与用户空间的数据交换安全,以及它们在硬件和软件层面的具体实现和应用,特别提到bpf_probe_read_kernel与bpf_probe_read_user之间的区别。

1 UAO/PAN 特性由来

linux 内核空间与用户空间通过 copy_from/to_user 进行数据拷贝交换,而不是通过简单的 memcpy/strcpy 进行拷贝复制,原因是安全问题(这里不详细展开)。

而对应内核有 __probe_kernel_read/__probe_user_read读取用户空间数据,该类接口在用户空间地址存在问题时内核读取用户空间不会导致内核系统出现问题。

那么 __probe_kernel_read和__probe_user_read 具体区别在哪里呢?通过源码可以看到具体区别只有一处:
__probe_kenel_read中设置 addr_limit 为 set_fs(KERNEL_DS),而 __probe_user_read 中设置 addr_limit 为 set_fs(USER_DS),首先需要说明每个任务的 thread 结构中都有一个
addr_limit 变量,该变量标记了该任务能访问的内核空间代码范围,比如内核线程都为addr_limit == KERNEL_DS 表明可以访问任意内核和用户空间地址,而用户态程序 addr_limit == USER_DS 表明只能访问用户空间地址,不能访问内核空间地址,当然在执行一些特殊操作时可以通过 set_fs(KERNEL_DS) 让用户态程序进入内核后可以访问内核地址空间,不过在访问完后会恢复原来的值,对于 arm64 还会在 set_fs 中会设置 set_thread_flag(TIF_FSCHECK)标记,作用是在返回用户空间时检查 addr_limit 是否恢复为 USER_DS。关于 USER_DS 和 KERNEL_DS 可以看内核中 asm/uaccess.h 中相关定义。

总之在这里两个函数会限制访问的地址空间范围,这里再看看 arm64 对 set_fs 的实现:

static inline void set_fs(mm_segment_t fs)
{
   
   
	current_thread_info()->addr_limit = fs;

	/*
	 * Prevent a mispredicted conditional call to set_fs from forwarding
	 * the wrong address limit to access_ok under speculation.
	 */
	spec_bar();

	/* On user-mode return, check fs is correct */
	set_thread_flag(TIF_FSCHECK);

	/*
	 * Enable/disable UAO so that copy_to_user() etc can access
	 * kernel memory with the unprivileged instructions.
	 */
	if (IS_ENABLED(CONFIG_ARM64_UAO) && fs == KERNEL_DS) --------------------------------------------(1)
		asm(ALTERNATIVE("nop", <
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值