]> git.pld-linux.org Git - packages/busybox.git/blob - 0001-modutils-check-ELF-header-before-calling-finit_module.patch
Drop CONFIG_EXTRA_LDLIBS from here as only first matters (so echo CONFIG_EXTRA_LDLIBS...
[packages/busybox.git] / 0001-modutils-check-ELF-header-before-calling-finit_module.patch
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
4
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.
8 --
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()
12
13 finit_module() and init_module() system calls have clear specification
14 to only accept valid ELF image.
15
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.
19
20 Treat the kernel better by just doing a very basic ELF header check
21 before calling finit_module().
22
23 Signed-off-by: Qu Wenruo <wqu at suse.com>
24
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
29 @@ -7,6 +7,7 @@
30   */
31  #include "modutils.h"
32  
33 +#include <elf.h>
34  #include <sys/syscall.h>
35  
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)
38  }
39  #endif
40  
41 +#ifdef __NR_finit_module
42 +/*
43 + * Return:
44 + * 0 on success,
45 + * <0 for error.
46 + *
47 + * finit_module()/init_module() only accepts ELF format.
48 + * Do basic ELF check to avoid calling finit_module() with compressed module.
49 + */
50 +static int check_elf_header(int fd)
51 +{
52 +       unsigned char buf[EI_NIDENT];
53 +       int ret;
54 +
55 +       ret = pread(fd, buf, sizeof(buf), 0);
56 +       if (ret < sizeof(buf))
57 +               return -EIO;
58 +       if (buf[EI_MAG0] != ELFMAG0 ||
59 +           buf[EI_MAG1] != ELFMAG1 ||
60 +           buf[EI_MAG2] != ELFMAG2 ||
61 +           buf[EI_MAG3] != ELFMAG3)
62 +               return -EINVAL;
63 +       /* Other more comprehensive check will be done inside kernel */
64 +       return 0;
65 +}
66 +#endif
67 +
68  /* Return:
69   * 0 on success,
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.
75 +        *
76 +        * Note that finit_module()/init_module() only accept ELF image, do
77 +        * basic check before calling finit_module() to avoid kernel
78 +        * complaining.
79          */
80  # ifdef __NR_finit_module
81         {
82                 int fd = open(filename, O_RDONLY | O_CLOEXEC);
83                 if (fd >= 0) {
84 -                       rc = finit_module(fd, options, 0) != 0;
85 +                       if (!check_elf_header(fd))
86 +                               rc = finit_module(fd, options, 0) != 0;
87 +                       else
88 +                               rc = 1;
89                         close(fd);
90                         if (rc == 0)
91                                 return rc;
92
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
97 @@ -24,6 +24,7 @@
98  //kbuild:lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o
99  
100  #include "libbb.h"
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() */
104  #include <fnmatch.h>
105 @@ -249,6 +250,33 @@ static const char *moderror(int err)
106         }
107  }
108  
109 +#ifdef __NR_finit_module
110 +/*
111 + * Return:
112 + * 0 on success,
113 + * <0 for error.
114 + *
115 + * finit_module()/init_module() only accepts ELF format.
116 + * Do basic ELF check to avoid calling finit_module() with compressed module.
117 + */
118 +static int check_elf_header(int fd)
119 +{
120 +       unsigned char buf[EI_NIDENT];
121 +       int ret;
122 +
123 +       ret = pread(fd, buf, sizeof(buf), 0);
124 +       if (ret < sizeof(buf))
125 +               return -EIO;
126 +       if (buf[EI_MAG0] != ELFMAG0 ||
127 +           buf[EI_MAG1] != ELFMAG1 ||
128 +           buf[EI_MAG2] != ELFMAG2 ||
129 +           buf[EI_MAG3] != ELFMAG3)
130 +               return -EINVAL;
131 +       /* Other more comprehensive check will be done inside kernel */
132 +       return 0;
133 +}
134 +#endif
135 +
136  static int load_module(const char *fname, const char *options)
137  {
138  #if 1
139 @@ -272,7 +300,10 @@ static int load_module(const char *fname, const char *options)
140         {
141                 int fd = open(fname, O_RDONLY | O_CLOEXEC);
142                 if (fd >= 0) {
143 -                       r = finit_module(fd, options, 0) != 0;
144 +                       if (!check_elf_header(fd))
145 +                               r = finit_module(fd, options, 0) != 0;
146 +                       else
147 +                               r = 1;
148                         close(fd);
149                 }
150         }
151 -- 
152 2.29.2
This page took 0.088861 seconds and 3 git commands to generate.