aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@chromium.org>2016-09-15 12:16:33 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-09-15 12:16:33 +0200
commit3a45b87ac36f60962d6d19c592813e186a9e82e6 (patch)
tree2b3d2249ff2e558bc92a71f91339474a50a0b596
parent7fa799a97d381902ab27556918722a6e2d138b9e (diff)
downloadbusybox-w32-3a45b87ac36f60962d6d19c592813e186a9e82e6.tar.gz
busybox-w32-3a45b87ac36f60962d6d19c592813e186a9e82e6.tar.bz2
busybox-w32-3a45b87ac36f60962d6d19c592813e186a9e82e6.zip
modutils: support finit_module syscall
On some systems like Chromium OS, loading modules from non-verified filesystems is denied. Only finit_module is allowed because an open fd is passed which can be checked against a verified location. Change the module loading code to first attempt finit_module and if that fails for whatever reason, fall back to the existing logic. On x86_64, this adds ~80 bytes to modutils/modutils.o and ~68 bytes to modutils/modprobe-small.o. Signed-off-by: Mike Frysinger <vapier@chromium.org> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--modutils/modprobe-small.c33
-rw-r--r--modutils/modutils.c21
2 files changed, 51 insertions, 3 deletions
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index 5936e48cf..a47e52234 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -18,9 +18,13 @@
18/* After libbb.h, since it needs sys/types.h on some systems */ 18/* After libbb.h, since it needs sys/types.h on some systems */
19#include <sys/utsname.h> /* uname() */ 19#include <sys/utsname.h> /* uname() */
20#include <fnmatch.h> 20#include <fnmatch.h>
21#include <sys/syscall.h>
21 22
22extern int init_module(void *module, unsigned long len, const char *options); 23extern int init_module(void *module, unsigned long len, const char *options);
23extern int delete_module(const char *module, unsigned flags); 24extern int delete_module(const char *module, unsigned flags);
25#ifdef __NR_finit_module
26# define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags)
27#endif
24/* linux/include/linux/module.h has limit of 64 chars on module names */ 28/* linux/include/linux/module.h has limit of 64 chars on module names */
25#undef MODULE_NAME_LEN 29#undef MODULE_NAME_LEN
26#define MODULE_NAME_LEN 64 30#define MODULE_NAME_LEN 64
@@ -209,11 +213,34 @@ static int load_module(const char *fname, const char *options)
209 int r; 213 int r;
210 size_t len = MAXINT(ssize_t); 214 size_t len = MAXINT(ssize_t);
211 char *module_image; 215 char *module_image;
216
217 if (!options)
218 options = "";
219
212 dbg1_error_msg("load_module('%s','%s')", fname, options); 220 dbg1_error_msg("load_module('%s','%s')", fname, options);
213 221
214 module_image = xmalloc_open_zipped_read_close(fname, &len); 222 /*
215 r = (!module_image || init_module(module_image, len, options ? options : "") != 0); 223 * First we try finit_module if available. Some kernels are configured
216 free(module_image); 224 * to only allow loading of modules off of secure storage (like a read-
225 * only rootfs) which needs the finit_module call. If it fails, we fall
226 * back to normal module loading to support compressed modules.
227 */
228 r = 1;
229# ifdef __NR_finit_module
230 {
231 int fd = open(fname, O_RDONLY | O_CLOEXEC);
232 if (fd >= 0) {
233 r = finit_module(fd, options, 0) != 0;
234 close(fd);
235 }
236 }
237# endif
238 if (r != 0) {
239 module_image = xmalloc_open_zipped_read_close(fname, &len);
240 r = (!module_image || init_module(module_image, len, options) != 0);
241 free(module_image);
242 }
243
217 dbg1_error_msg("load_module:%d", r); 244 dbg1_error_msg("load_module:%d", r);
218 return r; /* 0 = success */ 245 return r; /* 0 = success */
219#else 246#else
diff --git a/modutils/modutils.c b/modutils/modutils.c
index 0a056731d..d36caaf68 100644
--- a/modutils/modutils.c
+++ b/modutils/modutils.c
@@ -13,6 +13,9 @@ extern int delete_module(const char *module, unsigned int flags);
13#else 13#else
14# include <sys/syscall.h> 14# include <sys/syscall.h>
15# define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts) 15# define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
16# if defined(__NR_finit_module)
17# define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags)
18# endif
16# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) 19# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
17#endif 20#endif
18 21
@@ -212,6 +215,24 @@ int FAST_FUNC bb_init_module(const char *filename, const char *options)
212 return bb_init_module_24(filename, options); 215 return bb_init_module_24(filename, options);
213#endif 216#endif
214 217
218 /*
219 * First we try finit_module if available. Some kernels are configured
220 * to only allow loading of modules off of secure storage (like a read-
221 * only rootfs) which needs the finit_module call. If it fails, we fall
222 * back to normal module loading to support compressed modules.
223 */
224# ifdef __NR_finit_module
225 {
226 int fd = open(filename, O_RDONLY | O_CLOEXEC);
227 if (fd >= 0) {
228 rc = finit_module(fd, options, 0) != 0;
229 close(fd);
230 if (rc == 0)
231 return rc;
232 }
233 }
234# endif
235
215 image_size = INT_MAX - 4095; 236 image_size = INT_MAX - 4095;
216 mmaped = 0; 237 mmaped = 0;
217 image = try_to_mmap_module(filename, &image_size); 238 image = try_to_mmap_module(filename, &image_size);