History

module: add syscall to load module from fd

As part of the effort to create a stronger boundary between root and kernel, Chrome OS wants to be able to enforce that kernel modules are being loaded only from our read-only crypto-hash verified (dm_verity) root filesystem. Since the init_module syscall hands the kernel a module as a memory blob, no reasoning about the origin of the blob can be made. Earlier proposals for appending signatures to kernel modules would not be useful in Chrome OS, since it would involve adding an additional set of keys to our kernel and builds for no good reason: we already trust the contents of our root filesystem. We don't need to verify those kernel modules a second time. Having to do signature checking on module loading would slow us down and be redundant. All we need to know is where a module is coming from so we can say yes/no to loading it. If a file descriptor is used as the source of a kernel module, many more things can be reasoned about. In Chrome OS's case, we could enforce that the module lives on the filesystem we expect it to live on. In the case of IMA (or other LSMs), it would be possible, for example, to examine extended attributes that may contain signatures over the contents of the module. This introduces a new syscall (on x86), similar to init_module, that has only two arguments. The first argument is used as a file descriptor to the module and the second argument is a pointer to the NULL terminated string of module arguments.

Kees Cook committed 14 years ago

Commit 34e11691 parent 84ecfd15 files · +223 −148Browse files

Unified · Split

5 files
  1. arch/x86/syscalls/syscall_32.tbl +1 −0
  2. arch/x86/syscalls/syscall_64.tbl +1 −0
  3. include/linux/syscalls.h +1 −0
  4. kernel/module.c +219 −148
  5. kernel/sys_ni.c +1 −0
