外部内核模块编译modpost阶段如何识别已安装模块的导出符号?
问题:跨模块编译的符号依赖与许可冲突问题
我有三个存在依赖关系的外部内核模块:C依赖B的符号,B依赖A的符号。编译安装顺序如下:
make -C <Kernel dir> make -C <kernel dir> KERNELRELEASE=$(KERNEL_VER) modules make -C <kernel dir> KERNELRELEASE=$(KERNEL_VER) INSTALL_MOD_PATH=$(INSTALL_PATH) modules_install make -C <kernel_dir> M=<module_A_dir> modules; make -C <kernel_dir> M=<module_A_dir> INSTALL_MOD_PATH=$(INSTALL_PATH) modules_install; make -C <kernel_dir> M=<module_B_dir> modules; make -C <kernel_dir> M=<module_B_dir> INSTALL_MOD_PATH=$(INSTALL_PATH) modules_install; make -C <kernel_dir> M=<module_C_dir> modules; make -C <kernel_dir> M=<module_C_dir> INSTALL_MOD_PATH=$(INSTALL_PATH) modules_install;
编译模块B时,modpost阶段报错无法识别模块A的导出符号:
make[2]: Entering directory '/home/user/workingdir/kernel/linux-5.4.x' Building modules, stage 2. MODPOST 1 modules ERROR: "backport_dependency_symbol" [/home/user/workingdir/extModB/moduleB.ko] undefined! ERROR: "cfg80211_moduleA_cmd" [/home/user/workingdir/extModB/moduleB.ko] undefined!
已知可以通过引入A的Module.symvers解决符号识别问题,但存在许可冲突:模块A为GPL许可,B为BSD/GPL双许可,C为专有许可。若配置KBUILD_EXTRA_SYMBOLS引入A的Module.symvers,编译时会触发许可冲突。
核心疑问:是否可通过安装模块A到INSTALL_MOD_PATH,让编译模块B时modpost自动识别A的符号?
解答
仅安装模块A无法让modpost自动识别其符号:modpost在编译阶段仅从以下渠道获取符号信息,不会读取已安装到
INSTALL_MOD_PATH的.ko文件:- 当前内核源码树的
Module.symvers KBUILD_EXTRA_SYMBOLS指定的外部Module.symvers- 同一次编译流程中其他模块生成的临时符号数据
- 当前内核源码树的
针对许可冲突的可行解决思路:
- 利用B的双许可特性:编译模块B时,在代码中声明
MODULE_LICENSE("GPL")。由于B本身允许GPL许可,此时引用A的GPL导出符号不会触发许可检查。后续C作为专有模块,只要仅调用B导出的BSD许可符号(不直接引用A的GPL符号),就不会存在许可问题。 - 调整模块A的符号导出方式:修改A的代码,将需要被B引用的符号用
EXPORT_SYMBOL而非EXPORT_SYMBOL_GPL导出。这类非GPL符号可以被BSD许可的模块合法引用,无需修改B的许可声明,也不会触发冲突。
- 利用B的双许可特性:编译模块B时,在代码中声明
内容的提问来源于stack exchange,提问作者Tommy Lin
相关产品推荐
相关产品推荐

