Linux内核怎么判别地址是否坐落用户空间?

一、 问题描述

access_ok函数是什么原理?

Linux内核怎么判别地址是否坐落用户空间?

二、问题分析

我们在内核空间和用户空间进行数据仿制的时分有必要判别用户空间地址是否合法。
首要经过偶函数access_ok来判别。

1. Linux用安全教育手抄报户空间与内核地址空间

Linux 操作体系和驱动程序作业在内核空间,应用程序作业在用户空间,两者不能简单地运用指针传递数据,由于Linux运用的虚拟内存机制,用户空间的数据或许被换出,当内核空间运用用户空间指针时,对应的数据或许不在内存中。

一般32位Linux内核地址空间区源码编辑器编程猫下载别03G为用户空间,34G为内核空间。留神这里是32位内核地址空间差异,64位内核地址空间差异是不同的。

Linux内核怎么判别地址是否坐落用户空间?

  • 进程寻址空间0~4G
    
  • 进程在用户态只能拜访0~3G,只需进入内核态才能拜访3G~4G
    
  • 进程经过体系调用进入内核态
    
  • 每个进程虚拟空间的3G~4G部分是相linux体系装置同的
    
  • 进程从用户态进入内核态不会引起CR3的改动但会引起堆栈的改动
    

2. access_ok详解

原型汇编指令集

access_ok ( type,addr,size);

功用:

access_ok — 查看用户空间指针是否有用

留神,依据体系结安全教育手抄报构的不同,这个函数或许仅仅查看指针是否在用户空间规划内安全期是哪几天,在调用这个函数之后,内存操作体系的五大功用拜访函数或许依然回来 -EFAULT

参数阐明:

type

Type of access: VERIFY_READ or VERIFY_WRITE.
请留神,VERIFY_WRITE是VERIFY_READ的超集——假定写入一个块是安全的,那么从它读取总是安全的。

addr
要查看的块的linux常用指令开端的用安全户空间指针
size
要查看的块的大小

回来值:

此函数查看用户空间中的内存块是否可用。假定可用,则操作体系的主要功用是回来真(非0值),否则回来假 (0) 。

2. 源码分析

#define access_ok(type, addr, size)	(__range_ok汇编指令cld(addr, size) == 0)
/* We use 33-bit arithmetic here... */
#define __range_ok(addr, size) ({ 
unsigned long flag,安全手抄报 roksum; 
__chk_user_ptr(ad汇编指令clddr);	
__asm__("adds %1, %2安全期是哪几天, %3; sbcccs %1, %1, %0;linux重启指令 movcc %0, #0" 
: "=&安全期计算器r" (flag), "=&r" (roksum) 
: "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_li操作体系的五大功用mit) 
: "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详解如下Linux
参数对应:

f源码编辑器手机版下载lag   --------  %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 -linux操作体系基础知识 flag - 1

也便是(addr + size) – (current_thread_info()->addr_limit) – 1,操作影响符号位。.

假定(addr + size) >= (current_thread_info()->addr_汇编指令movlimit) – 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. 运用实例

我们在内核仿制数据到用户空间或许从用户空间仿制数源码超市据到内核空间,都linux指令需求判别用户空间地址是否在用户空间。

sta操作体系是什么的接口tic inline unsigned long __must_check copy_frolinux必学的60个指令m_user(v操作体系期末考试试题及答案oid *to, const void __use操作体系是一种r *from, unsigned long n)
{
if (access_ok(VERIFY_READ, from, n))
n = __copy_frolinux常用指令m_user(to, from, n);
else /* security h汇编指令cldole - plug it */
memset(t源码编辑器o, 0, n);
return n操作体系的主要功用是;
}
static inline unsigned long __must_check copy_to_user(void _操作体系是什么的接口_user *to, co操作体系有哪些nst void *from, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
n = __copy_t安全期计算器o_user(to, from, n);
return n;
}