Q:一直知道内核和用户态的数据交互前都需要 校验地址的合法性,一般都用copy_from/to_user完成数据拷贝,那么为什么要这样呢??

A:看了一些blog以及Stack Overflow 主要说的是安全性:

Linux Kernel: How does copy_to_user work?
Why can't you just call, say, memcpy? Two reasons.
One, the kernel is capable of writing to any memory. User process's can't. copy_to_user needs to check dst to ensure it is accessible and writable by the current process.
Two, depending on the architecture, you can't simply copy data from kernel to user-space. You might need to do some special setup first, invalidate certain caches, or use special operations.
而内核可以访问任意内存。copy_to_user需要 通过当前进程来 检查目标的可写权限   (而用户 进程无法检查内核空间目标地址的 写权限 )
同时:检查指针所指的内存是否有效

 
设想一下:我们在写file_opeteration的write函数时:write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)/read(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
1、buf地址不合法
2、buf地址合法,内核还没有给它映射物理地址
3、如果buf是个一个内核地址, read的时候不就是内核到内核的拷贝么??
 
所以为了解决上述问题就有了copy_xx_user-----------
  • 地址检查,不合法返回
  • copy_xx_user 使用精心布置的访存汇编实现,并指这个汇编指令所在的地址全部登记起来(称为extable表)。出现2时------>会发生缺页异常,进入内核do_page_fault流程;然后检查出错的PC地址是不是早已在extable登记好的,如果是,同表示该缺页异常是copy_from_user/copy_to_user函数产生的。最后才检查该地址是否为该进程的合法地址,如果是则分配物理页并处理,否则就是非法地址,把进程给杀死(发送sigsegv信号)


 
顺便有几个疑问??参考:https://www.cnblogs.com/alantu2018/p/8527077.html   http://www.mysixue.com/?p=114#33   这些blog写的详细
1、为什么会产生page fault?
2、发生缺页的上下文是否可以位于内核态
有可能在内核态,但这种情况下,发生缺页的地址只能位于用户态地址空间,而且也只能为exceptions table中预先定义好的异常,如果exceptions table中没有预先定义的处理,或者缺页的地址位于内核态地址空间,则表示错误,进入oops流程。通常属于异常,会导致oops。、、-----copy_xx_user干的就是这事
    /*
* If we're in an interrupt, have no user context or are running
* in an atomic region then we must not take the fault:
*/
if (unlikely(in_atomic() || !mm)) {mm 为空表示内核线程
bad_area_nosemaphore(regs, error_code, address);
return;
}

3、发生缺页的地址是否可以位于内核态地址空间----
有可能,发生缺页的内核态地址仅可能位于vmalloc区;在使用Vmalloc分配物理内存时,确实进行了映射,创建了页表项。
但是,其修改的仅为内核的主内核页表,并没有更新相关进程的页表;进程访问时,相关进程的页表中并没有Vmalloc分配内存相应的页表项,所以会触发page fault
//该分支表明发生缺页时是发生在访问内核空间时
if (unlikely(address >= TASK_SIZE)) {
//表示 代码是在内核态访问内核态不存在 的地址,转到vmalloc_fault处理分支,可能是访问了不连续的内核页面
if (!(error_code & 5))
goto vmalloc_fault;
//做相应出错处理
goto bad_area_nosemaphore;
}

关于内存管理文章见连接:

https://files.cnblogs.com/files/codestack/fp%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.zip

 
1、内核页表中的内容为所有进程共享,每个进程都有自己的“进程页表”,“进程页表”中映射的线性地址包括两部分:
用户态
内核态
其中,内核态地址对应的相关页表项,对于所有进程来说都是相同的(因为内核空间对所有进程来说都是共享的),而这部分页表内容其实就来源于“内核页表”,即每个进程的“进程页表”中内核态地址相关的页表项都是“内核页表”的一个拷贝。
2、“内核页表”由内核自己维护并更新,在vmalloc区发生page fault时,将“内核页表”同步到“进程页表”中。以32位系统为例,内核页表主要包含两部分:
线性映射区
vmalloc区
其中,线性映射区即通过TASK_SIZE偏移进行映射的区域,对32系统来说就是0-896M这部分区域,映射对应的虚拟地址区域为TASK_SIZE-TASK_SIZE+896M。这部分区域在内核初始化时就已经完成映射,并创建好相应的页表,即这部分虚拟内存区域不会发生page fault。
vmalloc区,为896M-896M+128M,这部分区域用于映射高端内存,有三种映射方式:vmalloc、固定、临时,这里就不像述了。。
以vmalloc为例(最常使用),这部分区域对应的线性地址在内核使用vmalloc分配内存时,其实就已经分配了相应的物理内存,并做了相应的映射,建立了相应的页表项,但相关页表项仅写入了“内核页表”,并没有实时更新到“进程页表中”,内核在这里使用了“延迟更新”的策略,将“进程页表”真正更新推迟到第一次访问相关线性地址,发生page fault时,此时在page fault的处理流程中进行“进程页表”的更新:

都知道的copy_from_user的更多相关文章

  1. 3年Java开发都知道的Redis数据结构和通用命令

    Redis的数据结构 Redis支持多种不同的数据结构,包括5种基础数据结构和几种比较复杂的数据,这些数据结构可以满足不同的应用场景. 五种基础数据结构 String:字符串,是构建其他数据结构的基础 ...

  2. What every computer science major should know 每一个计算机科学专业的毕业生都应该都知道的

    Given the expansive growth in the field, it's become challenging to discern what belongs in a modern ...

  3. C# 范型约束 new() 你必须要知道的事

    C# 范型约束 new() 你必须要知道的事 注意:本文不会讲范型如何使用,关于范型的概念和范型约束的使用请移步谷歌. 本文要讲的是关于范型约束无参构造函数 new 的一些底层细节和注意事项.写这篇文 ...

  4. 每个极客都应该知道的Linux技巧

    每个极客都应该知道的Linux技巧 2014/03/07 | 分类: IT技术 | 0 条评论 | 标签: LINUX 分享到:18 本文由 伯乐在线 - 欣仔 翻译自 TuxRadar Linux. ...

  5. 隔壁小孩都要知道的Drupal配置

    i春秋作家:Arizona 原文来自:隔壁小孩都要知道的Drupal配置 隔壁小孩都要知道的Drupal配置 Drupal是一个开源的PHP内容管理系统,具有相当复杂的架构.它还具有强大的安全模型.感 ...

  6. PDB文件:每个开发人员都必须知道的 PDB Files

    PDB文件:每个开发人员都必须知道的   PDB Files: What Every Developer Must Knowhttp://www.wintellect.com/CS/blogs/jro ...

  7. 每一个JavaScript开发者都应该知道的10道面试题

    JavaScript十分特别.而且差点儿在每一个大型应用中起着至关关键的数据.那么,究竟是什么使JavaScript显得与众不同,意义非凡? 这里有一些问题将帮助你了解其真正的奥妙所在:   1.你能 ...

  8. 每个开发者都应该知道的SOLID原则

    每个开发者都应该知道的SOLID原则 单一职责原则(SRP) 它为什么违反了 SRP? 这种设计将来会带来什么问题? 开闭原则(OCP) 如何使它(AnimalSound)符合 OCP? 里氏替换原则 ...

  9. 程序员必须要知道的Hadoop的一些事实

    程序员必须要知道的Hadoop的一些事实.现如今,Apache Hadoop已经无人不知无人不晓.当年雅虎搜索工程师Doug Cutting开发出这个用以创建分布式计算机环境的开源软...... 1: ...

随机推荐

  1. MeteoInfoLab脚本示例:Hamawari-8 netCDF data

    示例数据:ftp://ftp.bom.gov.au/anon/sample/catalogue/Satellite/IDE00220.201507140300.nc 该数据的分辨率很高(22000*2 ...

  2. Android Jetpack从入门到精通(深度好文,值得收藏)

    前言 即学即用Android Jetpack系列Blog的目的是通过学习Android Jetpack完成一个简单的Demo,本文是即学即用Android Jetpack系列Blog的第一篇. 记得去 ...

  3. 【UR #12】实验室外的攻防战

    UOJ小清新题表 题目内容 依然没有粘题面主要是UOJ的题面都太长了qwq UOJ链接 一句话题意:给出两个序列 \(A\) 和 \(B\),对于 \(A\) 进行若干次操作,每次给出一个 \(i\) ...

  4. Django创建表时报错django.db.utils.InternalError: (1366问题解决记录

    问题出现 执行Python manage.py makemigrations生成创建表的py文件 执行python manage.py migrate创建数据表 界面出现报错 问题原因 网上搜索原因, ...

  5. sql 删除所有存储过程

    1.执行以下sql语句即可删除所有存储过程 --/**********删除所有存储过程*************************/-- use 数据库名 go declare @tname v ...

  6. MySql中varchar(10)和varchar(100)的区别

    背景 许多使用MySQL的同学都会使用到varchar这个数据类型.初学者刚开始学习varchar时,一定记得varchar是个变长的类型这个知识点,所以很多初学者在设计表时,就会把varchar(X ...

  7. STL: set和map的区别、联系、使用

    set是一种关联式容器,其特性如下: set以RBTree作为底层容器 所得元素的只有key(键)没有value(值) 不允许出现键重复 所有的元素都会被自动排序 不能通过迭代器来改变set的值,因为 ...

  8. 【洛谷】 cpp-->c 一道好玩的显示题

    P1538 这题真的好玩 题目背景 HNSDFZ的同学们为了庆祝春节,准备排练一场舞会. 题目描述 在越来越讲究合作的时代,人们注意的更多的不是个人物的舞姿,而是集体的排列. 为了配合每年的倒计时,同 ...

  9. 去重想到set,排序想到Arrays.sort

    package test; import java.util.Arrays; import java.util.Scanner; import java.util.Set; import java.u ...

  10. 强网杯web之假的反序列化漏洞

    说明 打强网杯的时候一直在写论文, 做林逸师傅的培训题目. 现在得空,还是看了一部分的题目和wp. 源码 源码一共三部分, 这里只写下我知识盲区的一部分,作为自己的记录. <?php highl ...