4.18的kernel上无法卸载内核驱动模块

问题描述:
module在4.18的kernel上面无法在rmmod的时候会如下报错

[root@node-1 zjp]# insmod hello7.ko
[root@node-1 zjp]# rmmod hello7.ko
rmmod: ERROR: could not remove 'hello7': Device or resource busy
rmmod: ERROR: could not remove module hello7.ko: Device or resource busy

在rmmod卸载module的时候会调用delete_module,在return

EBUSY
The module is not "live" (i.e., it is still being initialized or is already marked for removal); or, the module has an init function but has no exit function, and O_TRUNC was not specified in flags.

调查过程

查看已经安装的module信息

[root@node-1 zjp]# cat /proc/modules | grep hello7
hello7 262144 0 [permanent], Live 0xffff4f26408b0000 (OE)

这个打印的代码

1005         if (mod->init != NULL && mod->exit == NULL) {
1006                 printed_something = 1;
1007                 seq_printf(m, "[permanent],");                                                                                                                          
1008         }
1009 

卸载的时候

 948         /* If it has an init func, it must have an exit func to unload */
 949         if (mod->init && !mod->exit) {
 950                 forced = try_force_unload(flags);                                                                                                                       
 951                 if (!forced) {
 952                         /* This module can't be removed */
 953                         ret = -EBUSY;
 954                         goto out;
 955                 }
 956         }

代码回去强制卸载如果调用 try_force_unload函数

 811 #ifdef CONFIG_MODULE_FORCE_UNLOAD
 812 static inline int try_force_unload(unsigned int flags)
 813 {
 814         int ret = (flags & O_TRUNC);
 815         if (ret)
 816                 add_taint(TAINT_FORCED_RMMOD, LOCKDEP_NOW_UNRELIABLE);
 817         return ret;
 818 }
 819 #else
 820 static inline int try_force_unload(unsigned int flags)
 821 {
 822         return 0;
 823 }
 824 #endif /* CONFIG_MODULE_FORCE_UNLOAD */

4.18的系统没有配置这个

[root@node-1 zjp]# grep -r "CONFIG_MODULE_FORCE_UNLOAD" /boot/config-4.18.0-80.11.2.el8.es.2.aarch64                                                                        
# CONFIG_MODULE_FORCE_UNLOAD is not set

根本原因是 mod->exitNULL LKM cleanup_module() not called

在测试的module的Makefile上添加 KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO

 LINUX_KERNEL_PATH := /lib/modules/$(shell uname -r)/build  #Linux内核源代码的绝对路径
 KBUILD_CFLAGS   += -DCC_HAVE_ASM_GOTO
all:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH)  modules   #编译模块了
clean:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean    #清理
⋊> ~/work-dir vim kernel-4.18.0/linux-4.18.0-80.1.2.el8_0/Makefile 
 500 # check for 'asm goto'
 501 ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y)                                                                                
 502   CC_HAVE_ASM_GOTO := 1
 503   KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
 504   KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO
 505 endif

4.14的Makefile文件

# check for 'asm goto'
ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y)
    KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
    KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO
endif

/scripts/gcc-goto.sh内容

  1 #!/bin/sh                                                                                                                                                                
  2 # SPDX-License-Identifier: GPL-2.0
  3 # Test for gcc 'asm goto' support
  4 # Copyright (C) 2010, Jason Baron <jbaron@redhat.com>
  5 
  6 cat << "END" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
  7 int main(void)
  8 {
  9 #if defined(__arm__) || defined(__aarch64__)
 10         /*
 11          * Not related to asm goto, but used by jump label
 12          * and broken on some ARM GCC versions (see GCC Bug 48637).
 13          */
 14         static struct { int dummy; int state; } tp;
 15         asm (".long %c0" :: "i" (&tp.state));
 16 #endif
 17 
 18 entry:
 19         asm goto ("" :::: entry);
 20         return 0;
 21 }
 22 END

抓取Makefile的执行过程
make V=1 SHELL='sh -x' > node-1-build.log 2>&1

  + /usr/bin/sh /usr/src/kernels/4.18.0-80.11.2.es.2.aarch64/scripts/gcc-goto.sh gcc -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                   -fno-strict-aliasing -fno-common -fshort-wchar \
                   -Werror-implicit-function-declaration \
                   -Wno-format-security \
                   -std=gnu89

输出内容报错

<stdin>: In function ‘main’:
<stdin>:9:2: error: invalid 'asm': invalid operand prefix '%c'

结果
得知4.18的编译环境是centos8的mock环境,4,18版本kernel两者的gcc版本差异很大,测试在centos8的mock环境编译的module是带有DCC_HAVE_ASM_GOTO,而4.14在build module的时候是没有带有 DCC_HAVE_ASM_GOTO;

参考链接:
[v1,5/7] arm64, jump label: detect %c support for ARM64
LKM cleanup_module() not called

编译参数打印

+ gcc -Wp,-MD,/root/zjp/zjp/.hello9.mod.o.d -nostdinc -isystem /usr/lib/gcc/aarch64-redhat-linux/4.8.5/include -I./arch/arm64/include -I./arch/arm64/include/generated -I./include -I./arch/arm64/include/uapi -I./arch/arm64/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -fno-PIE -fno-PIE -mgeneral-regs-only -DCONFIG_AS_LSE=1 -fno-asynchronous-unwind-tables -fno-delete-null-pointer-checks -O2 -Wno-maybe-uninitialized --param=allow-store-data-races=0 -Wframe-larger-than=2048 -fstack-protector-strong -Wno-unused-but-set-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracking-assignments -g -gdwarf-4 -pg -fno-inline-functions-called-once -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fno-stack-check -fconserve-stack -Werror=implicit-int -Werror=strict-prototypes '-DKBUILD_BASENAME="hello9.mod"' '-DKBUILD_MODNAME="hello9"' -DMODULE -c -o /root/zjp/zjp/hello9.mod.o /root/zjp/zjp/hello9.mod.c
+ scripts/basic/fixdep /root/zjp/zjp/.hello9.mod.o.d /root/zjp/zjp/hello9.mod.o 'gcc -Wp,-MD,/root/zjp/zjp/.hello9.mod.o.d  -nostdinc -isystem /usr/lib/gcc/aarch64-redhat-linux/4.8.5/include -I./arch/arm64/include -I./arch/arm64/include/generated  -I./include -I./arch/arm64/include/uapi -I./arch/arm64/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -fno-PIE -fno-PIE -mgeneral-regs-only -DCONFIG_AS_LSE=1 -fno-asynchronous-unwind-tables -fno-delete-null-pointer-checks -O2 -Wno-maybe-uninitialized --param=allow-store-data-races=0 -Wframe-larger-than=2048 -fstack-protector-strong -Wno-unused-but-set-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracking-assignments -g -gdwarf-4 -pg -fno-inline-functions-called-once -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fno-stack-check -fconserve-stack -Werror=implicit-int -Werror=strict-prototypes  -DKBUILD_BASENAME='\''"hello9.mod"'\'' -DKBUILD_MODNAME='\''"hello9"'\'' -DMODULE  -c -o /root/zjp/zjp/hello9.mod.o /root/zjp/zjp/hello9.mod.c' 
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