insmod内核模块提示Unknown Symbol问题处理

问题描述

在调试内核crash问题时打开了lockup相关的kernel CONFIG,重新编译FW后发现有个内核模块insmod失败

[Wed Nov 06 15:51:57.384 2019] ip6t_CONE: Unknown symbol rcu_bh_lock_map (err 0)
[Wed Nov 06 15:51:57.384 2019] ip6t_CONE: Unknown symbol lock_acquire (err 0)
[Wed Nov 06 15:51:57.384 2019] ip6t_CONE: Unknown symbol lock_release (err 0)

手动使用insmod重新加载也是提示相同的错误。

问题分析

原本这个问题是不存在的,出现的原因必然和启用的CONFIG相关,对比前后两个FW的ip6t_CONE.ko

# old .ko
$ strings ip6t_CONE.ko |grep rcu

# new .ko
$ strings ip6t_CONE.ko |grep rcu
rcu_bh_lock_map

发现新的.ko确实包含了提示出错的那些个symbol,为了找出这些参数是启用哪个CONFIG引入的,可以去查找kernel的sourcecode

export symbol rcu_bh_lock_map

Got you, 就是这个CONFIG_DEBUG_LOCK_ALLOC,这个CONFIG正是之前打开lockup相关CONFIG之一。当然其它两个报错的Symbol也是类似的情况。

对应的CONFIG找到了,但是本来就需要通过这个CONFIG去记录相关log,当然不然又把它禁掉,加载失败的问题也正是打开这个CONFIG才发现的,说明是个潜在问题。那么如何解决呢,首先我们以为是这些Symbol在内核中已经导出了,但是ipv6_CONE.ko没有引用的缘故,所以尝试在源文件ipv6_CONE.c中使用extern调用。

extern struct lockdep_map rcu_bh_lock_map;
extern void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
              int trylock, int read, int check,
              struct lockdep_map *nest_lock, unsigned long ip);
extern void lock_release(struct lockdep_map *lock, int nested,
              unsigned long ip);

事实证明这个方法不可行,说明不是这个思路,所以重新开始了Google之路,终于!万能的StackOverflow让我看到了希望

问题unknown symbol __class_create (err 0)

The function __class_create is exported only for GPL modules (exported with EXPORT_SYMBOL_GPL). So, you need to use a GPL license with MODULE_LICENSE macro to make use of that function. Same goes for other functions as well.

This should do the trick:
MODULE_LICENSE("GPL");

发现这个问题和我遇到的情况基本一致,然后我重新检查了这几个Symbol的export方式,确实都是EXPORT_SYMBOL_GPL,接着我再去看ip6t_CONE的sourcecode,发现确实没有声明LICENSE!!!

好了,解决方案来啦,立马加个kernel patch ↓

--- kmod-ipv6-cone.orig/ip6t_cone.c 2019-11-07 09:46:42.068839345 +0800
--- kmod-ipv6-cone/ip6t_cone.c 2019-11-07 09:47:45.956071600 +0800
@@ -466,3 +466,8 @@
 module_init(init);
 module_exit(fini);
 #endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("");
+MODULE_DESCRIPTION("IPv6");
+

加上重新编译,一切ok,那些恼人的log终于不见啦,ip6t_CONE.ko也正常加载完成,完美!

参考文档