【问题标题】:Linux kernel shows "WARNING: at arch/x86/mm/pageattr.c:962 change_page_attr_set_clr" without explanationLinux内核显示“警告:在arch/x86/mm/pageattr.c:962 change_page_attr_set_clr”,没有解释
【发布时间】:2021-09-09 20:50:26
【问题描述】:

我正在编写一个针对 Linux v3-v4 的 x86_64 内核模块,它在内核符号的地址上使用 set_memory_rw()。虽然通话有效,但我收到警告但没有任何解释:

[  596.183643] ------------[ cut here ]------------
[  596.183667] WARNING: at arch/x86/mm/pageattr.c:962 change_page_attr_set_clr+0x2ca/0x450()

以前我使用了另一种方法,称为 virt_to_page(),然后是 set_pages_rw()。然而,正如内核源代码所说,这是一个已弃用的 API,它建议使用 set_memory_rw() 代替

这些 API 应被视为已弃用,并且可能会 将来会被删除。 [...] 具体来说,旧 API 的许多用户都有一个虚拟地址, 在该地址上调用 virt_to_page() 或 vmalloc_to_page() 获取旧 API 所需的 struct page*。 要转换这些情况,请在原始文件上使用 set_memory_*() 虚拟地址,不要使用这些函数。

谁能解释这里的问题是什么?
我想我绊倒了this check,这表明我可以添加*addr &= PAGE_MASK;,但我不想盲目地这样做。

【问题讨论】:

  • “我收到警告,但没有任何解释” - 解释可能在警告消息所指的代码中。在您的情况下,您需要检查的是 arch/x86/mm/pageattr.c:962 行。即使没有解释,该行也应该包含一个失败的检查,这可以给你一个提示是哪里出了问题。请注意,一行代码特定于您的 Linux 内核版本和补丁。例如。 3.10.108 版在给定行不包含警告:elixir.bootlin.com/linux/v3.10.108/source/arch/x86/mm/…
  • @Tsyvarev 在我的案例中,第 962 行等于标准 941:elixir.bootlin.com/linux/v3.10.108/source/arch/x86/mm/… - 虽然我看到了支票,但我不清楚问题出在哪里......它是否强制地址指向页面的开头?
  • "是否强制地址指向页面的开头?" - 是的,它需要地址是页面对齐的。无论您使用何种架构(x86、arm 等),它都无法将 特定 地址设置为可写或可读。内存可写性或可读性的最小单位是

标签: linux linux-kernel x86 kernel-module


【解决方案1】:

我认为我正在检查此检查,这表明我可以添加 *addr &= PAGE_MASK;但我不想盲目地去做。

对我来说听起来不错(这极有可能是“地址未与页面边界对齐”问题;而且极有可能不想盲目地这样做是个好主意)。

可能的情况是您有一系列您关心的地址(而不是一系列页面);这就是你解决这个问题的方式。这意味着:

a) 计算 numpages 时要小心(例如,原始范围可能类似于“4 个字节,一页末尾有 2 个字节,下一页开头有 2 个字节”)。正确的做法是将“起始地址”向下取整(pg = start_address & PAGE_MASK;),将“结束地址”向上取整(end_page = ((start_address + size_in_bytes - 1) | ~PAGE_MASK) + 1;),然后计算页数(numpages = end_page - pg)。

b) 同一页面中可能存在您不希望使用新页面属性的其他内容。如果是这种情况,那么您就遇到了一个基本的设计问题。

【讨论】:

  • 谢谢!这是一个很好的解释。现在我知道问题出在哪里以及如何解决该问题 - 虽然在我的情况下我没有发现任何跨越页面边界的函数实例,但它肯定会发生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 2021-05-12
  • 2013-06-03
  • 2016-01-09
相关资源
最近更新 更多