diff options
author | Mike Frysinger <vapier@chromium.org> | 2016-09-15 12:16:33 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2016-09-15 12:16:33 +0200 |
commit | 3a45b87ac36f60962d6d19c592813e186a9e82e6 (patch) | |
tree | 2b3d2249ff2e558bc92a71f91339474a50a0b596 | |
parent | 7fa799a97d381902ab27556918722a6e2d138b9e (diff) | |
download | busybox-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.c | 33 | ||||
-rw-r--r-- | modutils/modutils.c | 21 |
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 | ||
22 | extern int init_module(void *module, unsigned long len, const char *options); | 23 | extern int init_module(void *module, unsigned long len, const char *options); |
23 | extern int delete_module(const char *module, unsigned flags); | 24 | extern 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); |