finit_module() and init_module() system calls have clear specification
to only accept valid ELF image.

Although we try finit_module() on compressed modules to let the kernel
determine if it's an ELF image, but it's not ideal, especially when
newer kernel will complain when some invalid files/memory is passed in.

Treat the kernel better by just doing a very basic ELF header check
before calling finit_module().

Signed-off-by: Qu Wenruo <[email protected]>
---
 modutils/modprobe-small.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

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 <elf.h> /* for ELF header magic */
 /* After libbb.h, since it needs sys/types.h on some systems */
 #include <sys/utsname.h> /* uname() */
 #include <fnmatch.h>
@@ -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

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to