arch/x86/syscalls/syscall_32.tbl+1−0
@@ -356,3 +356,4 @@ · 355 unmodified lines
356356 347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv
357357 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev
358358 349 i386 kcmp sys_kcmp
359+350 i386 finit_module sys_finit_module
arch/x86/syscalls/syscall_64.tbl+1−0
@@ -319,6 +319,7 @@ · 318 unmodified lines
319319 310 64 process_vm_readv sys_process_vm_readv
320320 311 64 process_vm_writev sys_process_vm_writev
321321 312 common kcmp sys_kcmp
322+313 common finit_module sys_finit_module
322323
323324 #
324325 # x32-specific system call numbers start at 512 to avoid cache impact
include/linux/syscalls.h+1−0
@@ -868,4 +868,5 @@ asmlinkage long sys_process_vm_writev(pid_t pid, · 867 unmodified lines
868868
869869 asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
870870 unsigned long idx1, unsigned long idx2);
871+asmlinkage long sys_finit_module(int fd, const char __user *uargs);
871872 #endif
kernel/module.c+219−148
@@ -21,6 +21,7 @@ · 20 unmodified lines
2121 #include <linux/ftrace_event.h>
2222 #include <linux/init.h>
2323 #include <linux/kallsyms.h>
24+#include <linux/file.h>
2425 #include <linux/fs.h>
2526 #include <linux/sysfs.h>
2627 #include <linux/kernel.h>
@@ -2425,18 +2426,17 @@ static inline void kmemleak_load_module(const struct module *mod, · 2398 unmodified lines
24252426 #endif
24262427
24272428 #ifdef CONFIG_MODULE_SIG
2428−static int module_sig_check(struct load_info *info,
2429− const void *mod, unsigned long *_len)
2429+static int module_sig_check(struct load_info *info)
24302430 {
24312431 int err = -ENOKEY;
2432− unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
2433− unsigned long len = *_len;
2432+ const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
2433+ const void *mod = info->hdr;
24342434
2435− if (len > markerlen &&
2436− memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
2435+ if (info->len > markerlen &&
2436+ memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
24372437 /* We truncate the module to discard the signature */
2438− *_len -= markerlen;
2439− err = mod_verify_sig(mod, _len);
2438+ info->len -= markerlen;
2439+ err = mod_verify_sig(mod, &info->len);
24402440 }
24412441
24422442 if (!err) {
@@ -2454,59 +2454,97 @@ static int module_sig_check(struct load_info *info, · 11 unmodified lines
24542454 return err;
24552455 }
24562456 #else /* !CONFIG_MODULE_SIG */
2457−static int module_sig_check(struct load_info *info,
2458− void *mod, unsigned long *len)
2457+static int module_sig_check(struct load_info *info)
24592458 {
24602459 return 0;
24612460 }
24622461 #endif /* !CONFIG_MODULE_SIG */
24632462
2464−/* Sets info->hdr, info->len and info->sig_ok. */
2465−static int copy_and_check(struct load_info *info,
2466− const void __user *umod, unsigned long len,
2467− const char __user *uargs)
2463+/* Sanity checks against invalid binaries, wrong arch, weird elf version. */
2464+static int elf_header_check(struct load_info *info)
24682465 {
2469− int err;
2470− Elf_Ehdr *hdr;
2466+ if (info->len < sizeof(*(info->hdr)))
2467+ return -ENOEXEC;
2468+
2469+ if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0
2470+ || info->hdr->e_type != ET_REL
2471+ || !elf_check_arch(info->hdr)
2472+ || info->hdr->e_shentsize != sizeof(Elf_Shdr))
2473+ return -ENOEXEC;
2474+
2475+ if (info->hdr->e_shoff >= info->len
2476+ || (info->hdr->e_shnum * sizeof(Elf_Shdr) >
2477+ info->len - info->hdr->e_shoff))
2478+ return -ENOEXEC;
24712479
2472− if (len < sizeof(*hdr))
2480+ return 0;
2481+}
2482+
2483+/* Sets info->hdr and info->len. */
2484+static int copy_module_from_user(const void __user *umod, unsigned long len,
2485+ struct load_info *info)
2486+{
2487+ info->len = len;
2488+ if (info->len < sizeof(*(info->hdr)))
24732489 return -ENOEXEC;
24742490
24752491 /* Suck in entire file: we'll want most of it. */
2476− if ((hdr = vmalloc(len)) == NULL)
2492+ info->hdr = vmalloc(info->len);
2493+ if (!info->hdr)
24772494 return -ENOMEM;
24782495
2479− if (copy_from_user(hdr, umod, len) != 0) {
2480− err = -EFAULT;
2481− goto free_hdr;
2496+ if (copy_from_user(info->hdr, umod, info->len) != 0) {
2497+ vfree(info->hdr);
2498+ return -EFAULT;
24822499 }
24832500
2484− err = module_sig_check(info, hdr, &len);
2501+ return 0;
2502+}
2503+
2504+/* Sets info->hdr and info->len. */
2505+static int copy_module_from_fd(int fd, struct load_info *info)
2506+{
2507+ struct file *file;
2508+ int err;
2509+ struct kstat stat;
2510+ loff_t pos;
2511+ ssize_t bytes = 0;
2512+
2513+ file = fget(fd);
2514+ if (!file)
2515+ return -ENOEXEC;
2516+
2517+ err = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat);
24852518 if (err)
2486− goto free_hdr;
2519+ goto out;
24872520
2488− /* Sanity checks against insmoding binaries or wrong arch,
2489− weird elf version */
2490− if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0
2491− || hdr->e_type != ET_REL
2492− || !elf_check_arch(hdr)
2493− || hdr->e_shentsize != sizeof(Elf_Shdr)) {
2494− err = -ENOEXEC;
2495− goto free_hdr;
2521+ if (stat.size > INT_MAX) {
2522+ err = -EFBIG;
2523+ goto out;
24962524 }
2497−
2498− if (hdr->e_shoff >= len ||
2499− hdr->e_shnum * sizeof(Elf_Shdr) > len - hdr->e_shoff) {
2500− err = -ENOEXEC;
2501− goto free_hdr;
2525+ info->hdr = vmalloc(stat.size);
2526+ if (!info->hdr) {
2527+ err = -ENOMEM;
2528+ goto out;
25022529 }
25032530
2504− info->hdr = hdr;
2505− info->len = len;
2506− return 0;
2531+ pos = 0;
2532+ while (pos < stat.size) {
2533+ bytes = kernel_read(file, pos, (char *)(info->hdr) + pos,
2534+ stat.size - pos);
2535+ if (bytes < 0) {
2536+ vfree(info->hdr);
2537+ err = bytes;
2538+ goto out;
2539+ }
2540+ if (bytes == 0)
2541+ break;
2542+ pos += bytes;
2543+ }
2544+ info->len = pos;
25072545
2508−free_hdr:
2509− vfree(hdr);
2546+out:
2547+ fput(file);
25102548 return err;
25112549 }
25122550
@@ -2945,33 +2983,123 @@ static bool finished_loading(const char *name) · 432 unmodified lines
29452983 return ret;
29462984 }
29472985
2986+/* Call module constructors. */
2987+static void do_mod_ctors(struct module *mod)
2988+{
2989+#ifdef CONFIG_CONSTRUCTORS
2990+ unsigned long i;
2991+
2992+ for (i = 0; i < mod->num_ctors; i++)
2993+ mod->ctors[i]();
2994+#endif
2995+}
2996+
2997+/* This is where the real work happens */
2998+static int do_init_module(struct module *mod)
2999+{
3000+ int ret = 0;
3001+
3002+ blocking_notifier_call_chain(&module_notify_list,
3003+ MODULE_STATE_COMING, mod);
3004+
3005+ /* Set RO and NX regions for core */
3006+ set_section_ro_nx(mod->module_core,
3007+ mod->core_text_size,
3008+ mod->core_ro_size,
3009+ mod->core_size);
3010+
3011+ /* Set RO and NX regions for init */
3012+ set_section_ro_nx(mod->module_init,
3013+ mod->init_text_size,
3014+ mod->init_ro_size,
3015+ mod->init_size);
3016+
3017+ do_mod_ctors(mod);
3018+ /* Start the module */
3019+ if (mod->init != NULL)
3020+ ret = do_one_initcall(mod->init);
3021+ if (ret < 0) {
3022+ /* Init routine failed: abort. Try to protect us from
3023+ buggy refcounters. */
3024+ mod->state = MODULE_STATE_GOING;
3025+ synchronize_sched();
3026+ module_put(mod);
3027+ blocking_notifier_call_chain(&module_notify_list,
3028+ MODULE_STATE_GOING, mod);
3029+ free_module(mod);
3030+ wake_up_all(&module_wq);
3031+ return ret;
3032+ }
3033+ if (ret > 0) {
3034+ printk(KERN_WARNING
3035+"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
3036+"%s: loading module anyway...\n",
3037+ __func__, mod->name, ret,
3038+ __func__);
3039+ dump_stack();
3040+ }
3041+
3042+ /* Now it's a first class citizen! */
3043+ mod->state = MODULE_STATE_LIVE;
3044+ blocking_notifier_call_chain(&module_notify_list,
3045+ MODULE_STATE_LIVE, mod);
3046+
3047+ /* We need to finish all async code before the module init sequence is done */
3048+ async_synchronize_full();
3049+
3050+ mutex_lock(&module_mutex);
3051+ /* Drop initial reference. */
3052+ module_put(mod);
3053+ trim_init_extable(mod);
3054+#ifdef CONFIG_KALLSYMS
3055+ mod->num_symtab = mod->core_num_syms;
3056+ mod->symtab = mod->core_symtab;
3057+ mod->strtab = mod->core_strtab;
3058+#endif
3059+ unset_module_init_ro_nx(mod);
3060+ module_free(mod, mod->module_init);
3061+ mod->module_init = NULL;
3062+ mod->init_size = 0;
3063+ mod->init_ro_size = 0;
3064+ mod->init_text_size = 0;
3065+ mutex_unlock(&module_mutex);
3066+ wake_up_all(&module_wq);
3067+
3068+ return 0;
3069+}
3070+
3071+static int may_init_module(void)
3072+{
3073+ if (!capable(CAP_SYS_MODULE) || modules_disabled)
3074+ return -EPERM;
3075+
3076+ return 0;
3077+}
3078+
29483079 /* Allocate and load the module: note that size of section 0 is always
29493080 zero, and we rely on this for optional sections. */
2950−static struct module *load_module(void __user *umod,
2951− unsigned long len,
2952− const char __user *uargs)
3081+static int load_module(struct load_info *info, const char __user *uargs)
29533082 {
2954− struct load_info info = { NULL, };
29553083 struct module *mod, *old;
29563084 long err;
29573085
2958− pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n",
2959− umod, len, uargs);
3086+ err = module_sig_check(info);
3087+ if (err)
3088+ goto free_copy;
29603089
2961− /* Copy in the blobs from userspace, check they are vaguely sane. */
2962− err = copy_and_check(&info, umod, len, uargs);
3090+ err = elf_header_check(info);
29633091 if (err)
2964− return ERR_PTR(err);
3092+ goto free_copy;
29653093
29663094 /* Figure out module layout, and allocate all the memory. */
2967− mod = layout_and_allocate(&info);
3095+ mod = layout_and_allocate(info);
29683096 if (IS_ERR(mod)) {
29693097 err = PTR_ERR(mod);
29703098 goto free_copy;
29713099 }
29723100
29733101 #ifdef CONFIG_MODULE_SIG
2974− mod->sig_ok = info.sig_ok;
3102+ mod->sig_ok = info->sig_ok;
29753103 if (!mod->sig_ok)
29763104 add_taint_module(mod, TAINT_FORCED_MODULE);
29773105 #endif
@@ -2983,25 +3111,25 @@ static struct module *load_module(void __user *umod, · 5 unmodified lines
29833111
29843112 /* Now we've got everything in the final locations, we can
29853113 * find optional sections. */
2986− find_module_sections(mod, &info);
3114+ find_module_sections(mod, info);
29873115
29883116 err = check_module_license_and_versions(mod);
29893117 if (err)
29903118 goto free_unload;
29913119
29923120 /* Set up MODINFO_ATTR fields */
2993− setup_modinfo(mod, &info);
3121+ setup_modinfo(mod, info);
29943122
29953123 /* Fix up syms, so that st_value is a pointer to location. */
2996− err = simplify_symbols(mod, &info);
3124+ err = simplify_symbols(mod, info);
29973125 if (err < 0)
29983126 goto free_modinfo;
29993127
3000− err = apply_relocations(mod, &info);
3128+ err = apply_relocations(mod, info);
30013129 if (err < 0)
30023130 goto free_modinfo;
30033131
3004− err = post_relocation(mod, &info);
3132+ err = post_relocation(mod, info);
30053133 if (err < 0)
30063134 goto free_modinfo;
30073135
@@ -3041,14 +3169,14 @@ again: · 33 unmodified lines
30413169 }
30423170
30433171 /* This has to be done once we're sure module name is unique. */
3044− dynamic_debug_setup(info.debug, info.num_debug);
3172+ dynamic_debug_setup(info->debug, info->num_debug);
30453173
30463174 /* Find duplicate symbols */
30473175 err = verify_export_symbols(mod);
30483176 if (err < 0)
30493177 goto ddebug;
30503178
3051− module_bug_finalize(info.hdr, info.sechdrs, mod);
3179+ module_bug_finalize(info->hdr, info->sechdrs, mod);
30523180 list_add_rcu(&mod->list, &modules);
30533181 mutex_unlock(&module_mutex);
30543182
@@ -3059,16 +3187,17 @@ again: · 4 unmodified lines
30593187 goto unlink;
30603188
30613189 /* Link in to syfs. */
3062− err = mod_sysfs_setup(mod, &info, mod->kp, mod->num_kp);
3190+ err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
30633191 if (err < 0)
30643192 goto unlink;
30653193
30663194 /* Get rid of temporary copy. */
3067− free_copy(&info);
3195+ free_copy(info);
30683196
30693197 /* Done! */
30703198 trace_module_load(mod);
3071− return mod;
3199+
3200+ return do_init_module(mod);
30723201
30733202 unlink:
30743203 mutex_lock(&module_mutex);
@@ -3077,7 +3206,7 @@ again: · 2 unmodified lines
30773206 module_bug_cleanup(mod);
30783207 wake_up_all(&module_wq);
30793208 ddebug:
3080− dynamic_debug_remove(info.debug);
3209+ dynamic_debug_remove(info->debug);
30813210 unlock:
30823211 mutex_unlock(&module_mutex);
30833212 synchronize_sched();
@@ -3089,106 +3218,48 @@ again: · 5 unmodified lines
30893218 free_unload:
30903219 module_unload_free(mod);
30913220 free_module:
3092− module_deallocate(mod, &info);
3221+ module_deallocate(mod, info);
30933222 free_copy:
3094− free_copy(&info);
3095− return ERR_PTR(err);
3096−}
3097−
3098−/* Call module constructors. */
3099−static void do_mod_ctors(struct module *mod)
3100−{
3101−#ifdef CONFIG_CONSTRUCTORS
3102− unsigned long i;
3103−
3104− for (i = 0; i < mod->num_ctors; i++)
3105− mod->ctors[i]();
3106−#endif
3223+ free_copy(info);
3224+ return err;
31073225 }
31083226
3109−/* This is where the real work happens */
31103227 SYSCALL_DEFINE3(init_module, void __user *, umod,
31113228 unsigned long, len, const char __user *, uargs)
31123229 {
3113− struct module *mod;
3114− int ret = 0;
3115−
3116− /* Must have permission */
3117− if (!capable(CAP_SYS_MODULE) || modules_disabled)
3118− return -EPERM;
3230+ int err;
3231+ struct load_info info = { };
31193232
3120− /* Do all the hard work */
3121− mod = load_module(umod, len, uargs);
3122− if (IS_ERR(mod))
3123− return PTR_ERR(mod);
3233+ err = may_init_module();
3234+ if (err)
3235+ return err;
31243236
3125− blocking_notifier_call_chain(&module_notify_list,
3126− MODULE_STATE_COMING, mod);
3237+ pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n",
3238+ umod, len, uargs);
31273239
3128− /* Set RO and NX regions for core */
3129− set_section_ro_nx(mod->module_core,
3130− mod->core_text_size,
3131− mod->core_ro_size,
3132− mod->core_size);
3240+ err = copy_module_from_user(umod, len, &info);
3241+ if (err)
3242+ return err;
31333243
3134− /* Set RO and NX regions for init */
3135− set_section_ro_nx(mod->module_init,
3136− mod->init_text_size,
3137− mod->init_ro_size,
3138− mod->init_size);
3244+ return load_module(&info, uargs);
3245+}
31393246
3140− do_mod_ctors(mod);
3141− /* Start the module */
3142− if (mod->init != NULL)
3143− ret = do_one_initcall(mod->init);
3144− if (ret < 0) {
3145− /* Init routine failed: abort. Try to protect us from
3146− buggy refcounters. */
3147− mod->state = MODULE_STATE_GOING;
3148− synchronize_sched();
3149− module_put(mod);
3150− blocking_notifier_call_chain(&module_notify_list,
3151− MODULE_STATE_GOING, mod);
3152− free_module(mod);
3153− wake_up_all(&module_wq);
3154− return ret;
3155− }
3156− if (ret > 0) {
3157− printk(KERN_WARNING
3158−"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
3159−"%s: loading module anyway...\n",
3160− __func__, mod->name, ret,
3161− __func__);
3162− dump_stack();
3163− }
3247+SYSCALL_DEFINE2(finit_module, int, fd, const char __user *, uargs)
3248+{
3249+ int err;
3250+ struct load_info info = { };
31643251
3165− /* Now it's a first class citizen! */
3166− mod->state = MODULE_STATE_LIVE;
3167− blocking_notifier_call_chain(&module_notify_list,
3168− MODULE_STATE_LIVE, mod);
3252+ err = may_init_module();
3253+ if (err)
3254+ return err;
31693255
3170− /* We need to finish all async code before the module init sequence is done */
3171− async_synchronize_full();
3256+ pr_debug("finit_module: fd=%d, uargs=%p\n", fd, uargs);
31723257
3173− mutex_lock(&module_mutex);
3174− /* Drop initial reference. */
3175− module_put(mod);
3176− trim_init_extable(mod);
3177−#ifdef CONFIG_KALLSYMS
3178− mod->num_symtab = mod->core_num_syms;
3179− mod->symtab = mod->core_symtab;
3180− mod->strtab = mod->core_strtab;
3181−#endif
3182− unset_module_init_ro_nx(mod);
3183− module_free(mod, mod->module_init);
3184− mod->module_init = NULL;
3185− mod->init_size = 0;
3186− mod->init_ro_size = 0;
3187− mod->init_text_size = 0;
3188− mutex_unlock(&module_mutex);
3189− wake_up_all(&module_wq);
3258+ err = copy_module_from_fd(fd, &info);
3259+ if (err)
3260+ return err;
31903261
3191− return 0;
3262+ return load_module(&info, uargs);
31923263 }
31933264
31943265 static inline int within(unsigned long addr, void *start, unsigned long size)
kernel/sys_ni.c+1−0
@@ -25,6 +25,7 @@ cond_syscall(sys_swapoff); · 24 unmodified lines
2525 cond_syscall(sys_kexec_load);
2626 cond_syscall(compat_sys_kexec_load);
2727 cond_syscall(sys_init_module);
28+cond_syscall(sys_finit_module);
2829 cond_syscall(sys_delete_module);
2930 cond_syscall(sys_socketpair);
3031 cond_syscall(sys_bind);