diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-19 10:55:08 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-19 10:55:08 -0500 |
| commit | 7a684c452e2589f3ddd7e2d466b4f747d3715ad9 (patch) | |
| tree | fed803e7450770993575b37807ba2195eafd5b0e | |
| parent | 7f2de8171ddf28fdb2ca7f9a683ee1207849f718 (diff) | |
| parent | e10e1774efbdaec54698454200619a03a01e1d64 (diff) | |
Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull module update from Rusty Russell:
"Nothing all that exciting; a new module-from-fd syscall for those who
want to verify the source of the module (ChromeOS) and/or use standard
IMA on it or other security hooks."
* tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
MODSIGN: Fix kbuild output when using default extra_certificates
MODSIGN: Avoid using .incbin in C source
modules: don't hand 0 to vmalloc.
module: Remove a extra null character at the top of module->strtab.
ASN.1: Use the ASN1_LONG_TAG and ASN1_INDEFINITE_LENGTH constants
ASN.1: Define indefinite length marker constant
moduleparam: use __UNIQUE_ID()
__UNIQUE_ID()
MODSIGN: Add modules_sign make target
powerpc: add finit_module syscall.
ima: support new kernel module syscall
add finit_module syscall to asm-generic
ARM: add finit_module syscall to ARM
security: introduce kernel_module_from_file hook
module: add flags arg to sys_finit_module()
module: add syscall to load module from fd
36 files changed, 434 insertions, 210 deletions
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index 986946613542..ec0a38ef3145 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy | |||
| @@ -23,7 +23,7 @@ Description: | |||
| 23 | lsm: [[subj_user=] [subj_role=] [subj_type=] | 23 | lsm: [[subj_user=] [subj_role=] [subj_type=] |
| 24 | [obj_user=] [obj_role=] [obj_type=]] | 24 | [obj_user=] [obj_role=] [obj_type=]] |
| 25 | 25 | ||
| 26 | base: func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK] | 26 | base: func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK][MODULE_CHECK] |
| 27 | mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] | 27 | mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] |
| 28 | fsmagic:= hex value | 28 | fsmagic:= hex value |
| 29 | uid:= decimal value | 29 | uid:= decimal value |
| @@ -53,6 +53,7 @@ Description: | |||
| 53 | measure func=BPRM_CHECK | 53 | measure func=BPRM_CHECK |
| 54 | measure func=FILE_MMAP mask=MAY_EXEC | 54 | measure func=FILE_MMAP mask=MAY_EXEC |
| 55 | measure func=FILE_CHECK mask=MAY_READ uid=0 | 55 | measure func=FILE_CHECK mask=MAY_READ uid=0 |
| 56 | measure func=MODULE_CHECK uid=0 | ||
| 56 | appraise fowner=0 | 57 | appraise fowner=0 |
| 57 | 58 | ||
| 58 | The default policy measures all executables in bprm_check, | 59 | The default policy measures all executables in bprm_check, |
| @@ -981,6 +981,12 @@ _modinst_post: _modinst_ | |||
| 981 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst | 981 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst |
| 982 | $(call cmd,depmod) | 982 | $(call cmd,depmod) |
| 983 | 983 | ||
| 984 | ifeq ($(CONFIG_MODULE_SIG), y) | ||
| 985 | PHONY += modules_sign | ||
| 986 | modules_sign: | ||
| 987 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modsign | ||
| 988 | endif | ||
| 989 | |||
| 984 | else # CONFIG_MODULES | 990 | else # CONFIG_MODULES |
| 985 | 991 | ||
| 986 | # Modules not configured | 992 | # Modules not configured |
diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h index ac03bdb4ae44..4da7cde70b5d 100644 --- a/arch/arm/include/uapi/asm/unistd.h +++ b/arch/arm/include/uapi/asm/unistd.h | |||
| @@ -405,6 +405,7 @@ | |||
| 405 | #define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) | 405 | #define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) |
| 406 | #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) | 406 | #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) |
| 407 | /* 378 for kcmp */ | 407 | /* 378 for kcmp */ |
| 408 | #define __NR_finit_module (__NR_SYSCALL_BASE+379) | ||
| 408 | 409 | ||
| 409 | /* | 410 | /* |
| 410 | * This may need to be greater than __NR_last_syscall+1 in order to | 411 | * This may need to be greater than __NR_last_syscall+1 in order to |
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 5935b6a02e6e..a4fda4e7a372 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
| @@ -388,6 +388,7 @@ | |||
| 388 | CALL(sys_process_vm_readv) | 388 | CALL(sys_process_vm_readv) |
| 389 | CALL(sys_process_vm_writev) | 389 | CALL(sys_process_vm_writev) |
| 390 | CALL(sys_ni_syscall) /* reserved for sys_kcmp */ | 390 | CALL(sys_ni_syscall) /* reserved for sys_kcmp */ |
| 391 | CALL(sys_finit_module) | ||
| 391 | #ifndef syscalls_counted | 392 | #ifndef syscalls_counted |
| 392 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls | 393 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls |
| 393 | #define syscalls_counted | 394 | #define syscalls_counted |
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c index 37400f5869e6..51123f985eb5 100644 --- a/arch/cris/kernel/module.c +++ b/arch/cris/kernel/module.c | |||
| @@ -32,8 +32,6 @@ | |||
| 32 | #ifdef CONFIG_ETRAX_KMALLOCED_MODULES | 32 | #ifdef CONFIG_ETRAX_KMALLOCED_MODULES |
| 33 | void *module_alloc(unsigned long size) | 33 | void *module_alloc(unsigned long size) |
| 34 | { | 34 | { |
| 35 | if (size == 0) | ||
| 36 | return NULL; | ||
| 37 | return kmalloc(size, GFP_KERNEL); | 35 | return kmalloc(size, GFP_KERNEL); |
| 38 | } | 36 | } |
| 39 | 37 | ||
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 5e34ccf39a49..2a625fb063e1 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c | |||
| @@ -214,8 +214,6 @@ static inline int reassemble_22(int as22) | |||
| 214 | 214 | ||
| 215 | void *module_alloc(unsigned long size) | 215 | void *module_alloc(unsigned long size) |
| 216 | { | 216 | { |
| 217 | if (size == 0) | ||
| 218 | return NULL; | ||
| 219 | /* using RWX means less protection for modules, but it's | 217 | /* using RWX means less protection for modules, but it's |
| 220 | * easier than trying to map the text, data, init_text and | 218 | * easier than trying to map the text, data, init_text and |
| 221 | * init_data correctly */ | 219 | * init_data correctly */ |
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index cec8aae5cbf8..97909d3b1d7b 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h | |||
| @@ -356,3 +356,4 @@ COMPAT_SYS_SPU(sendmmsg) | |||
| 356 | SYSCALL_SPU(setns) | 356 | SYSCALL_SPU(setns) |
| 357 | COMPAT_SYS(process_vm_readv) | 357 | COMPAT_SYS(process_vm_readv) |
| 358 | COMPAT_SYS(process_vm_writev) | 358 | COMPAT_SYS(process_vm_writev) |
| 359 | SYSCALL(finit_module) | ||
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index bcbbe413c606..29365e15ed7c 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include <uapi/asm/unistd.h> | 12 | #include <uapi/asm/unistd.h> |
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | #define __NR_syscalls 353 | 15 | #define __NR_syscalls 354 |
| 16 | 16 | ||
| 17 | #define __NR__exit __NR_exit | 17 | #define __NR__exit __NR_exit |
| 18 | #define NR_syscalls __NR_syscalls | 18 | #define NR_syscalls __NR_syscalls |
diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h index 380b5d37a904..8c478c6c6b1e 100644 --- a/arch/powerpc/include/uapi/asm/unistd.h +++ b/arch/powerpc/include/uapi/asm/unistd.h | |||
| @@ -375,6 +375,7 @@ | |||
| 375 | #define __NR_setns 350 | 375 | #define __NR_setns 350 |
| 376 | #define __NR_process_vm_readv 351 | 376 | #define __NR_process_vm_readv 351 |
| 377 | #define __NR_process_vm_writev 352 | 377 | #define __NR_process_vm_writev 352 |
| 378 | #define __NR_finit_module 353 | ||
| 378 | 379 | ||
| 379 | 380 | ||
| 380 | #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ | 381 | #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ |
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index f1ddc0d23679..4435488ebe25 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c | |||
| @@ -43,10 +43,6 @@ void *module_alloc(unsigned long size) | |||
| 43 | { | 43 | { |
| 44 | void *ret; | 44 | void *ret; |
| 45 | 45 | ||
| 46 | /* We handle the zero case fine, unlike vmalloc */ | ||
| 47 | if (size == 0) | ||
| 48 | return NULL; | ||
| 49 | |||
| 50 | ret = module_map(size); | 46 | ret = module_map(size); |
| 51 | if (ret) | 47 | if (ret) |
| 52 | memset(ret, 0, size); | 48 | memset(ret, 0, size); |
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c index 243ffebe38d6..4918d91bc3a6 100644 --- a/arch/tile/kernel/module.c +++ b/arch/tile/kernel/module.c | |||
| @@ -42,8 +42,6 @@ void *module_alloc(unsigned long size) | |||
| 42 | int i = 0; | 42 | int i = 0; |
| 43 | int npages; | 43 | int npages; |
| 44 | 44 | ||
| 45 | if (size == 0) | ||
| 46 | return NULL; | ||
| 47 | npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; | 45 | npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; |
| 48 | pages = kmalloc(npages * sizeof(struct page *), GFP_KERNEL); | 46 | pages = kmalloc(npages * sizeof(struct page *), GFP_KERNEL); |
| 49 | if (pages == NULL) | 47 | if (pages == NULL) |
diff --git a/arch/unicore32/kernel/module.c b/arch/unicore32/kernel/module.c index 8fbe8577f5e6..16bd1495b934 100644 --- a/arch/unicore32/kernel/module.c +++ b/arch/unicore32/kernel/module.c | |||
| @@ -27,9 +27,6 @@ void *module_alloc(unsigned long size) | |||
| 27 | struct vm_struct *area; | 27 | struct vm_struct *area; |
| 28 | 28 | ||
| 29 | size = PAGE_ALIGN(size); | 29 | size = PAGE_ALIGN(size); |
| 30 | if (!size) | ||
| 31 | return NULL; | ||
| 32 | |||
| 33 | area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END); | 30 | area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END); |
| 34 | if (!area) | 31 | if (!area) |
| 35 | return NULL; | 32 | return NULL; |
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl index ee3c220ee500..05f404f53f59 100644 --- a/arch/x86/syscalls/syscall_32.tbl +++ b/arch/x86/syscalls/syscall_32.tbl | |||
| @@ -356,3 +356,4 @@ | |||
| 356 | 347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv | 356 | 347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv |
| 357 | 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev | 357 | 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev |
| 358 | 349 i386 kcmp sys_kcmp | 358 | 349 i386 kcmp sys_kcmp |
| 359 | 350 i386 finit_module sys_finit_module | ||
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index a582bfed95bb..7c58c84b7bc8 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl | |||
| @@ -319,6 +319,7 @@ | |||
| 319 | 310 64 process_vm_readv sys_process_vm_readv | 319 | 310 64 process_vm_readv sys_process_vm_readv |
| 320 | 311 64 process_vm_writev sys_process_vm_writev | 320 | 311 64 process_vm_writev sys_process_vm_writev |
| 321 | 312 common kcmp sys_kcmp | 321 | 312 common kcmp sys_kcmp |
| 322 | 313 common finit_module sys_finit_module | ||
| 322 | 323 | ||
| 323 | # | 324 | # |
| 324 | # x32-specific system call numbers start at 512 to avoid cache impact | 325 | # x32-specific system call numbers start at 512 to avoid cache impact |
diff --git a/include/linux/asn1.h b/include/linux/asn1.h index 5c3f4e4b9a23..eed6982860ba 100644 --- a/include/linux/asn1.h +++ b/include/linux/asn1.h | |||
| @@ -64,4 +64,6 @@ enum asn1_tag { | |||
| 64 | ASN1_LONG_TAG = 31 /* Long form tag */ | 64 | ASN1_LONG_TAG = 31 /* Long form tag */ |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | #define ASN1_INDEFINITE_LENGTH 0x80 | ||
| 68 | |||
| 67 | #endif /* _LINUX_ASN1_H */ | 69 | #endif /* _LINUX_ASN1_H */ |
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index dc16a858e77c..662fd1b4c42a 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h | |||
| @@ -31,6 +31,8 @@ | |||
| 31 | 31 | ||
| 32 | #define __linktime_error(message) __attribute__((__error__(message))) | 32 | #define __linktime_error(message) __attribute__((__error__(message))) |
| 33 | 33 | ||
| 34 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) | ||
| 35 | |||
| 34 | #if __GNUC_MINOR__ >= 5 | 36 | #if __GNUC_MINOR__ >= 5 |
| 35 | /* | 37 | /* |
| 36 | * Mark a position in code as unreachable. This can be used to | 38 | * Mark a position in code as unreachable. This can be used to |
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index b121554f1fe2..dd852b73b286 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h | |||
| @@ -44,6 +44,10 @@ extern void __chk_io_ptr(const volatile void __iomem *); | |||
| 44 | # define __rcu | 44 | # define __rcu |
| 45 | #endif | 45 | #endif |
| 46 | 46 | ||
| 47 | /* Indirect macros required for expanded argument pasting, eg. __LINE__. */ | ||
| 48 | #define ___PASTE(a,b) a##b | ||
| 49 | #define __PASTE(a,b) ___PASTE(a,b) | ||
| 50 | |||
| 47 | #ifdef __KERNEL__ | 51 | #ifdef __KERNEL__ |
| 48 | 52 | ||
| 49 | #ifdef __GNUC__ | 53 | #ifdef __GNUC__ |
| @@ -166,6 +170,11 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); | |||
| 166 | (typeof(ptr)) (__ptr + (off)); }) | 170 | (typeof(ptr)) (__ptr + (off)); }) |
| 167 | #endif | 171 | #endif |
| 168 | 172 | ||
| 173 | /* Not-quite-unique ID. */ | ||
| 174 | #ifndef __UNIQUE_ID | ||
| 175 | # define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__) | ||
| 176 | #endif | ||
| 177 | |||
| 169 | #endif /* __KERNEL__ */ | 178 | #endif /* __KERNEL__ */ |
| 170 | 179 | ||
| 171 | #endif /* __ASSEMBLY__ */ | 180 | #endif /* __ASSEMBLY__ */ |
diff --git a/include/linux/ima.h b/include/linux/ima.h index 2c7223d7e73b..86c361e947b9 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h | |||
| @@ -18,6 +18,7 @@ extern int ima_bprm_check(struct linux_binprm *bprm); | |||
| 18 | extern int ima_file_check(struct file *file, int mask); | 18 | extern int ima_file_check(struct file *file, int mask); |
| 19 | extern void ima_file_free(struct file *file); | 19 | extern void ima_file_free(struct file *file); |
| 20 | extern int ima_file_mmap(struct file *file, unsigned long prot); | 20 | extern int ima_file_mmap(struct file *file, unsigned long prot); |
| 21 | extern int ima_module_check(struct file *file); | ||
| 21 | 22 | ||
| 22 | #else | 23 | #else |
| 23 | static inline int ima_bprm_check(struct linux_binprm *bprm) | 24 | static inline int ima_bprm_check(struct linux_binprm *bprm) |
| @@ -40,6 +41,11 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot) | |||
| 40 | return 0; | 41 | return 0; |
| 41 | } | 42 | } |
| 42 | 43 | ||
| 44 | static inline int ima_module_check(struct file *file) | ||
| 45 | { | ||
| 46 | return 0; | ||
| 47 | } | ||
| 48 | |||
| 43 | #endif /* CONFIG_IMA_H */ | 49 | #endif /* CONFIG_IMA_H */ |
| 44 | 50 | ||
| 45 | #ifdef CONFIG_IMA_APPRAISE | 51 | #ifdef CONFIG_IMA_APPRAISE |
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index d6a58065c09c..137b4198fc03 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
| @@ -16,17 +16,15 @@ | |||
| 16 | /* Chosen so that structs with an unsigned long line up. */ | 16 | /* Chosen so that structs with an unsigned long line up. */ |
| 17 | #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long)) | 17 | #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long)) |
| 18 | 18 | ||
| 19 | #define ___module_cat(a,b) __mod_ ## a ## b | ||
| 20 | #define __module_cat(a,b) ___module_cat(a,b) | ||
| 21 | #ifdef MODULE | 19 | #ifdef MODULE |
| 22 | #define __MODULE_INFO(tag, name, info) \ | 20 | #define __MODULE_INFO(tag, name, info) \ |
| 23 | static const char __module_cat(name,__LINE__)[] \ | 21 | static const char __UNIQUE_ID(name)[] \ |
| 24 | __used __attribute__((section(".modinfo"), unused, aligned(1))) \ | 22 | __used __attribute__((section(".modinfo"), unused, aligned(1))) \ |
| 25 | = __stringify(tag) "=" info | 23 | = __stringify(tag) "=" info |
| 26 | #else /* !MODULE */ | 24 | #else /* !MODULE */ |
| 27 | /* This struct is here for syntactic coherency, it is not used */ | 25 | /* This struct is here for syntactic coherency, it is not used */ |
| 28 | #define __MODULE_INFO(tag, name, info) \ | 26 | #define __MODULE_INFO(tag, name, info) \ |
| 29 | struct __module_cat(name,__LINE__) {} | 27 | struct __UNIQUE_ID(name) {} |
| 30 | #endif | 28 | #endif |
| 31 | #define __MODULE_PARM_TYPE(name, _type) \ | 29 | #define __MODULE_PARM_TYPE(name, _type) \ |
| 32 | __MODULE_INFO(parmtype, name##type, #name ":" _type) | 30 | __MODULE_INFO(parmtype, name##type, #name ":" _type) |
diff --git a/include/linux/security.h b/include/linux/security.h index 05e88bdcf7d9..0f6afc657f77 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
| @@ -694,6 +694,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 694 | * userspace to load a kernel module with the given name. | 694 | * userspace to load a kernel module with the given name. |
| 695 | * @kmod_name name of the module requested by the kernel | 695 | * @kmod_name name of the module requested by the kernel |
| 696 | * Return 0 if successful. | 696 | * Return 0 if successful. |
| 697 | * @kernel_module_from_file: | ||
| 698 | * Load a kernel module from userspace. | ||
| 699 | * @file contains the file structure pointing to the file containing | ||
| 700 | * the kernel module to load. If the module is being loaded from a blob, | ||
| 701 | * this argument will be NULL. | ||
| 702 | * Return 0 if permission is granted. | ||
| 697 | * @task_fix_setuid: | 703 | * @task_fix_setuid: |
| 698 | * Update the module's state after setting one or more of the user | 704 | * Update the module's state after setting one or more of the user |
| 699 | * identity attributes of the current process. The @flags parameter | 705 | * identity attributes of the current process. The @flags parameter |
| @@ -1508,6 +1514,7 @@ struct security_operations { | |||
| 1508 | int (*kernel_act_as)(struct cred *new, u32 secid); | 1514 | int (*kernel_act_as)(struct cred *new, u32 secid); |
| 1509 | int (*kernel_create_files_as)(struct cred *new, struct inode *inode); | 1515 | int (*kernel_create_files_as)(struct cred *new, struct inode *inode); |
| 1510 | int (*kernel_module_request)(char *kmod_name); | 1516 | int (*kernel_module_request)(char *kmod_name); |
| 1517 | int (*kernel_module_from_file)(struct file *file); | ||
| 1511 | int (*task_fix_setuid) (struct cred *new, const struct cred *old, | 1518 | int (*task_fix_setuid) (struct cred *new, const struct cred *old, |
| 1512 | int flags); | 1519 | int flags); |
| 1513 | int (*task_setpgid) (struct task_struct *p, pid_t pgid); | 1520 | int (*task_setpgid) (struct task_struct *p, pid_t pgid); |
| @@ -1765,6 +1772,7 @@ void security_transfer_creds(struct cred *new, const struct cred *old); | |||
| 1765 | int security_kernel_act_as(struct cred *new, u32 secid); | 1772 | int security_kernel_act_as(struct cred *new, u32 secid); |
| 1766 | int security_kernel_create_files_as(struct cred *new, struct inode *inode); | 1773 | int security_kernel_create_files_as(struct cred *new, struct inode *inode); |
| 1767 | int security_kernel_module_request(char *kmod_name); | 1774 | int security_kernel_module_request(char *kmod_name); |
| 1775 | int security_kernel_module_from_file(struct file *file); | ||
| 1768 | int security_task_fix_setuid(struct cred *new, const struct cred *old, | 1776 | int security_task_fix_setuid(struct cred *new, const struct cred *old, |
| 1769 | int flags); | 1777 | int flags); |
| 1770 | int security_task_setpgid(struct task_struct *p, pid_t pgid); | 1778 | int security_task_setpgid(struct task_struct *p, pid_t pgid); |
| @@ -2278,6 +2286,11 @@ static inline int security_kernel_module_request(char *kmod_name) | |||
| 2278 | return 0; | 2286 | return 0; |
| 2279 | } | 2287 | } |
| 2280 | 2288 | ||
| 2289 | static inline int security_kernel_module_from_file(struct file *file) | ||
| 2290 | { | ||
| 2291 | return 0; | ||
| 2292 | } | ||
| 2293 | |||
| 2281 | static inline int security_task_fix_setuid(struct cred *new, | 2294 | static inline int security_task_fix_setuid(struct cred *new, |
| 2282 | const struct cred *old, | 2295 | const struct cred *old, |
| 2283 | int flags) | 2296 | int flags) |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 36c3b07c5119..6caee34bf8a2 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
| @@ -880,4 +880,5 @@ asmlinkage long sys_process_vm_writev(pid_t pid, | |||
| 880 | 880 | ||
| 881 | asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, | 881 | asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, |
| 882 | unsigned long idx1, unsigned long idx2); | 882 | unsigned long idx1, unsigned long idx2); |
| 883 | asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags); | ||
| 883 | #endif | 884 | #endif |
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 6e595ba545f4..2c531f478410 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h | |||
| @@ -690,9 +690,11 @@ __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \ | |||
| 690 | compat_sys_process_vm_writev) | 690 | compat_sys_process_vm_writev) |
| 691 | #define __NR_kcmp 272 | 691 | #define __NR_kcmp 272 |
| 692 | __SYSCALL(__NR_kcmp, sys_kcmp) | 692 | __SYSCALL(__NR_kcmp, sys_kcmp) |
| 693 | #define __NR_finit_module 273 | ||
| 694 | __SYSCALL(__NR_finit_module, sys_finit_module) | ||
| 693 | 695 | ||
| 694 | #undef __NR_syscalls | 696 | #undef __NR_syscalls |
| 695 | #define __NR_syscalls 273 | 697 | #define __NR_syscalls 274 |
| 696 | 698 | ||
| 697 | /* | 699 | /* |
| 698 | * All syscalls below here should go away really, | 700 | * All syscalls below here should go away really, |
diff --git a/include/uapi/linux/module.h b/include/uapi/linux/module.h new file mode 100644 index 000000000000..38da4258b12f --- /dev/null +++ b/include/uapi/linux/module.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #ifndef _UAPI_LINUX_MODULE_H | ||
| 2 | #define _UAPI_LINUX_MODULE_H | ||
| 3 | |||
| 4 | /* Flags for sys_finit_module: */ | ||
| 5 | #define MODULE_INIT_IGNORE_MODVERSIONS 1 | ||
| 6 | #define MODULE_INIT_IGNORE_VERMAGIC 2 | ||
| 7 | |||
| 8 | #endif /* _UAPI_LINUX_MODULE_H */ | ||
diff --git a/kernel/Makefile b/kernel/Makefile index ac0d533eb7de..6c072b6da239 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
| @@ -54,7 +54,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o | |||
| 54 | obj-$(CONFIG_PROVE_LOCKING) += spinlock.o | 54 | obj-$(CONFIG_PROVE_LOCKING) += spinlock.o |
| 55 | obj-$(CONFIG_UID16) += uid16.o | 55 | obj-$(CONFIG_UID16) += uid16.o |
| 56 | obj-$(CONFIG_MODULES) += module.o | 56 | obj-$(CONFIG_MODULES) += module.o |
| 57 | obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o | 57 | obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o |
| 58 | obj-$(CONFIG_KALLSYMS) += kallsyms.o | 58 | obj-$(CONFIG_KALLSYMS) += kallsyms.o |
| 59 | obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o | 59 | obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o |
| 60 | obj-$(CONFIG_KEXEC) += kexec.o | 60 | obj-$(CONFIG_KEXEC) += kexec.o |
| @@ -137,10 +137,14 @@ ifeq ($(CONFIG_MODULE_SIG),y) | |||
| 137 | # | 137 | # |
| 138 | # Pull the signing certificate and any extra certificates into the kernel | 138 | # Pull the signing certificate and any extra certificates into the kernel |
| 139 | # | 139 | # |
| 140 | |||
| 141 | quiet_cmd_touch = TOUCH $@ | ||
| 142 | cmd_touch = touch $@ | ||
| 143 | |||
| 140 | extra_certificates: | 144 | extra_certificates: |
| 141 | touch $@ | 145 | $(call cmd,touch) |
| 142 | 146 | ||
| 143 | kernel/modsign_pubkey.o: signing_key.x509 extra_certificates | 147 | kernel/modsign_certificate.o: signing_key.x509 extra_certificates |
| 144 | 148 | ||
| 145 | ############################################################################### | 149 | ############################################################################### |
| 146 | # | 150 | # |
diff --git a/kernel/modsign_certificate.S b/kernel/modsign_certificate.S new file mode 100644 index 000000000000..246b4c6e6135 --- /dev/null +++ b/kernel/modsign_certificate.S | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | /* SYMBOL_PREFIX defined on commandline from CONFIG_SYMBOL_PREFIX */ | ||
| 2 | #ifndef SYMBOL_PREFIX | ||
| 3 | #define ASM_SYMBOL(sym) sym | ||
| 4 | #else | ||
| 5 | #define PASTE2(x,y) x##y | ||
| 6 | #define PASTE(x,y) PASTE2(x,y) | ||
| 7 | #define ASM_SYMBOL(sym) PASTE(SYMBOL_PREFIX, sym) | ||
| 8 | #endif | ||
| 9 | |||
| 10 | #define GLOBAL(name) \ | ||
| 11 | .globl ASM_SYMBOL(name); \ | ||
| 12 | ASM_SYMBOL(name): | ||
| 13 | |||
| 14 | .section ".init.data","aw" | ||
| 15 | |||
| 16 | GLOBAL(modsign_certificate_list) | ||
| 17 | .incbin "signing_key.x509" | ||
| 18 | .incbin "extra_certificates" | ||
| 19 | GLOBAL(modsign_certificate_list_end) | ||
diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c index 767e559dfb10..045504fffbb2 100644 --- a/kernel/modsign_pubkey.c +++ b/kernel/modsign_pubkey.c | |||
| @@ -20,12 +20,6 @@ struct key *modsign_keyring; | |||
| 20 | 20 | ||
| 21 | extern __initdata const u8 modsign_certificate_list[]; | 21 | extern __initdata const u8 modsign_certificate_list[]; |
| 22 | extern __initdata const u8 modsign_certificate_list_end[]; | 22 | extern __initdata const u8 modsign_certificate_list_end[]; |
| 23 | asm(".section .init.data,\"aw\"\n" | ||
| 24 | SYMBOL_PREFIX "modsign_certificate_list:\n" | ||
| 25 | ".incbin \"signing_key.x509\"\n" | ||
| 26 | ".incbin \"extra_certificates\"\n" | ||
| 27 | SYMBOL_PREFIX "modsign_certificate_list_end:" | ||
| 28 | ); | ||
| 29 | 23 | ||
| 30 | /* | 24 | /* |
| 31 | * We need to make sure ccache doesn't cache the .o file as it doesn't notice | 25 | * We need to make sure ccache doesn't cache the .o file as it doesn't notice |
diff --git a/kernel/module.c b/kernel/module.c index 808bd62e1723..250092c1d57d 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/ftrace_event.h> | 21 | #include <linux/ftrace_event.h> |
| 22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 23 | #include <linux/kallsyms.h> | 23 | #include <linux/kallsyms.h> |
| 24 | #include <linux/file.h> | ||
| 24 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
| 25 | #include <linux/sysfs.h> | 26 | #include <linux/sysfs.h> |
| 26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| @@ -28,6 +29,7 @@ | |||
| 28 | #include <linux/vmalloc.h> | 29 | #include <linux/vmalloc.h> |
| 29 | #include <linux/elf.h> | 30 | #include <linux/elf.h> |
| 30 | #include <linux/proc_fs.h> | 31 | #include <linux/proc_fs.h> |
| 32 | #include <linux/security.h> | ||
| 31 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
| 32 | #include <linux/syscalls.h> | 34 | #include <linux/syscalls.h> |
| 33 | #include <linux/fcntl.h> | 35 | #include <linux/fcntl.h> |
| @@ -59,6 +61,7 @@ | |||
| 59 | #include <linux/pfn.h> | 61 | #include <linux/pfn.h> |
| 60 | #include <linux/bsearch.h> | 62 | #include <linux/bsearch.h> |
| 61 | #include <linux/fips.h> | 63 | #include <linux/fips.h> |
| 64 | #include <uapi/linux/module.h> | ||
| 62 | #include "module-internal.h" | 65 | #include "module-internal.h" |
| 63 | 66 | ||
| 64 | #define CREATE_TRACE_POINTS | 67 | #define CREATE_TRACE_POINTS |
| @@ -2279,7 +2282,7 @@ static void layout_symtab(struct module *mod, struct load_info *info) | |||
| 2279 | Elf_Shdr *symsect = info->sechdrs + info->index.sym; | 2282 | Elf_Shdr *symsect = info->sechdrs + info->index.sym; |
| 2280 | Elf_Shdr *strsect = info->sechdrs + info->index.str; | 2283 | Elf_Shdr *strsect = info->sechdrs + info->index.str; |
| 2281 | const Elf_Sym *src; | 2284 | const Elf_Sym *src; |
| 2282 | unsigned int i, nsrc, ndst, strtab_size; | 2285 | unsigned int i, nsrc, ndst, strtab_size = 0; |
| 2283 | 2286 | ||
| 2284 | /* Put symbol section at end of init part of module. */ | 2287 | /* Put symbol section at end of init part of module. */ |
| 2285 | symsect->sh_flags |= SHF_ALLOC; | 2288 | symsect->sh_flags |= SHF_ALLOC; |
| @@ -2290,9 +2293,6 @@ static void layout_symtab(struct module *mod, struct load_info *info) | |||
| 2290 | src = (void *)info->hdr + symsect->sh_offset; | 2293 | src = (void *)info->hdr + symsect->sh_offset; |
| 2291 | nsrc = symsect->sh_size / sizeof(*src); | 2294 | nsrc = symsect->sh_size / sizeof(*src); |
| 2292 | 2295 | ||
| 2293 | /* strtab always starts with a nul, so offset 0 is the empty string. */ | ||
| 2294 | strtab_size = 1; | ||
| 2295 | |||
| 2296 | /* Compute total space required for the core symbols' strtab. */ | 2296 | /* Compute total space required for the core symbols' strtab. */ |
| 2297 | for (ndst = i = 0; i < nsrc; i++) { | 2297 | for (ndst = i = 0; i < nsrc; i++) { |
| 2298 | if (i == 0 || | 2298 | if (i == 0 || |
| @@ -2334,7 +2334,6 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) | |||
| 2334 | mod->core_symtab = dst = mod->module_core + info->symoffs; | 2334 | mod->core_symtab = dst = mod->module_core + info->symoffs; |
| 2335 | mod->core_strtab = s = mod->module_core + info->stroffs; | 2335 | mod->core_strtab = s = mod->module_core + info->stroffs; |
| 2336 | src = mod->symtab; | 2336 | src = mod->symtab; |
| 2337 | *s++ = 0; | ||
| 2338 | for (ndst = i = 0; i < mod->num_symtab; i++) { | 2337 | for (ndst = i = 0; i < mod->num_symtab; i++) { |
| 2339 | if (i == 0 || | 2338 | if (i == 0 || |
| 2340 | is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { | 2339 | is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { |
| @@ -2375,7 +2374,7 @@ static void dynamic_debug_remove(struct _ddebug *debug) | |||
| 2375 | 2374 | ||
| 2376 | void * __weak module_alloc(unsigned long size) | 2375 | void * __weak module_alloc(unsigned long size) |
| 2377 | { | 2376 | { |
| 2378 | return size == 0 ? NULL : vmalloc_exec(size); | 2377 | return vmalloc_exec(size); |
| 2379 | } | 2378 | } |
| 2380 | 2379 | ||
| 2381 | static void *module_alloc_update_bounds(unsigned long size) | 2380 | static void *module_alloc_update_bounds(unsigned long size) |
| @@ -2422,18 +2421,17 @@ static inline void kmemleak_load_module(const struct module *mod, | |||
| 2422 | #endif | 2421 | #endif |
| 2423 | 2422 | ||
| 2424 | #ifdef CONFIG_MODULE_SIG | 2423 | #ifdef CONFIG_MODULE_SIG |
| 2425 | static int module_sig_check(struct load_info *info, | 2424 | static int module_sig_check(struct load_info *info) |
| 2426 | const void *mod, unsigned long *_len) | ||
| 2427 | { | 2425 | { |
| 2428 | int err = -ENOKEY; | 2426 | int err = -ENOKEY; |
| 2429 | unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; | 2427 | const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; |
| 2430 | unsigned long len = *_len; | 2428 | const void *mod = info->hdr; |
| 2431 | 2429 | ||
| 2432 | if (len > markerlen && | 2430 | if (info->len > markerlen && |
| 2433 | memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { | 2431 | memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { |
| 2434 | /* We truncate the module to discard the signature */ | 2432 | /* We truncate the module to discard the signature */ |
| 2435 | *_len -= markerlen; | 2433 | info->len -= markerlen; |
| 2436 | err = mod_verify_sig(mod, _len); | 2434 | err = mod_verify_sig(mod, &info->len); |
| 2437 | } | 2435 | } |
| 2438 | 2436 | ||
| 2439 | if (!err) { | 2437 | if (!err) { |
| @@ -2451,59 +2449,107 @@ static int module_sig_check(struct load_info *info, | |||
| 2451 | return err; | 2449 | return err; |
| 2452 | } | 2450 | } |
| 2453 | #else /* !CONFIG_MODULE_SIG */ | 2451 | #else /* !CONFIG_MODULE_SIG */ |
| 2454 | static int module_sig_check(struct load_info *info, | 2452 | static int module_sig_check(struct load_info *info) |
| 2455 | void *mod, unsigned long *len) | ||
| 2456 | { | 2453 | { |
| 2457 | return 0; | 2454 | return 0; |
| 2458 | } | 2455 | } |
| 2459 | #endif /* !CONFIG_MODULE_SIG */ | 2456 | #endif /* !CONFIG_MODULE_SIG */ |
| 2460 | 2457 | ||
| 2461 | /* Sets info->hdr, info->len and info->sig_ok. */ | 2458 | /* Sanity checks against invalid binaries, wrong arch, weird elf version. */ |
| 2462 | static int copy_and_check(struct load_info *info, | 2459 | static int elf_header_check(struct load_info *info) |
| 2463 | const void __user *umod, unsigned long len, | 2460 | { |
| 2464 | const char __user *uargs) | 2461 | if (info->len < sizeof(*(info->hdr))) |
| 2462 | return -ENOEXEC; | ||
| 2463 | |||
| 2464 | if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0 | ||
| 2465 | || info->hdr->e_type != ET_REL | ||
| 2466 | || !elf_check_arch(info->hdr) | ||
| 2467 | || info->hdr->e_shentsize != sizeof(Elf_Shdr)) | ||
| 2468 | return -ENOEXEC; | ||
| 2469 | |||
| 2470 | if (info->hdr->e_shoff >= info->len | ||
| 2471 | || (info->hdr->e_shnum * sizeof(Elf_Shdr) > | ||
| 2472 | info->len - info->hdr->e_shoff)) | ||
| 2473 | return -ENOEXEC; | ||
| 2474 | |||
| 2475 | return 0; | ||
| 2476 | } | ||
| 2477 | |||
| 2478 | /* Sets info->hdr and info->len. */ | ||
| 2479 | static int copy_module_from_user(const void __user *umod, unsigned long len, | ||
| 2480 | struct load_info *info) | ||
| 2465 | { | 2481 | { |
| 2466 | int err; | 2482 | int err; |
| 2467 | Elf_Ehdr *hdr; | ||
| 2468 | 2483 | ||
| 2469 | if (len < sizeof(*hdr)) | 2484 | info->len = len; |
| 2485 | if (info->len < sizeof(*(info->hdr))) | ||
| 2470 | return -ENOEXEC; | 2486 | return -ENOEXEC; |
| 2471 | 2487 | ||
| 2488 | err = security_kernel_module_from_file(NULL); | ||
| 2489 | if (err) | ||
| 2490 | return err; | ||
| 2491 | |||
| 2472 | /* Suck in entire file: we'll want most of it. */ | 2492 | /* Suck in entire file: we'll want most of it. */ |
| 2473 | if ((hdr = vmalloc(len)) == NULL) | 2493 | info->hdr = vmalloc(info->len); |
| 2494 | if (!info->hdr) | ||
| 2474 | return -ENOMEM; | 2495 | return -ENOMEM; |
| 2475 | 2496 | ||
| 2476 | if (copy_from_user(hdr, umod, len) != 0) { | 2497 | if (copy_from_user(info->hdr, umod, info->len) != 0) { |
| 2477 | err = -EFAULT; | 2498 | vfree(info->hdr); |
| 2478 | goto free_hdr; | 2499 | return -EFAULT; |
| 2479 | } | 2500 | } |
| 2480 | 2501 | ||
| 2481 | err = module_sig_check(info, hdr, &len); | 2502 | return 0; |
| 2503 | } | ||
| 2504 | |||
| 2505 | /* Sets info->hdr and info->len. */ | ||
| 2506 | static int copy_module_from_fd(int fd, struct load_info *info) | ||
| 2507 | { | ||
| 2508 | struct file *file; | ||
| 2509 | int err; | ||
| 2510 | struct kstat stat; | ||
| 2511 | loff_t pos; | ||
| 2512 | ssize_t bytes = 0; | ||
| 2513 | |||
| 2514 | file = fget(fd); | ||
| 2515 | if (!file) | ||
| 2516 | return -ENOEXEC; | ||
| 2517 | |||
| 2518 | err = security_kernel_module_from_file(file); | ||
| 2482 | if (err) | 2519 | if (err) |
| 2483 | goto free_hdr; | 2520 | goto out; |
| 2484 | 2521 | ||
| 2485 | /* Sanity checks against insmoding binaries or wrong arch, | 2522 | err = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat); |
| 2486 | weird elf version */ | 2523 | if (err) |
| 2487 | if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 | 2524 | goto out; |
| 2488 | || hdr->e_type != ET_REL | ||
| 2489 | || !elf_check_arch(hdr) | ||
| 2490 | || hdr->e_shentsize != sizeof(Elf_Shdr)) { | ||
| 2491 | err = -ENOEXEC; | ||
| 2492 | goto free_hdr; | ||
| 2493 | } | ||
| 2494 | 2525 | ||
| 2495 | if (hdr->e_shoff >= len || | 2526 | if (stat.size > INT_MAX) { |
| 2496 | hdr->e_shnum * sizeof(Elf_Shdr) > len - hdr->e_shoff) { | 2527 | err = -EFBIG; |
| 2497 | err = -ENOEXEC; | 2528 | goto out; |
| 2498 | goto free_hdr; | 2529 | } |
| 2530 | info->hdr = vmalloc(stat.size); | ||
| 2531 | if (!info->hdr) { | ||
| 2532 | err = -ENOMEM; | ||
| 2533 | goto out; | ||
| 2499 | } | 2534 | } |
| 2500 | 2535 | ||
| 2501 | info->hdr = hdr; | 2536 | pos = 0; |
| 2502 | info->len = len; | 2537 | while (pos < stat.size) { |
| 2503 | return 0; | 2538 | bytes = kernel_read(file, pos, (char *)(info->hdr) + pos, |
| 2539 | stat.size - pos); | ||
| 2540 | if (bytes < 0) { | ||
| 2541 | vfree(info->hdr); | ||
| 2542 | err = bytes; | ||
| 2543 | goto out; | ||
| 2544 | } | ||
| 2545 | if (bytes == 0) | ||
| 2546 | break; | ||
| 2547 | pos += bytes; | ||
| 2548 | } | ||
| 2549 | info->len = pos; | ||
| 2504 | 2550 | ||
| 2505 | free_hdr: | 2551 | out: |
| 2506 | vfree(hdr); | 2552 | fput(file); |
| 2507 | return err; | 2553 | return err; |
| 2508 | } | 2554 | } |
| 2509 | 2555 | ||
| @@ -2512,7 +2558,7 @@ static void free_copy(struct load_info *info) | |||
| 2512 | vfree(info->hdr); | 2558 | vfree(info->hdr); |
| 2513 | } | 2559 | } |
| 2514 | 2560 | ||
| 2515 | static int rewrite_section_headers(struct load_info *info) | 2561 | static int rewrite_section_headers(struct load_info *info, int flags) |
| 2516 | { | 2562 | { |
| 2517 | unsigned int i; | 2563 | unsigned int i; |
| 2518 | 2564 | ||
| @@ -2540,7 +2586,10 @@ static int rewrite_section_headers(struct load_info *info) | |||
| 2540 | } | 2586 | } |
| 2541 | 2587 | ||
| 2542 | /* Track but don't keep modinfo and version sections. */ | 2588 | /* Track but don't keep modinfo and version sections. */ |
| 2543 | info->index.vers = find_sec(info, "__versions"); | 2589 | if (flags & MODULE_INIT_IGNORE_MODVERSIONS) |
| 2590 | info->index.vers = 0; /* Pretend no __versions section! */ | ||
| 2591 | else | ||
| 2592 | info->index.vers = find_sec(info, "__versions"); | ||
| 2544 | info->index.info = find_sec(info, ".modinfo"); | 2593 | info->index.info = find_sec(info, ".modinfo"); |
| 2545 | info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2594 | info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2546 | info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2595 | info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| @@ -2555,7 +2604,7 @@ static int rewrite_section_headers(struct load_info *info) | |||
| 2555 | * Return the temporary module pointer (we'll replace it with the final | 2604 | * Return the temporary module pointer (we'll replace it with the final |
| 2556 | * one when we move the module sections around). | 2605 | * one when we move the module sections around). |
| 2557 | */ | 2606 | */ |
| 2558 | static struct module *setup_load_info(struct load_info *info) | 2607 | static struct module *setup_load_info(struct load_info *info, int flags) |
| 2559 | { | 2608 | { |
| 2560 | unsigned int i; | 2609 | unsigned int i; |
| 2561 | int err; | 2610 | int err; |
| @@ -2566,7 +2615,7 @@ static struct module *setup_load_info(struct load_info *info) | |||
| 2566 | info->secstrings = (void *)info->hdr | 2615 | info->secstrings = (void *)info->hdr |
| 2567 | + info->sechdrs[info->hdr->e_shstrndx].sh_offset; | 2616 | + info->sechdrs[info->hdr->e_shstrndx].sh_offset; |
| 2568 | 2617 | ||
| 2569 | err = rewrite_section_headers(info); | 2618 | err = rewrite_section_headers(info, flags); |
| 2570 | if (err) | 2619 | if (err) |
| 2571 | return ERR_PTR(err); | 2620 | return ERR_PTR(err); |
| 2572 | 2621 | ||
| @@ -2604,11 +2653,14 @@ static struct module *setup_load_info(struct load_info *info) | |||
| 2604 | return mod; | 2653 | return mod; |
| 2605 | } | 2654 | } |
| 2606 | 2655 | ||
| 2607 | static int check_modinfo(struct module *mod, struct load_info *info) | 2656 | static int check_modinfo(struct module *mod, struct load_info *info, int flags) |
| 2608 | { | 2657 | { |
| 2609 | const char *modmagic = get_modinfo(info, "vermagic"); | 2658 | const char *modmagic = get_modinfo(info, "vermagic"); |
| 2610 | int err; | 2659 | int err; |
| 2611 | 2660 | ||
| 2661 | if (flags & MODULE_INIT_IGNORE_VERMAGIC) | ||
| 2662 | modmagic = NULL; | ||
| 2663 | |||
| 2612 | /* This is allowed: modprobe --force will invalidate it. */ | 2664 | /* This is allowed: modprobe --force will invalidate it. */ |
| 2613 | if (!modmagic) { | 2665 | if (!modmagic) { |
| 2614 | err = try_to_force_load(mod, "bad vermagic"); | 2666 | err = try_to_force_load(mod, "bad vermagic"); |
| @@ -2738,20 +2790,23 @@ static int move_module(struct module *mod, struct load_info *info) | |||
| 2738 | memset(ptr, 0, mod->core_size); | 2790 | memset(ptr, 0, mod->core_size); |
| 2739 | mod->module_core = ptr; | 2791 | mod->module_core = ptr; |
| 2740 | 2792 | ||
| 2741 | ptr = module_alloc_update_bounds(mod->init_size); | 2793 | if (mod->init_size) { |
| 2742 | /* | 2794 | ptr = module_alloc_update_bounds(mod->init_size); |
| 2743 | * The pointer to this block is stored in the module structure | 2795 | /* |
| 2744 | * which is inside the block. This block doesn't need to be | 2796 | * The pointer to this block is stored in the module structure |
| 2745 | * scanned as it contains data and code that will be freed | 2797 | * which is inside the block. This block doesn't need to be |
| 2746 | * after the module is initialized. | 2798 | * scanned as it contains data and code that will be freed |
| 2747 | */ | 2799 | * after the module is initialized. |
| 2748 | kmemleak_ignore(ptr); | 2800 | */ |
| 2749 | if (!ptr && mod->init_size) { | 2801 | kmemleak_ignore(ptr); |
| 2750 | module_free(mod, mod->module_core); | 2802 | if (!ptr) { |
| 2751 | return -ENOMEM; | 2803 | module_free(mod, mod->module_core); |
| 2752 | } | 2804 | return -ENOMEM; |
| 2753 | memset(ptr, 0, mod->init_size); | 2805 | } |
| 2754 | mod->module_init = ptr; | 2806 | memset(ptr, 0, mod->init_size); |
| 2807 | mod->module_init = ptr; | ||
| 2808 | } else | ||
| 2809 | mod->module_init = NULL; | ||
| 2755 | 2810 | ||
| 2756 | /* Transfer each section which specifies SHF_ALLOC */ | 2811 | /* Transfer each section which specifies SHF_ALLOC */ |
| 2757 | pr_debug("final section addresses:\n"); | 2812 | pr_debug("final section addresses:\n"); |
| @@ -2844,18 +2899,18 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr, | |||
| 2844 | return 0; | 2899 | return 0; |
| 2845 | } | 2900 | } |
| 2846 | 2901 | ||
| 2847 | static struct module *layout_and_allocate(struct load_info *info) | 2902 | static struct module *layout_and_allocate(struct load_info *info, int flags) |
| 2848 | { | 2903 | { |
| 2849 | /* Module within temporary copy. */ | 2904 | /* Module within temporary copy. */ |
| 2850 | struct module *mod; | 2905 | struct module *mod; |
| 2851 | Elf_Shdr *pcpusec; | 2906 | Elf_Shdr *pcpusec; |
| 2852 | int err; | 2907 | int err; |
| 2853 | 2908 | ||
| 2854 | mod = setup_load_info(info); | 2909 | mod = setup_load_info(info, flags); |
| 2855 | if (IS_ERR(mod)) | 2910 | if (IS_ERR(mod)) |
| 2856 | return mod; | 2911 | return mod; |
| 2857 | 2912 | ||
| 2858 | err = check_modinfo(mod, info); | 2913 | err = check_modinfo(mod, info, flags); |
| 2859 | if (err) | 2914 | if (err) |
| 2860 | return ERR_PTR(err); | 2915 | return ERR_PTR(err); |
| 2861 | 2916 | ||
| @@ -2942,33 +2997,124 @@ static bool finished_loading(const char *name) | |||
| 2942 | return ret; | 2997 | return ret; |
| 2943 | } | 2998 | } |
| 2944 | 2999 | ||
| 3000 | /* Call module constructors. */ | ||
| 3001 | static void do_mod_ctors(struct module *mod) | ||
| 3002 | { | ||
| 3003 | #ifdef CONFIG_CONSTRUCTORS | ||
| 3004 | unsigned long i; | ||
| 3005 | |||
| 3006 | for (i = 0; i < mod->num_ctors; i++) | ||
| 3007 | mod->ctors[i](); | ||
| 3008 | #endif | ||
| 3009 | } | ||
| 3010 | |||
| 3011 | /* This is where the real work happens */ | ||
| 3012 | static int do_init_module(struct module *mod) | ||
| 3013 | { | ||
| 3014 | int ret = 0; | ||
| 3015 | |||
| 3016 | blocking_notifier_call_chain(&module_notify_list, | ||
| 3017 | MODULE_STATE_COMING, mod); | ||
| 3018 | |||
| 3019 | /* Set RO and NX regions for core */ | ||
| 3020 | set_section_ro_nx(mod->module_core, | ||
| 3021 | mod->core_text_size, | ||
| 3022 | mod->core_ro_size, | ||
| 3023 | mod->core_size); | ||
| 3024 | |||
| 3025 | /* Set RO and NX regions for init */ | ||
| 3026 | set_section_ro_nx(mod->module_init, | ||
| 3027 | mod->init_text_size, | ||
| 3028 | mod->init_ro_size, | ||
| 3029 | mod->init_size); | ||
| 3030 | |||
| 3031 | do_mod_ctors(mod); | ||
| 3032 | /* Start the module */ | ||
| 3033 | if (mod->init != NULL) | ||
| 3034 | ret = do_one_initcall(mod->init); | ||
| 3035 | if (ret < 0) { | ||
| 3036 | /* Init routine failed: abort. Try to protect us from | ||
| 3037 | buggy refcounters. */ | ||
| 3038 | mod->state = MODULE_STATE_GOING; | ||
| 3039 | synchronize_sched(); | ||
| 3040 | module_put(mod); | ||
| 3041 | blocking_notifier_call_chain(&module_notify_list, | ||
| 3042 | MODULE_STATE_GOING, mod); | ||
| 3043 | free_module(mod); | ||
| 3044 | wake_up_all(&module_wq); | ||
| 3045 | return ret; | ||
| 3046 | } | ||
| 3047 | if (ret > 0) { | ||
| 3048 | printk(KERN_WARNING | ||
| 3049 | "%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n" | ||
| 3050 | "%s: loading module anyway...\n", | ||
| 3051 | __func__, mod->name, ret, | ||
| 3052 | __func__); | ||
| 3053 | dump_stack(); | ||
| 3054 | } | ||
| 3055 | |||
| 3056 | /* Now it's a first class citizen! */ | ||
| 3057 | mod->state = MODULE_STATE_LIVE; | ||
| 3058 | blocking_notifier_call_chain(&module_notify_list, | ||
| 3059 | MODULE_STATE_LIVE, mod); | ||
| 3060 | |||
| 3061 | /* We need to finish all async code before the module init sequence is done */ | ||
| 3062 | async_synchronize_full(); | ||
| 3063 | |||
| 3064 | mutex_lock(&module_mutex); | ||
| 3065 | /* Drop initial reference. */ | ||
| 3066 | module_put(mod); | ||
| 3067 | trim_init_extable(mod); | ||
| 3068 | #ifdef CONFIG_KALLSYMS | ||
| 3069 | mod->num_symtab = mod->core_num_syms; | ||
| 3070 | mod->symtab = mod->core_symtab; | ||
| 3071 | mod->strtab = mod->core_strtab; | ||
| 3072 | #endif | ||
| 3073 | unset_module_init_ro_nx(mod); | ||
| 3074 | module_free(mod, mod->module_init); | ||
| 3075 | mod->module_init = NULL; | ||
| 3076 | mod->init_size = 0; | ||
| 3077 | mod->init_ro_size = 0; | ||
| 3078 | mod->init_text_size = 0; | ||
| 3079 | mutex_unlock(&module_mutex); | ||
| 3080 | wake_up_all(&module_wq); | ||
| 3081 | |||
| 3082 | return 0; | ||
| 3083 | } | ||
| 3084 | |||
| 3085 | static int may_init_module(void) | ||
| 3086 | { | ||
| 3087 | if (!capable(CAP_SYS_MODULE) || modules_disabled) | ||
| 3088 | return -EPERM; | ||
| 3089 | |||
| 3090 | return 0; | ||
| 3091 | } | ||
| 3092 | |||
| 2945 | /* Allocate and load the module: note that size of section 0 is always | 3093 | /* Allocate and load the module: note that size of section 0 is always |
| 2946 | zero, and we rely on this for optional sections. */ | 3094 | zero, and we rely on this for optional sections. */ |
| 2947 | static struct module *load_module(void __user *umod, | 3095 | static int load_module(struct load_info *info, const char __user *uargs, |
| 2948 | unsigned long len, | 3096 | int flags) |
| 2949 | const char __user *uargs) | ||
| 2950 | { | 3097 | { |
| 2951 | struct load_info info = { NULL, }; | ||
| 2952 | struct module *mod, *old; | 3098 | struct module *mod, *old; |
| 2953 | long err; | 3099 | long err; |
| 2954 | 3100 | ||
| 2955 | pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n", | 3101 | err = module_sig_check(info); |
| 2956 | umod, len, uargs); | 3102 | if (err) |
| 3103 | goto free_copy; | ||
| 2957 | 3104 | ||
| 2958 | /* Copy in the blobs from userspace, check they are vaguely sane. */ | 3105 | err = elf_header_check(info); |
| 2959 | err = copy_and_check(&info, umod, len, uargs); | ||
| 2960 | if (err) | 3106 | if (err) |
| 2961 | return ERR_PTR(err); | 3107 | goto free_copy; |
| 2962 | 3108 | ||
| 2963 | /* Figure out module layout, and allocate all the memory. */ | 3109 | /* Figure out module layout, and allocate all the memory. */ |
| 2964 | mod = layout_and_allocate(&info); | 3110 | mod = layout_and_allocate(info, flags); |
| 2965 | if (IS_ERR(mod)) { | 3111 | if (IS_ERR(mod)) { |
| 2966 | err = PTR_ERR(mod); | 3112 | err = PTR_ERR(mod); |
| 2967 | goto free_copy; | 3113 | goto free_copy; |
| 2968 | } | 3114 | } |
| 2969 | 3115 | ||
| 2970 | #ifdef CONFIG_MODULE_SIG | 3116 | #ifdef CONFIG_MODULE_SIG |
| 2971 | mod->sig_ok = info.sig_ok; | 3117 | mod->sig_ok = info->sig_ok; |
| 2972 | if (!mod->sig_ok) | 3118 | if (!mod->sig_ok) |
| 2973 | add_taint_module(mod, TAINT_FORCED_MODULE); | 3119 | add_taint_module(mod, TAINT_FORCED_MODULE); |
| 2974 | #endif | 3120 | #endif |
| @@ -2980,25 +3126,25 @@ static struct module *load_module(void __user *umod, | |||
| 2980 | 3126 | ||
| 2981 | /* Now we've got everything in the final locations, we can | 3127 | /* Now we've got everything in the final locations, we can |
| 2982 | * find optional sections. */ | 3128 | * find optional sections. */ |
| 2983 | find_module_sections(mod, &info); | 3129 | find_module_sections(mod, info); |
| 2984 | 3130 | ||
| 2985 | err = check_module_license_and_versions(mod); | 3131 | err = check_module_license_and_versions(mod); |
| 2986 | if (err) | 3132 | if (err) |
| 2987 | goto free_unload; | 3133 | goto free_unload; |
| 2988 | 3134 | ||
| 2989 | /* Set up MODINFO_ATTR fields */ | 3135 | /* Set up MODINFO_ATTR fields */ |
| 2990 | setup_modinfo(mod, &info); | 3136 | setup_modinfo(mod, info); |
| 2991 | 3137 | ||
| 2992 | /* Fix up syms, so that st_value is a pointer to location. */ | 3138 | /* Fix up syms, so that st_value is a pointer to location. */ |
| 2993 | err = simplify_symbols(mod, &info); | 3139 | err = simplify_symbols(mod, info); |
| 2994 | if (err < 0) | 3140 | if (err < 0) |
| 2995 | goto free_modinfo; | 3141 | goto free_modinfo; |
| 2996 | 3142 | ||
| 2997 | err = apply_relocations(mod, &info); | 3143 | err = apply_relocations(mod, info); |
| 2998 | if (err < 0) | 3144 | if (err < 0) |
| 2999 | goto free_modinfo; | 3145 | goto free_modinfo; |
| 3000 | 3146 | ||
| 3001 | err = post_relocation(mod, &info); | 3147 | err = post_relocation(mod, info); |
| 3002 | if (err < 0) | 3148 | if (err < 0) |
| 3003 | goto free_modinfo; | 3149 | goto free_modinfo; |
| 3004 | 3150 | ||
| @@ -3038,14 +3184,14 @@ again: | |||
| 3038 | } | 3184 | } |
| 3039 | 3185 | ||
| 3040 | /* This has to be done once we're sure module name is unique. */ | 3186 | /* This has to be done once we're sure module name is unique. */ |
| 3041 | dynamic_debug_setup(info.debug, info.num_debug); | 3187 | dynamic_debug_setup(info->debug, info->num_debug); |
| 3042 | 3188 | ||
| 3043 | /* Find duplicate symbols */ | 3189 | /* Find duplicate symbols */ |
| 3044 | err = verify_export_symbols(mod); | 3190 | err = verify_export_symbols(mod); |
| 3045 | if (err < 0) | 3191 | if (err < 0) |
| 3046 | goto ddebug; | 3192 | goto ddebug; |
| 3047 | 3193 | ||
| 3048 | module_bug_finalize(info.hdr, info.sechdrs, mod); | 3194 | module_bug_finalize(info->hdr, info->sechdrs, mod); |
| 3049 | list_add_rcu(&mod->list, &modules); | 3195 | list_add_rcu(&mod->list, &modules); |
| 3050 | mutex_unlock(&module_mutex); | 3196 | mutex_unlock(&module_mutex); |
| 3051 | 3197 | ||
| @@ -3056,16 +3202,17 @@ again: | |||
| 3056 | goto unlink; | 3202 | goto unlink; |
| 3057 | 3203 | ||
| 3058 | /* Link in to syfs. */ | 3204 | /* Link in to syfs. */ |
| 3059 | err = mod_sysfs_setup(mod, &info, mod->kp, mod->num_kp); | 3205 | err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp); |
| 3060 | if (err < 0) | 3206 | if (err < 0) |
| 3061 | goto unlink; | 3207 | goto unlink; |
| 3062 | 3208 | ||
| 3063 | /* Get rid of temporary copy. */ | 3209 | /* Get rid of temporary copy. */ |
| 3064 | free_copy(&info); | 3210 | free_copy(info); |
| 3065 | 3211 | ||
| 3066 | /* Done! */ | 3212 | /* Done! */ |
| 3067 | trace_module_load(mod); | 3213 | trace_module_load(mod); |
| 3068 | return mod; | 3214 | |
| 3215 | return do_init_module(mod); | ||
| 3069 | 3216 | ||
| 3070 | unlink: | 3217 | unlink: |
| 3071 | mutex_lock(&module_mutex); | 3218 | mutex_lock(&module_mutex); |
| @@ -3074,7 +3221,7 @@ again: | |||
| 3074 | module_bug_cleanup(mod); | 3221 | module_bug_cleanup(mod); |
| 3075 | wake_up_all(&module_wq); | 3222 | wake_up_all(&module_wq); |
| 3076 | ddebug: | 3223 | ddebug: |
| 3077 | dynamic_debug_remove(info.debug); | 3224 | dynamic_debug_remove(info->debug); |
| 3078 | unlock: | 3225 | unlock: |
| 3079 | mutex_unlock(&module_mutex); | 3226 | mutex_unlock(&module_mutex); |
| 3080 | synchronize_sched(); | 3227 | synchronize_sched(); |
| @@ -3086,106 +3233,52 @@ again: | |||
| 3086 | free_unload: | 3233 | free_unload: |
| 3087 | module_unload_free(mod); | 3234 | module_unload_free(mod); |
| 3088 | free_module: | 3235 | free_module: |
| 3089 | module_deallocate(mod, &info); | 3236 | module_deallocate(mod, info); |
| 3090 | free_copy: | 3237 | free_copy: |
| 3091 | free_copy(&info); | 3238 | free_copy(info); |
| 3092 | return ERR_PTR(err); | 3239 | return err; |
| 3093 | } | ||
| 3094 | |||
| 3095 | /* Call module constructors. */ | ||
| 3096 | static void do_mod_ctors(struct module *mod) | ||
| 3097 | { | ||
| 3098 | #ifdef CONFIG_CONSTRUCTORS | ||
| 3099 | unsigned long i; | ||
| 3100 | |||
| 3101 | for (i = 0; i < mod->num_ctors; i++) | ||
| 3102 | mod->ctors[i](); | ||
| 3103 | #endif | ||
| 3104 | } | 3240 | } |
| 3105 | 3241 | ||
| 3106 | /* This is where the real work happens */ | ||
| 3107 | SYSCALL_DEFINE3(init_module, void __user *, umod, | 3242 | SYSCALL_DEFINE3(init_module, void __user *, umod, |
| 3108 | unsigned long, len, const char __user *, uargs) | 3243 | unsigned long, len, const char __user *, uargs) |
| 3109 | { | 3244 | { |
| 3110 | struct module *mod; | 3245 | int err; |
| 3111 | int ret = 0; | 3246 | struct load_info info = { }; |
| 3112 | 3247 | ||
| 3113 | /* Must have permission */ | 3248 | err = may_init_module(); |
| 3114 | if (!capable(CAP_SYS_MODULE) || modules_disabled) | 3249 | if (err) |
| 3115 | return -EPERM; | 3250 | return err; |
| 3116 | 3251 | ||
| 3117 | /* Do all the hard work */ | 3252 | pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n", |
| 3118 | mod = load_module(umod, len, uargs); | 3253 | umod, len, uargs); |
| 3119 | if (IS_ERR(mod)) | ||
| 3120 | return PTR_ERR(mod); | ||
| 3121 | 3254 | ||
| 3122 | blocking_notifier_call_chain(&module_notify_list, | 3255 | err = copy_module_from_user(umod, len, &info); |
| 3123 | MODULE_STATE_COMING, mod); | 3256 | if (err) |
| 3257 | return err; | ||
| 3124 | 3258 | ||
| 3125 | /* Set RO and NX regions for core */ | 3259 | return load_module(&info, uargs, 0); |
| 3126 | set_section_ro_nx(mod->module_core, | 3260 | } |
| 3127 | mod->core_text_size, | ||
| 3128 | mod->core_ro_size, | ||
| 3129 | mod->core_size); | ||
| 3130 | 3261 | ||
| 3131 | /* Set RO and NX regions for init */ | 3262 | SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags) |
| 3132 | set_section_ro_nx(mod->module_init, | 3263 | { |
| 3133 | mod->init_text_size, | 3264 | int err; |
| 3134 | mod->init_ro_size, | 3265 | struct load_info info = { }; |
| 3135 | mod->init_size); | ||
| 3136 | 3266 | ||
| 3137 | do_mod_ctors(mod); | 3267 | err = may_init_module(); |
| 3138 | /* Start the module */ | 3268 | if (err) |
| 3139 | if (mod->init != NULL) | 3269 | return err; |
| 3140 | ret = do_one_initcall(mod->init); | ||
| 3141 | if (ret < 0) { | ||
| 3142 | /* Init routine failed: abort. Try to protect us from | ||
| 3143 | buggy refcounters. */ | ||
| 3144 | mod->state = MODULE_STATE_GOING; | ||
| 3145 | synchronize_sched(); | ||
| 3146 | module_put(mod); | ||
| 3147 | blocking_notifier_call_chain(&module_notify_list, | ||
| 3148 | MODULE_STATE_GOING, mod); | ||
| 3149 | free_module(mod); | ||
| 3150 | wake_up_all(&module_wq); | ||
| 3151 | return ret; | ||
| 3152 | } | ||
| 3153 | if (ret > 0) { | ||
| 3154 | printk(KERN_WARNING | ||
| 3155 | "%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n" | ||
| 3156 | "%s: loading module anyway...\n", | ||
| 3157 | __func__, mod->name, ret, | ||
| 3158 | __func__); | ||
| 3159 | dump_stack(); | ||
| 3160 | } | ||
| 3161 | 3270 | ||
| 3162 | /* Now it's a first class citizen! */ | 3271 | pr_debug("finit_module: fd=%d, uargs=%p, flags=%i\n", fd, uargs, flags); |
| 3163 | mod->state = MODULE_STATE_LIVE; | ||
| 3164 | blocking_notifier_call_chain(&module_notify_list, | ||
| 3165 | MODULE_STATE_LIVE, mod); | ||
| 3166 | 3272 | ||
| 3167 | /* We need to finish all async code before the module init sequence is done */ | 3273 | if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS |
| 3168 | async_synchronize_full(); | 3274 | |MODULE_INIT_IGNORE_VERMAGIC)) |
| 3275 | return -EINVAL; | ||
| 3169 | 3276 | ||
| 3170 | mutex_lock(&module_mutex); | 3277 | err = copy_module_from_fd(fd, &info); |
| 3171 | /* Drop initial reference. */ | 3278 | if (err) |
| 3172 | module_put(mod); | 3279 | return err; |
| 3173 | trim_init_extable(mod); | ||
| 3174 | #ifdef CONFIG_KALLSYMS | ||
| 3175 | mod->num_symtab = mod->core_num_syms; | ||
| 3176 | mod->symtab = mod->core_symtab; | ||
| 3177 | mod->strtab = mod->core_strtab; | ||
| 3178 | #endif | ||
| 3179 | unset_module_init_ro_nx(mod); | ||
| 3180 | module_free(mod, mod->module_init); | ||
| 3181 | mod->module_init = NULL; | ||
| 3182 | mod->init_size = 0; | ||
| 3183 | mod->init_ro_size = 0; | ||
| 3184 | mod->init_text_size = 0; | ||
| 3185 | mutex_unlock(&module_mutex); | ||
| 3186 | wake_up_all(&module_wq); | ||
| 3187 | 3280 | ||
| 3188 | return 0; | 3281 | return load_module(&info, uargs, flags); |
| 3189 | } | 3282 | } |
| 3190 | 3283 | ||
| 3191 | static inline int within(unsigned long addr, void *start, unsigned long size) | 3284 | static inline int within(unsigned long addr, void *start, unsigned long size) |
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index dbff751e4086..395084d4ce16 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
| @@ -25,6 +25,7 @@ cond_syscall(sys_swapoff); | |||
| 25 | cond_syscall(sys_kexec_load); | 25 | cond_syscall(sys_kexec_load); |
| 26 | cond_syscall(compat_sys_kexec_load); | 26 | cond_syscall(compat_sys_kexec_load); |
| 27 | cond_syscall(sys_init_module); | 27 | cond_syscall(sys_init_module); |
| 28 | cond_syscall(sys_finit_module); | ||
| 28 | cond_syscall(sys_delete_module); | 29 | cond_syscall(sys_delete_module); |
| 29 | cond_syscall(sys_socketpair); | 30 | cond_syscall(sys_socketpair); |
| 30 | cond_syscall(sys_bind); | 31 | cond_syscall(sys_bind); |
diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index 5293d2433029..11b9b01fda6b 100644 --- a/lib/asn1_decoder.c +++ b/lib/asn1_decoder.c | |||
| @@ -81,7 +81,7 @@ next_tag: | |||
| 81 | goto next_tag; | 81 | goto next_tag; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | if (unlikely((tag & 0x1f) == 0x1f)) { | 84 | if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) { |
| 85 | do { | 85 | do { |
| 86 | if (unlikely(datalen - dp < 2)) | 86 | if (unlikely(datalen - dp < 2)) |
| 87 | goto data_overrun_error; | 87 | goto data_overrun_error; |
| @@ -96,7 +96,7 @@ next_tag: | |||
| 96 | goto next_tag; | 96 | goto next_tag; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | if (unlikely(len == 0x80)) { | 99 | if (unlikely(len == ASN1_INDEFINITE_LENGTH)) { |
| 100 | /* Indefinite length */ | 100 | /* Indefinite length */ |
| 101 | if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) | 101 | if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) |
| 102 | goto indefinite_len_primitive; | 102 | goto indefinite_len_primitive; |
| @@ -222,7 +222,7 @@ next_op: | |||
| 222 | if (unlikely(dp >= datalen - 1)) | 222 | if (unlikely(dp >= datalen - 1)) |
| 223 | goto data_overrun_error; | 223 | goto data_overrun_error; |
| 224 | tag = data[dp++]; | 224 | tag = data[dp++]; |
| 225 | if (unlikely((tag & 0x1f) == 0x1f)) | 225 | if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) |
| 226 | goto long_tag_not_supported; | 226 | goto long_tag_not_supported; |
| 227 | 227 | ||
| 228 | if (op & ASN1_OP_MATCH__ANY) { | 228 | if (op & ASN1_OP_MATCH__ANY) { |
| @@ -254,7 +254,7 @@ next_op: | |||
| 254 | 254 | ||
| 255 | len = data[dp++]; | 255 | len = data[dp++]; |
| 256 | if (len > 0x7f) { | 256 | if (len > 0x7f) { |
| 257 | if (unlikely(len == 0x80)) { | 257 | if (unlikely(len == ASN1_INDEFINITE_LENGTH)) { |
| 258 | /* Indefinite length */ | 258 | /* Indefinite length */ |
| 259 | if (unlikely(!(tag & ASN1_CONS_BIT))) | 259 | if (unlikely(!(tag & ASN1_CONS_BIT))) |
| 260 | goto indefinite_len_primitive; | 260 | goto indefinite_len_primitive; |
diff --git a/scripts/Makefile.modsign b/scripts/Makefile.modsign new file mode 100644 index 000000000000..abfda626dbad --- /dev/null +++ b/scripts/Makefile.modsign | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | # ========================================================================== | ||
| 2 | # Signing modules | ||
| 3 | # ========================================================================== | ||
| 4 | |||
| 5 | PHONY := __modsign | ||
| 6 | __modsign: | ||
| 7 | |||
| 8 | include scripts/Kbuild.include | ||
| 9 | |||
| 10 | __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) | ||
| 11 | modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) | ||
| 12 | |||
| 13 | PHONY += $(modules) | ||
| 14 | __modsign: $(modules) | ||
| 15 | @: | ||
| 16 | |||
| 17 | quiet_cmd_sign_ko = SIGN [M] $(2)/$(notdir $@) | ||
| 18 | cmd_sign_ko = $(mod_sign_cmd) $(2)/$(notdir $@) | ||
| 19 | |||
| 20 | # Modules built outside the kernel source tree go into extra by default | ||
| 21 | INSTALL_MOD_DIR ?= extra | ||
| 22 | ext-mod-dir = $(INSTALL_MOD_DIR)$(subst $(patsubst %/,%,$(KBUILD_EXTMOD)),,$(@D)) | ||
| 23 | |||
| 24 | modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) | ||
| 25 | |||
| 26 | $(modules): | ||
| 27 | $(call cmd,sign_ko,$(MODLIB)/$(modinst_dir)) | ||
| 28 | |||
| 29 | # Declare the contents of the .PHONY variable as phony. We keep that | ||
| 30 | # information in a variable se we can use it in if_changed and friends. | ||
| 31 | |||
| 32 | .PHONY: $(PHONY) | ||
diff --git a/security/capability.c b/security/capability.c index b14a30c234b8..0fe5a026aef8 100644 --- a/security/capability.c +++ b/security/capability.c | |||
| @@ -395,6 +395,11 @@ static int cap_kernel_module_request(char *kmod_name) | |||
| 395 | return 0; | 395 | return 0; |
| 396 | } | 396 | } |
| 397 | 397 | ||
| 398 | static int cap_kernel_module_from_file(struct file *file) | ||
| 399 | { | ||
| 400 | return 0; | ||
| 401 | } | ||
| 402 | |||
| 398 | static int cap_task_setpgid(struct task_struct *p, pid_t pgid) | 403 | static int cap_task_setpgid(struct task_struct *p, pid_t pgid) |
| 399 | { | 404 | { |
| 400 | return 0; | 405 | return 0; |
| @@ -967,6 +972,7 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
| 967 | set_to_cap_if_null(ops, kernel_act_as); | 972 | set_to_cap_if_null(ops, kernel_act_as); |
| 968 | set_to_cap_if_null(ops, kernel_create_files_as); | 973 | set_to_cap_if_null(ops, kernel_create_files_as); |
| 969 | set_to_cap_if_null(ops, kernel_module_request); | 974 | set_to_cap_if_null(ops, kernel_module_request); |
| 975 | set_to_cap_if_null(ops, kernel_module_from_file); | ||
| 970 | set_to_cap_if_null(ops, task_fix_setuid); | 976 | set_to_cap_if_null(ops, task_fix_setuid); |
| 971 | set_to_cap_if_null(ops, task_setpgid); | 977 | set_to_cap_if_null(ops, task_setpgid); |
| 972 | set_to_cap_if_null(ops, task_getpgid); | 978 | set_to_cap_if_null(ops, task_getpgid); |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 6ee8826662cc..3b2adb794f15 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
| @@ -127,7 +127,7 @@ struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); | |||
| 127 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | 127 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); |
| 128 | 128 | ||
| 129 | /* IMA policy related functions */ | 129 | /* IMA policy related functions */ |
| 130 | enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, POST_SETATTR }; | 130 | enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, MODULE_CHECK, POST_SETATTR }; |
| 131 | 131 | ||
| 132 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, | 132 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, |
| 133 | int flags); | 133 | int flags); |
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index b356884fb3ef..0cea3db21657 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
| @@ -100,12 +100,12 @@ err_out: | |||
| 100 | * ima_get_action - appraise & measure decision based on policy. | 100 | * ima_get_action - appraise & measure decision based on policy. |
| 101 | * @inode: pointer to inode to measure | 101 | * @inode: pointer to inode to measure |
| 102 | * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) | 102 | * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) |
| 103 | * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP) | 103 | * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP, MODULE_CHECK) |
| 104 | * | 104 | * |
| 105 | * The policy is defined in terms of keypairs: | 105 | * The policy is defined in terms of keypairs: |
| 106 | * subj=, obj=, type=, func=, mask=, fsmagic= | 106 | * subj=, obj=, type=, func=, mask=, fsmagic= |
| 107 | * subj,obj, and type: are LSM specific. | 107 | * subj,obj, and type: are LSM specific. |
| 108 | * func: FILE_CHECK | BPRM_CHECK | FILE_MMAP | 108 | * func: FILE_CHECK | BPRM_CHECK | FILE_MMAP | MODULE_CHECK |
| 109 | * mask: contains the permission mask | 109 | * mask: contains the permission mask |
| 110 | * fsmagic: hex value | 110 | * fsmagic: hex value |
| 111 | * | 111 | * |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 73c9a268253e..45de18e9a6f2 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
| @@ -280,6 +280,27 @@ int ima_file_check(struct file *file, int mask) | |||
| 280 | } | 280 | } |
| 281 | EXPORT_SYMBOL_GPL(ima_file_check); | 281 | EXPORT_SYMBOL_GPL(ima_file_check); |
| 282 | 282 | ||
| 283 | /** | ||
| 284 | * ima_module_check - based on policy, collect/store/appraise measurement. | ||
| 285 | * @file: pointer to the file to be measured/appraised | ||
| 286 | * | ||
| 287 | * Measure/appraise kernel modules based on policy. | ||
| 288 | * | ||
| 289 | * Always return 0 and audit dentry_open failures. | ||
| 290 | * Return code is based upon measurement appraisal. | ||
| 291 | */ | ||
| 292 | int ima_module_check(struct file *file) | ||
| 293 | { | ||
| 294 | int rc; | ||
| 295 | |||
| 296 | if (!file) | ||
| 297 | rc = INTEGRITY_UNKNOWN; | ||
| 298 | else | ||
| 299 | rc = process_measurement(file, file->f_dentry->d_name.name, | ||
| 300 | MAY_EXEC, MODULE_CHECK); | ||
| 301 | return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0; | ||
| 302 | } | ||
| 303 | |||
| 283 | static int __init init_ima(void) | 304 | static int __init init_ima(void) |
| 284 | { | 305 | { |
| 285 | int error; | 306 | int error; |
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index c7dacd2eab7a..af7d182d5a46 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
| @@ -80,6 +80,7 @@ static struct ima_rule_entry default_rules[] = { | |||
| 80 | .flags = IMA_FUNC | IMA_MASK}, | 80 | .flags = IMA_FUNC | IMA_MASK}, |
| 81 | {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = GLOBAL_ROOT_UID, | 81 | {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = GLOBAL_ROOT_UID, |
| 82 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, | 82 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, |
| 83 | {.action = MEASURE,.func = MODULE_CHECK, .flags = IMA_FUNC}, | ||
| 83 | }; | 84 | }; |
| 84 | 85 | ||
| 85 | static struct ima_rule_entry default_appraise_rules[] = { | 86 | static struct ima_rule_entry default_appraise_rules[] = { |
| @@ -401,6 +402,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
| 401 | /* PATH_CHECK is for backwards compat */ | 402 | /* PATH_CHECK is for backwards compat */ |
| 402 | else if (strcmp(args[0].from, "PATH_CHECK") == 0) | 403 | else if (strcmp(args[0].from, "PATH_CHECK") == 0) |
| 403 | entry->func = FILE_CHECK; | 404 | entry->func = FILE_CHECK; |
| 405 | else if (strcmp(args[0].from, "MODULE_CHECK") == 0) | ||
| 406 | entry->func = MODULE_CHECK; | ||
| 404 | else if (strcmp(args[0].from, "FILE_MMAP") == 0) | 407 | else if (strcmp(args[0].from, "FILE_MMAP") == 0) |
| 405 | entry->func = FILE_MMAP; | 408 | entry->func = FILE_MMAP; |
| 406 | else if (strcmp(args[0].from, "BPRM_CHECK") == 0) | 409 | else if (strcmp(args[0].from, "BPRM_CHECK") == 0) |
diff --git a/security/security.c b/security/security.c index 8dcd4ae10a5f..daa97f4ac9d1 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -820,6 +820,16 @@ int security_kernel_module_request(char *kmod_name) | |||
| 820 | return security_ops->kernel_module_request(kmod_name); | 820 | return security_ops->kernel_module_request(kmod_name); |
| 821 | } | 821 | } |
| 822 | 822 | ||
| 823 | int security_kernel_module_from_file(struct file *file) | ||
| 824 | { | ||
| 825 | int ret; | ||
| 826 | |||
| 827 | ret = security_ops->kernel_module_from_file(file); | ||
| 828 | if (ret) | ||
| 829 | return ret; | ||
| 830 | return ima_module_check(file); | ||
| 831 | } | ||
| 832 | |||
| 823 | int security_task_fix_setuid(struct cred *new, const struct cred *old, | 833 | int security_task_fix_setuid(struct cred *new, const struct cred *old, |
| 824 | int flags) | 834 | int flags) |
| 825 | { | 835 | { |
