当内核映射到与进程本身相同的虚拟地址空间时,为什么需要“copy_from_user()”和“copy_to_user()”?

Shu*_*eng 2 c drivers kernel

当内核映射到与进程本身相同的虚拟地址空间时,为什么需要copy_from_user()它?copy_to_user()

为了学习目的开发了一些(玩具)内核模块后,我很快就意识到了这一点,copy_from_user()并且copy_to_user()需要将数据从用户空间缓冲区复制到用户空间缓冲区;否则与无效地址相关的错误会导致崩溃。

但是,如果0x1fffff虚拟地址指向用户空间缓冲区,那么为什么该地址在内核中无效?内核位于相同的虚拟地址空间中,因此0x1fffff将映射到相同的物理内存。

在此输入图像描述

在此输入图像描述

Ste*_*itt 6

地址空间映射在某些(不是全部!)体系结构上是相同的,但即使在它们相同的体系结构上,保护级别也是\xe2\x80\x99t。copy_from_user等服务于三个主要目的:

\n
    \n
  • 他们检查要读取或写入的内存的权限是否允许在用户空间中运行的进程读取或写入\xe2\x80\x94,这确保进程可以\xe2\x80\x99t欺骗内核进程不应该\xe2\x80\x99 能够访问内存;
  • \n
  • 它们允许特定的错误处理,以便保护错误不会导致内核崩溃,例如,如果请求的地址当前映射为\xe2\x80\x99t(想想零页或换出页);
  • \n
  • 它们确保内核不会超出其自身的保护,例如 SMAP或内核特定的地址空间 (S/390)。
  • \n
\n

某些体系结构使用内存布局,允许这些函数采用快捷方式,例如使用物理内存的直接映射,但您可以\xe2\x80\x99t假设情况如此,并且它不\xe2\x80\x99t处理所有情况无论如何(换出的页面不存在于物理内存中)。

\n

  • 即使在 x86 上,如果启用了 KPTI,地址空间映射也不相同(但这不会影响用户空间映射)。然而,据我所知,x86 和 ARM 上的用户模式和内核模式下的用户空间映射是相同的。SMAP 仅在实际副本周围被禁用(在内核代码中查找“STAC”/“CLAC”)。即使使用直接映射也可以交换用户页面。 (2认同)