diff --git a/modutils/modutils.c b/modutils/modutils.c index f7ad5e8058fe..037d609e42df 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c @@ -7,6 +7,7 @@ */ #include "modutils.h" +#include #include #define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts) @@ -186,6 +187,33 @@ void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p) } #endif +#ifdef __NR_finit_module +/* + * Return: + * 0 on success, + * <0 for error. + * + * finit_module()/init_module() only accepts ELF format. + * Do basic ELF check to avoid calling finit_module() with compressed module. + */ +static int check_elf_header(int fd) +{ + unsigned char buf[EI_NIDENT]; + int ret; + + ret = pread(fd, buf, sizeof(buf), 0); + if (ret < sizeof(buf)) + return -EIO; + if (buf[EI_MAG0] != ELFMAG0 || + buf[EI_MAG1] != ELFMAG1 || + buf[EI_MAG2] != ELFMAG2 || + buf[EI_MAG3] != ELFMAG3) + return -EINVAL; + /* Other more comprehensive check will be done inside kernel */ + return 0; +} +#endif + /* Return: * 0 on success, * -errno on open/read error, @@ -212,12 +240,19 @@ int FAST_FUNC bb_init_module(const char *filename, const char *options) * to only allow loading of modules off of secure storage (like a read- * only rootfs) which needs the finit_module call. If it fails, we fall * back to normal module loading to support compressed modules. + * + * Note that finit_module()/init_module() only accept ELF image, do + * basic check before calling finit_module() to avoid kernel + * complaining. */ # ifdef __NR_finit_module { int fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd >= 0) { - rc = finit_module(fd, options, 0) != 0; + if (!check_elf_header(fd)) + rc = finit_module(fd, options, 0) != 0; + else + rc = 1; close(fd); if (rc == 0) return rc; diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index db44a2ed0ab5..d2cd6a64c1d0 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -24,6 +24,7 @@ //kbuild:lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o #include "libbb.h" +#include /* for ELF header magic */ /* After libbb.h, since it needs sys/types.h on some systems */ #include /* uname() */ #include @@ -249,6 +250,33 @@ static const char *moderror(int err) } } +#ifdef __NR_finit_module +/* + * Return: + * 0 on success, + * <0 for error. + * + * finit_module()/init_module() only accepts ELF format. + * Do basic ELF check to avoid calling finit_module() with compressed module. + */ +static int check_elf_header(int fd) +{ + unsigned char buf[EI_NIDENT]; + int ret; + + ret = pread(fd, buf, sizeof(buf), 0); + if (ret < sizeof(buf)) + return -EIO; + if (buf[EI_MAG0] != ELFMAG0 || + buf[EI_MAG1] != ELFMAG1 || + buf[EI_MAG2] != ELFMAG2 || + buf[EI_MAG3] != ELFMAG3) + return -EINVAL; + /* Other more comprehensive check will be done inside kernel */ + return 0; +} +#endif + static int load_module(const char *fname, const char *options) { #if 1 @@ -272,7 +300,10 @@ static int load_module(const char *fname, const char *options) { int fd = open(fname, O_RDONLY | O_CLOEXEC); if (fd >= 0) { - r = finit_module(fd, options, 0) != 0; + if (!check_elf_header(fd)) + r = finit_module(fd, options, 0) != 0; + else + r = 1; close(fd); } } -- 2.29.2