百科问答小站 logo
百科问答小站 font logo



linux在系统调用进入内核时,为什么要将参数从用户空间拷贝到内核空间?不能直接访问,或是使用memcpy吗?非要使用copy_from_user才行吗? 第1页

  

user avatar   ivan-lam-50 网友的相关建议: 
      

在现代通用操作系统里面,cpu运行指令时,它的运级别分为用户态和内核态这两个态,内核要保护应用程序,不能让用户态的数据对内核进行污染。

那用户态要委托内核完成某个服务时(比如打开文件,访问文件内容),必须通过系统调用完成。系统调用传参,跟函数传参是比较类似的,分为基础类型和内存块类型这两类。

1. 对于基础类型,通过寄存器可以直接拷贝传递

2. 对内存块类型,C语言没有语言类型上的支持,必须通过指针进行传递,然后再访问指针指向的内存空间

如果你在Linux下要写一个字符驱动,必须定义一个file_operations结构,实现该文件的写操作细节,它的签名如下:

ssize_t XXX_drviver_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)

上述的len参数为基础类型,而buf就是内存块类型,你在该函数应该实现将buf指向并且长度为len的缓冲区写到驱动所表示的文件里面。

这里会遇到几个问题:

1. buf 指针是不是一个合法地址

2. 如果buf 指针是一个合法地地,但是该buf指针的空间,内核还没有给它分配物理地址空间怎么办

3. 如果黑客故意将buf值写成一个精心构造的内核地址,那驱动需要往该buf拷贝数据时(通过是read操作),那不是将数据写到内核态了吗?那黑客就可以通过这个问题来修改内核代码,控制内核执行,达成目标。

如果直接使用memcpy,上述这3个问题都无法解决。如果遇到的是场景1)和2),那么内核会Oops,如果是3),则攻击很可能成功。

copy_from_user和copy_to_user就是用来保证内核态安全地访问(读和写)用户态内存空间。

copy_from_user/copy_to_user 的实现原理非常简单,如下:

1. 如果buf空间属于内核态空间,直接返回出错,不处理(这是解决上述场景3)

2. copy_from_user/copy_to_user使用精心布置的访存汇编实现,并指这个汇编指令所在的地址全部登记起来(称为extable表)。运行时出现上述场景1)和2),首先会发生缺页异常,进入内核do_page_fault流程;然后检查出错的PC地址是不是早已在extable登记好的,如果是,同表示该缺页异常是copy_from_user/copy_to_user函数产生的。最后才检查该地址是否为该进程的合法地址,如果是则分配物理页并处理,否则就是非法地址,把进程给杀死(发送sigsegv信号)。




  

相关话题

  有没有RAM版的U盘? 
  Linux C++ 服务器端这条线怎么走?一年半能做出什么? 
  linux的TCP连接数量最大不能超过65535个,那服务器是如何应对百万千万的并发的? 
  C++ 中,std::atomic 是真正的「原子」吗? 
  如何解决Linux下信号产生的死锁? 
  终端、Shell、tty 和控制台(console)有什么区别? 
  熟悉 Ubuntu 的新手怎么玩转 Arch? 
  Fuchsia OS可以从Cast OS保留数据升级,是否说明Fuchsia只是Linux套壳? 
  Linux 下 “一切皆文件” 思想的本质和好处在哪里?与 Windows 下的文件管理思想有啥差别? 
  嵌入式linux内核在内存中运行地址0x30008000到内存起始运行地址0x30000000中的(0x8000=32k)怎么回事? 

前一个讨论
为什么国内各大云存储服务都不支持 WebDAV?
下一个讨论
雷雨中的周萍算渣男么?





© 2024-11-25 - tinynew.org. All Rights Reserved.
© 2024-11-25 - tinynew.org. 保留所有权利