1 Patch-Source: http://lists.busybox.net/pipermail/busybox/2021-January/088398.html
2 Patch-Source: http://lists.busybox.net/pipermail/busybox/2021-January/088399.html
3 See-Also: https://gitlab.alpinelinux.org/alpine/aports/-/issues/13427
5 The purpose of this patch is to remove confusing error messages
6 "Module has invalid ELF structures" produced by kernel when loading gzip
7 compressed kernel modules using busybox modprobe.
9 From: Qu Wenruo <wqu@suse.com>
10 Date: Sun, 03 Jan 2021 04:10:52 +0000
11 Subject: [PATCH v2] modutils: check ELF header before calling finit_module()
13 finit_module() and init_module() system calls have clear specification
14 to only accept valid ELF image.
16 Although we try finit_module() on compressed modules to let the kernel
17 determine if it's an ELF image, but it's not ideal, especially when
18 newer kernel will complain when some invalid files/memory is passed in.
20 Treat the kernel better by just doing a very basic ELF header check
21 before calling finit_module().
23 Signed-off-by: Qu Wenruo <wqu at suse.com>
25 diff --git a/modutils/modutils.c b/modutils/modutils.c
26 index f7ad5e8058fe..037d609e42df 100644
27 --- a/modutils/modutils.c
28 +++ b/modutils/modutils.c
34 #include <sys/syscall.h>
36 #define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
37 @@ -186,6 +187,33 @@ void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p)
41 +#ifdef __NR_finit_module
47 + * finit_module()/init_module() only accepts ELF format.
48 + * Do basic ELF check to avoid calling finit_module() with compressed module.
50 +static int check_elf_header(int fd)
52 + unsigned char buf[EI_NIDENT];
55 + ret = pread(fd, buf, sizeof(buf), 0);
56 + if (ret < sizeof(buf))
58 + if (buf[EI_MAG0] != ELFMAG0 ||
59 + buf[EI_MAG1] != ELFMAG1 ||
60 + buf[EI_MAG2] != ELFMAG2 ||
61 + buf[EI_MAG3] != ELFMAG3)
63 + /* Other more comprehensive check will be done inside kernel */
70 * -errno on open/read error,
71 @@ -212,12 +240,19 @@ int FAST_FUNC bb_init_module(const char *filename, const char *options)
72 * to only allow loading of modules off of secure storage (like a read-
73 * only rootfs) which needs the finit_module call. If it fails, we fall
74 * back to normal module loading to support compressed modules.
76 + * Note that finit_module()/init_module() only accept ELF image, do
77 + * basic check before calling finit_module() to avoid kernel
80 # ifdef __NR_finit_module
82 int fd = open(filename, O_RDONLY | O_CLOEXEC);
84 - rc = finit_module(fd, options, 0) != 0;
85 + if (!check_elf_header(fd))
86 + rc = finit_module(fd, options, 0) != 0;
93 diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
94 index db44a2ed0ab5..d2cd6a64c1d0 100644
95 --- a/modutils/modprobe-small.c
96 +++ b/modutils/modprobe-small.c
98 //kbuild:lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o
101 +#include <elf.h> /* for ELF header magic */
102 /* After libbb.h, since it needs sys/types.h on some systems */
103 #include <sys/utsname.h> /* uname() */
105 @@ -249,6 +250,33 @@ static const char *moderror(int err)
109 +#ifdef __NR_finit_module
115 + * finit_module()/init_module() only accepts ELF format.
116 + * Do basic ELF check to avoid calling finit_module() with compressed module.
118 +static int check_elf_header(int fd)
120 + unsigned char buf[EI_NIDENT];
123 + ret = pread(fd, buf, sizeof(buf), 0);
124 + if (ret < sizeof(buf))
126 + if (buf[EI_MAG0] != ELFMAG0 ||
127 + buf[EI_MAG1] != ELFMAG1 ||
128 + buf[EI_MAG2] != ELFMAG2 ||
129 + buf[EI_MAG3] != ELFMAG3)
131 + /* Other more comprehensive check will be done inside kernel */
136 static int load_module(const char *fname, const char *options)
139 @@ -272,7 +300,10 @@ static int load_module(const char *fname, const char *options)
141 int fd = open(fname, O_RDONLY | O_CLOEXEC);
143 - r = finit_module(fd, options, 0) != 0;
144 + if (!check_elf_header(fd))
145 + r = finit_module(fd, options, 0) != 0;