[交叉]编译Linux内核时缺少OpenSSL库

Posted by 橙叶 on Mon, May 13, 2024

编译内核时提示<openssl/bio.h>缺失,原因是编译的机器上没有安装libssl库。

网上查了一下基本都需要用apt之类的安装libssl,但是我是在公用的机器上编译的,并不太方便直接安装。

于是下载编译了openssl源码,然后尝试在编译内核时把头文件和编译好的库添加进去,但是依然会报错。

实际上,用到openssl的是scripts下的extract-cert.c, 这个文件是用本地的GCC编译的,并不是内核的一部分, 所以make时直接传递的CFLAGS等参数是不会作用到这个文件的编译的。

研究了一下暂时没找到怎么在编译内核时给这个文件指定CFLAGS。 所以直接修改了scripts下的Makefile。

 1# SPDX-License-Identifier: GPL-2.0
 2###
 3# scripts contains sources for various helper programs used throughout
 4# the kernel for the build process.
 5
 6# 修改的部分
 7OPENSSL_INSTALL=<.....>/openssl-build/      # 编译好的openssl
 8OPENSSL_LDFLAG=-L$(OPENSSL_INSTALL)lib      # openssl的库文件
 9OPENSSL_CFLAG=-I$(OPENSSL_INSTALL)include   # openssl的头文件
10
11CRYPTO_LIBS = $(shell pkg-config --libs libcrypto 2> /dev/null || echo $(OPENSSL_LDFLAG) -lcrypto)      # 把编译好的openssl库加进来
12CRYPTO_CFLAGS = $(OPENSSL_CFLAG) $(shell pkg-config --cflags libcrypto 2> /dev/null)    # 添加openssl的头文件
13
14
15hostprogs-always-$(CONFIG_BUILD_BIN2C)			+= bin2c
16hostprogs-always-$(CONFIG_KALLSYMS)			+= kallsyms
17hostprogs-always-$(BUILD_C_RECORDMCOUNT)		+= recordmcount
18hostprogs-always-$(CONFIG_BUILDTIME_TABLE_SORT)		+= sorttable
19hostprogs-always-$(CONFIG_ASN1)				+= asn1_compiler
20hostprogs-always-$(CONFIG_MODULE_SIG_FORMAT)		+= sign-file
21hostprogs-always-$(CONFIG_SYSTEM_TRUSTED_KEYRING)	+= extract-cert
22hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE)	+= insert-sys-cert
23hostprogs-always-$(CONFIG_SYSTEM_REVOCATION_LIST)	+= extract-cert
24
25HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
26HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
27HOSTCFLAGS_sign-file.o = $(CRYPTO_CFLAGS)
28HOSTLDLIBS_sign-file = $(CRYPTO_LIBS)
29HOSTCFLAGS_extract-cert.o = $(CRYPTO_CFLAGS)
30HOSTLDLIBS_extract-cert = $(CRYPTO_LIBS)
31
32ifdef CONFIG_UNWINDER_ORC
33ifeq ($(ARCH),x86_64)
34ARCH := x86
35endif
36HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/x86/include
37HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED
38HOSTLDLIBS_sorttable = -lpthread
39endif
40
41# The following programs are only built on demand
42hostprogs += unifdef
43
44# The module linker script is preprocessed on demand
45targets += module.lds
46
47subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
48subdir-$(CONFIG_MODVERSIONS) += genksyms
49subdir-$(CONFIG_SECURITY_SELINUX) += selinux
50
51# Let clean descend into subdirs
52subdir-	+= basic dtc gdb kconfig mod

之后正常执行内核编译步骤即可。

附openssl编译步骤:

1# 下载openssl源码
2
3./config --prefix=<.....>/openssl-build/       # 指定安装位置
4make CC=x86_64-conda-linux-gnu-gcc  -j         # 编译,公用的机器gcc版本太低,所以使用的是conda安装的gcc
5make install    # 编译安装

补充

以上编译的是5.9的内核。其他版本的Makefile会有区别,不过方法是一样的。

如果是新的内核,还需要涉及到其他地方。原来的scripts/Makefile里仍然需要修改,只是要编译的文件变成了sign-file

1HOSTCFLAGS_sign-file.o = $(OPENSSL_CFLAG) # $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null)
2HOSTLDLIBS_sign-file = $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || echo $(OPENSSL_LDFLAG) -lcrypto)

而extract-cert.c在/certs里,这个目录里的Makefile也需要修改。

1HOSTCFLAGS_extract-cert.o :=  $(OPENSSL_CFLAG) # $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null)
2HOSTLDLIBS_extract-cert :=  -L$(OPENSSL_INSTALL)lib -lcrypto # $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || echo $(OPENSSL_LDFLAG) -lcrypto)

但是make时还会报错,

1certs/extract-cert: error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file: No such file or directory

因为是用非系统库目录下的.so库文件编译的,所以编译好的extract-cert运行时还是会找不到动态链接库libcrypto.so。找到certs/Makefile里的cmd_extract_certs, 用环境变量LD_LIBRARY_PATH来给它添加运行时的用到的动态链接库。

1EXPORT_LD_LIBRARY_PATH=env "LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(OPENSSL_INSTALL)lib"
2
3quiet_cmd_extract_certs  = CERT    $@
4      cmd_extract_certs  =$(EXPORT_LD_LIBRARY_PATH) $(obj)/extract-cert "$(extract-cert-in)" $@
5extract-cert-in = $(filter-out $(obj)/extract-cert, $(real-prereqs))

这样应该能正常编译整个内核了。

总结

主要是问题来自内核编译之前需要先编译scripts/里的一些工具,它们和内核本身是没有关系的。本来编译它们时额外指定头文件和库很简单,只是在Linux本来就很复杂的Makefile工程里解决起来比较麻烦。



comments powered by Disqus