diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 43 | 
1 files changed, 32 insertions, 11 deletions
diff --git a/kernel/module.c b/kernel/module.c index b34813f725e9..42a1d2afb217 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -56,7 +56,6 @@  #include <linux/async.h>  #include <linux/percpu.h>  #include <linux/kmemleak.h> -#include <linux/kasan.h>  #include <linux/jump_label.h>  #include <linux/pfn.h>  #include <linux/bsearch.h> @@ -388,9 +387,9 @@ static bool check_symbol(const struct symsearch *syms,  		pr_warn("Symbol %s is marked as UNUSED, however this module is "  			"using it.\n", fsa->name);  		pr_warn("This symbol will go away in the future.\n"); -		pr_warn("Please evalute if this is the right api to use and if " -			"it really is, submit a report the linux kernel " -			"mailinglist together with submitting your code for " +		pr_warn("Please evaluate if this is the right api to use and " +			"if it really is, submit a report to the linux kernel " +			"mailing list together with submitting your code for "  			"inclusion.\n");  	}  #endif @@ -1814,7 +1813,6 @@ static void unset_module_init_ro_nx(struct module *mod) { }  void __weak module_memfree(void *module_region)  {  	vfree(module_region); -	kasan_module_free(module_region);  }  void __weak module_arch_cleanup(struct module *mod) @@ -1867,7 +1865,7 @@ static void free_module(struct module *mod)  	kfree(mod->args);  	percpu_modfree(mod); -	/* Free lock-classes: */ +	/* Free lock-classes; relies on the preceding sync_rcu(). */  	lockdep_free_key_range(mod->module_core, mod->core_size);  	/* Finally, free the core (containing the module structure) */ @@ -2313,11 +2311,13 @@ static void layout_symtab(struct module *mod, struct load_info *info)  	info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);  	info->stroffs = mod->core_size = info->symoffs + ndst * sizeof(Elf_Sym);  	mod->core_size += strtab_size; +	mod->core_size = debug_align(mod->core_size);  	/* Put string table section at end of init part of module. */  	strsect->sh_flags |= SHF_ALLOC;  	strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect,  					 info->index.str) | INIT_OFFSET_MASK; +	mod->init_size = debug_align(mod->init_size);  	pr_debug("\t%s\n", info->secstrings + strsect->sh_name);  } @@ -2479,6 +2479,23 @@ static int elf_header_check(struct load_info *info)  	return 0;  } +#define COPY_CHUNK_SIZE (16*PAGE_SIZE) + +static int copy_chunked_from_user(void *dst, const void __user *usrc, unsigned long len) +{ +	do { +		unsigned long n = min(len, COPY_CHUNK_SIZE); + +		if (copy_from_user(dst, usrc, n) != 0) +			return -EFAULT; +		cond_resched(); +		dst += n; +		usrc += n; +		len -= n; +	} while (len); +	return 0; +} +  /* Sets info->hdr and info->len. */  static int copy_module_from_user(const void __user *umod, unsigned long len,  				  struct load_info *info) @@ -2494,11 +2511,12 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,  		return err;  	/* Suck in entire file: we'll want most of it. */ -	info->hdr = vmalloc(info->len); +	info->hdr = __vmalloc(info->len, +			GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN, PAGE_KERNEL);  	if (!info->hdr)  		return -ENOMEM; -	if (copy_from_user(info->hdr, umod, info->len) != 0) { +	if (copy_chunked_from_user(info->hdr, umod, info->len) != 0) {  		vfree(info->hdr);  		return -EFAULT;  	} @@ -2753,6 +2771,9 @@ static int find_module_sections(struct module *mod, struct load_info *info)  	mod->trace_events = section_objs(info, "_ftrace_events",  					 sizeof(*mod->trace_events),  					 &mod->num_trace_events); +	mod->trace_enums = section_objs(info, "_ftrace_enum_map", +					sizeof(*mod->trace_enums), +					&mod->num_trace_enums);  #endif  #ifdef CONFIG_TRACING  	mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt", @@ -3349,9 +3370,6 @@ static int load_module(struct load_info *info, const char __user *uargs,  	module_bug_cleanup(mod);  	mutex_unlock(&module_mutex); -	/* Free lock-classes: */ -	lockdep_free_key_range(mod->module_core, mod->core_size); -  	/* we can't deallocate the module until we clear memory protection */  	unset_module_init_ro_nx(mod);  	unset_module_core_ro_nx(mod); @@ -3375,6 +3393,9 @@ static int load_module(struct load_info *info, const char __user *uargs,  	synchronize_rcu();  	mutex_unlock(&module_mutex);   free_module: +	/* Free lock-classes; relies on the preceding sync_rcu() */ +	lockdep_free_key_range(mod->module_core, mod->core_size); +  	module_deallocate(mod, info);   free_copy:  	free_copy(info);  |