Linux suse:
# cat /etc/os-release
NAME="SLES"
VERSION="12-SP2"
VERSION_ID="12.2"
PRETTY_NAME="SUSE Linux Enterprise Server 12 SP2"
ID="sles"
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:suse:sles:12:sp2"
# uname -r
4.4.120-92.70-default
在编译SUSE Linux Enterprise Server 12 SP时,使用低版本的docker镜像编译内核模块时,加载内核模块时出现:
# dmesg
[12996.210792] Spectre V2 : System may be vulnerable to spectre v2
[12996.210892] test: loading module not compiled with retpoline compiler.
[13299.232906] test: Unknown symbol mcount (err 0)
加载内核模块时:
(1)
# dmesg
[12996.210792] Spectre V2 : System may be vulnerable to spectre v2
[12996.210892] test: loading module not compiled with retpoline compiler.
指示系统可能受到 Spectre V2 漏洞的影响,并且正在加载的模块没有使用 retpoline 编译器进行编译。
Spectre V2(CVE-2017-5715)是 Spectre 漏洞家族中的一个变种,它是一种基于推测执行的侧信道攻击。Spectre V2 漏洞影响现代处理器,可能允许攻击者访问其他进程内存中的敏感信息。
Spectre V2 漏洞利用了分支预测的缺陷,这是一种现代处理器使用的性能优化技术。通过操纵分支的推测执行,攻击者可以欺骗处理器泄露应该是不可访问的敏感信息。
为了解决 Spectre V2 漏洞,需要在硬件和软件层面上采取综合的缓解措施。硬件厂商发布了包含处理器固件更新的微码更新,以在硬件层面上缓解漏洞。此外,操作系统厂商提供了软件补丁和更新,包括支持 Retpoline 的编译器和更新的内核,以在软件层面上缓解漏洞。
Retpoline(Return Trampoline)是一种软件缓解技术,用于应对 Spectre V2 漏洞。它是一种编译器技术,修改代码中的间接分支指令,防止推测执行访问未经授权的内存位置。Retpoline 可以在不需要昂贵的硬件修改的情况下缓解 Spectre V2 漏洞。
检查内核配置:检查您的内核配置,确保已启用retpoline支持。可以通过查看内核配置文件/proc/config.gz是否启用了retpoline选项:
# zgrep CONFIG_RETPOLINE /proc/config.gz
CONFIG_RETPOLINE=y
如果输出显示 CONFIG_RETPOLINE=y,则表示retpoline已启用。
这只是警告而已,不影响模块的加载运行。
(2)
# dmesg
[13299.232906] test: Unknown symbol mcount (err 0)
gcc 的 -pg 选项,它插入 mcount() 调用以与 gprof 一起使用。
当在Linux系统中加载内核模块时遇到 “Unknown symbol mcount (err 0)” 的错误消息时,这通常表示所加载的内核模块依赖于 mcount 符号,但该符号在当前系统内核中不可用或未定义。
mcount 是一个用于性能分析和跟踪的内核符号,通常由 gcc 编译器生成的代码调用。它用于计算函数调用的计数,以便进行性能分析和跟踪操作。
从 gcc 4.6 版开始,这个 mcount() 调用现在是 fentry()。
使用的 docker 容器 gcc 版本过低,低于 gcc 4.6,因此编译内核模块时出现了mcount符号,该符号在当前系统内核中是未定义。
# nm test.ko | grep mcount
U mcount
# cat /proc/kallsyms | grep mcount
ffffffff81eecb60 T __start_mcount_loc
ffffffff81f1dd78 T __stop_mcount_loc
可以看到当前内核版本没有 mcount 符号。
__start_mcount_loc 和 __stop_mcount_loc 这两个符号实际上是用于标记函数fentry()插装跟踪信息的起始和结束位置,这些符号是由编译器自动插入的。当使用 -pg 选项编译程序时,编译器会在每个函数的入口和出口处插入这些符号,以便在程序运行时收集函数调用和执行时间的数据。
__start_mcount_loc 标记了函数调用跟踪信息的起始位置,而 __stop_mcount_loc 则标记了其结束位置。这两个符号之间的范围表示了fentry() 插装数据的范围。
使用较高版本的docker(gcc)即可,比如 gcc 4.8:
# nm test.ko| grep __fentry__
U __fentry__
# cat /proc/kallsyms | grep __fentry__
ffffffff815f89d0 T __fentry__
内核当前镜像中有该内核符号__fentry__。文章来源:https://www.toymoban.com/news/detail-665418.html
(3)内核顶层 makefile文章来源地址https://www.toymoban.com/news/detail-665418.html
vim /usr/src/linux-4.4.120-92.70/Makefile
KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common \
-Werror-implicit-function-declaration \
-Wno-format-security \
-std=gnu89 $(call cc-option,-fno-PIE)
ifdef CONFIG_FUNCTION_TRACER
ifndef CC_FLAGS_FTRACE
CC_FLAGS_FTRACE := -pg
endif
export CC_FLAGS_FTRACE
ifdef CONFIG_HAVE_FENTRY
CC_USING_FENTRY := $(call cc-option, -mfentry -DCC_USING_FENTRY)
endif
KBUILD_CFLAGS += $(CC_FLAGS_FTRACE) $(CC_USING_FENTRY)
KBUILD_AFLAGS += $(CC_USING_FENTRY)
ifdef CONFIG_DYNAMIC_FTRACE
ifdef CONFIG_HAVE_C_RECORDMCOUNT
BUILD_C_RECORDMCOUNT := y
export BUILD_C_RECORDMCOUNT
endif
endif
endif
# zgrep CONFIG_FUNCTION_TRACER /proc/config.gz
CONFIG_FUNCTION_TRACER=y
# zgrep CONFIG_HAVE_FENTRY /proc/config.gz
CONFIG_HAVE_FENTRY=y
# zgrep CONFIG_DYNAMIC_FTRACE /proc/config.gz
CONFIG_DYNAMIC_FTRACE=y
到了这里,关于Linux 编译内核模块出现--Unknown symbol mcount的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!