15AH, San Francisco

California, United States.

Send Your Mail At:

tianyingkejishe@sina.cn

Working Hours

Mon-Sat: 9.30am To 7.00pm

[Arm]version magic ‘5.6.0-rc5+ SMP mod_unload ‘ should be…问题研究

1, 首先,为什么会出现修改了kernel重新编译后magic num改变
内核版本是如何生成的:

Linux 内核在进行模块装载时先完成模块的 CRC 值校验,再核对 vermagic 中的字符信息,linux版本在 include/generated/utsrelease.h中定义,文件中的内容如下:

#define UTS_RELEASE "4.9.123"

utsrelease.h是kernel编译后自动生成的,用户更改里面的内容不会有效果。
这个值可以通过修改最顶层的Makefile文件来修改。

VERSION = 4
PATCHLEVEL = 9                
SUBLEVEL = 123                
EXTRAVERSION =
...

init/version.c中,定义了kernel启动时的第一条打印信息:

/* FIXED STRINGS! Don't touch! */
const char linux_banner[] =
  "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
  LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";

const char linux_proc_banner[] =
  "%s version %s"
  " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
  " (" LINUX_COMPILER ") %s\n";

这里UTS_RELEASE在kernel编译时自动生成

init/main.casmlinkage __visible void __init start_kernel(void)函数中,有kernel启动的第一条打印信息,这条信息是dmesg命令打印出来:

pr_notice("%s", linux_banner);

驱动模块的version magic信息是怎么生成的:

4.x 内核下,在include/linux/vermagic.h中定义有VERMAGIC_STRING,如下:

#include <generated/utsrelease.h>
              
/* Simply sanity version stamp for modules. */
#ifdef CONFIG_SMP
#define MODULE_VERMAGIC_SMP "SMP "
#else
#define MODULE_VERMAGIC_SMP ""
#endif
#ifdef CONFIG_PREEMPT
#define MODULE_VERMAGIC_PREEMPT "preempt "
#else
#define MODULE_VERMAGIC_PREEMPT ""
#endif
#ifdef CONFIG_MODULE_UNLOAD
#define MODULE_VERMAGIC_MODULE_UNLOAD "mod_unload "
#else
#define MODULE_VERMAGIC_MODULE_UNLOAD ""
#endif 
#ifdef CONFIG_MODVERSIONS
#define MODULE_VERMAGIC_MODVERSIONS "modversions "
#else
#define MODULE_VERMAGIC_MODVERSIONS ""
#endif
#ifndef MODULE_ARCH_VERMAGIC
#define MODULE_ARCH_VERMAGIC ""
#endif  

#define VERMAGIC_STRING             \
  UTS_RELEASE " "             \
  MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT       \
  MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS \
  MODULE_ARCH_VERMAGIC

VERMAGIC_STRING不仅包含内核版本号,还包含有内核使用的SMP与preempt, MODULE_UNLOAD, 架构等配置信息。模块在编译时,我们可以看到屏幕上会显示”MODPOST”。

  <~/Documents/Demo/driver/debugfs> make
make -C ~/kernel/ SUBDIRS=~/Documents/Demo/driver/debugfs modules
make[1]: Entering directory '~/kernel'
  CC [M]  ~/Documents/Demo/driver/debugfs/my_debugfs.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      ~/Documents/Demo/driver/debugfs/my_debugfs.mod.o
  LD [M]  ~/Documents/Demo/driver/debugfs/my_debugfs.ko
make[1]: Leaving directory '~/kernel'

在此阶段, VERMAGIC_STRING会添加到模块的modinfo段。在内核源码目录下scripts\mod\modpost.c文件中可以看到模块后续处理部分的代码。模块编译生成后,通过modinfo my_debugfs.ko命令可以查看此模块的vermagic等信息。

  <~/Documents/Demo/driver/debugfs> modinfo my_debugfs.ko 
filename:      ~/Documents/Demo/driver/debugfs/my_debugfs.ko
license:        GPL
depends:        
vermagic:       4.9.123 SMP preempt mod_unload aarch64

4.x 内核下的模块装载器里保存有内核的版本信息,在装载模块时,装载器会比较所保存的内核vermagic与此模块的modinfo段里保存的vermagic信息是否一致,两者一致时,模块才能被装载。

为了使两个版本一致:可以把 依赖源码中的include/linux/vermagic.h中的UTS_RELEASE修改成与目标机器的版本一致,这样,再次编译模块就可以了。

内核模块版本和内核版本不一致的处理方法

2, 发现版本号会追加git的版本号,还有个“+”
向linux内核版本号添加字符/为何有时会自动添加“+”号,根据这篇文章,一步一步试一下

第一步:去掉git的附加信息
先在menuconfig中找到

  │ Symbol: LOCALVERSION [=]                                                                                                                                                                                   │  
  │ Type  : string                                                                                                                                                                                             │  
  │ Prompt: Local version - append to kernel release                                                                                                                                                           │  
  │   Location:                                                                                                                                                                                                │  
  │ (1) -> General setup                                                                                                                                                                                       │  
  │   Defined at init/Kconfig:81                                                                                                                                                                               │  
  │                                                                                                                                                                                                            │  
  │                                                                                                                                                                                                            │  
  │ Symbol: LOCALVERSION_AUTO [=n]                                                                                                                                                                             │  
  │ Type  : boolean                                                                                                                                                                                            │  
  │ Prompt: Automatically append version information to the version string                                                                                                                                     │  
  │   Location:                                                                                                                                                                                                │  
  │ (2) -> General setup                                                                                                                                                                                       │  
  │   Defined at init/Kconfig:91                                                                                                                                                                               │  
  │   Depends on: !COMPILE_TEST [=n]                                                                                                                                                                           │  
  │                                                           

关掉LOCALVERSION_AUTO并留空LOCALVERSION,发现git版本确实是不见了,但是‘+’还是存在。

第二步:去掉“+”号

scripts/setlocalversion文件中,找到以下语句:

# CONFIG_LOCALVERSION and LOCALVERSION (if set)
res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}"

# scm version string if not at a tagged commit
if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then
  # full scm version string
  res="$res$(scm_version)"
else
  # append a plus sign if the repository is not in a clean
  # annotated or signed tagged state (as git describe only
  # looks at signed or annotated tags - git tag -a/-s) and
  # LOCALVERSION= is not specified
  if test "${LOCALVERSION+set}" != "set"; then
    scm=$(scm_version --short)
   # res="$res${scm:++}"	//××××××××××××××注释掉这句话××××××××××××
  fi
fi

下面是注释前后的对比

注释前
在这里插入图片描述

问题解决。

Note:在网上还看到两种方法,写在下面:第一种:menuconfig 的时候不要勾选,直接搜MODVERSIONS

注意不要选图中那行

第二种:modprobe –force-vermagic helloworld.ko

这个大家可以自行尝试一下

anyShare分享到:
本站的文章和资源来自互联网或者站长的原创,按照 CC BY -NC -SA 3.0 CN协议发布和共享,转载或引用本站文章应遵循相同协议。如果有侵犯版权的资源请尽快联系站长,我们会在24h内删除有争议的资源。欢迎大家多多交流,期待共同学习进步。
stormwind

发表评论