diff options
-rw-r--r-- | include/linux/security.h | 13 | ||||
-rw-r--r-- | kernel/module.c | 11 | ||||
-rw-r--r-- | security/capability.c | 6 | ||||
-rw-r--r-- | security/security.c | 5 |
4 files changed, 35 insertions, 0 deletions
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/kernel/module.c b/kernel/module.c index 1395ca382fb5..a1d2ed8bab93 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/vmalloc.h> | 29 | #include <linux/vmalloc.h> |
30 | #include <linux/elf.h> | 30 | #include <linux/elf.h> |
31 | #include <linux/proc_fs.h> | 31 | #include <linux/proc_fs.h> |
32 | #include <linux/security.h> | ||
32 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
33 | #include <linux/syscalls.h> | 34 | #include <linux/syscalls.h> |
34 | #include <linux/fcntl.h> | 35 | #include <linux/fcntl.h> |
@@ -2485,10 +2486,16 @@ static int elf_header_check(struct load_info *info) | |||
2485 | static int copy_module_from_user(const void __user *umod, unsigned long len, | 2486 | static int copy_module_from_user(const void __user *umod, unsigned long len, |
2486 | struct load_info *info) | 2487 | struct load_info *info) |
2487 | { | 2488 | { |
2489 | int err; | ||
2490 | |||
2488 | info->len = len; | 2491 | info->len = len; |
2489 | if (info->len < sizeof(*(info->hdr))) | 2492 | if (info->len < sizeof(*(info->hdr))) |
2490 | return -ENOEXEC; | 2493 | return -ENOEXEC; |
2491 | 2494 | ||
2495 | err = security_kernel_module_from_file(NULL); | ||
2496 | if (err) | ||
2497 | return err; | ||
2498 | |||
2492 | /* Suck in entire file: we'll want most of it. */ | 2499 | /* Suck in entire file: we'll want most of it. */ |
2493 | info->hdr = vmalloc(info->len); | 2500 | info->hdr = vmalloc(info->len); |
2494 | if (!info->hdr) | 2501 | if (!info->hdr) |
@@ -2515,6 +2522,10 @@ static int copy_module_from_fd(int fd, struct load_info *info) | |||
2515 | if (!file) | 2522 | if (!file) |
2516 | return -ENOEXEC; | 2523 | return -ENOEXEC; |
2517 | 2524 | ||
2525 | err = security_kernel_module_from_file(file); | ||
2526 | if (err) | ||
2527 | goto out; | ||
2528 | |||
2518 | err = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat); | 2529 | err = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat); |
2519 | if (err) | 2530 | if (err) |
2520 | goto out; | 2531 | goto out; |
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/security.c b/security/security.c index 8dcd4ae10a5f..ce88630de15d 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -820,6 +820,11 @@ 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 | return security_ops->kernel_module_from_file(file); | ||
826 | } | ||
827 | |||
823 | int security_task_fix_setuid(struct cred *new, const struct cred *old, | 828 | int security_task_fix_setuid(struct cred *new, const struct cred *old, |
824 | int flags) | 829 | int flags) |
825 | { | 830 | { |