Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selinux: restrict kernel module loading

Utilize existing kernel_read_file hook on kernel module load.
Add module_load permission to the system class.

Enforces restrictions on kernel module origin when calling the
finit_module syscall. The hook checks that source type has
permission module_load for the target type.
Example for finit_module:

allow foo bar_file:system module_load;

Similarly restrictions are enforced on kernel module loading when
calling the init_module syscall. The hook checks that source
type has permission module_load with itself as the target object
because the kernel module is sourced from the calling process.
Example for init_module:

allow foo foo:system module_load;

Signed-off-by: Jeff Vander Stoep <jeffv@google.com>
[PM: fixed return value of selinux_kernel_read_file()]
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Jeff Vander Stoep and committed by
Paul Moore
61d612ea 0c6181cb

+48 -1
+47
security/selinux/hooks.c
··· 3722 3722 SYSTEM__MODULE_REQUEST, &ad); 3723 3723 } 3724 3724 3725 + static int selinux_kernel_module_from_file(struct file *file) 3726 + { 3727 + struct common_audit_data ad; 3728 + struct inode_security_struct *isec; 3729 + struct file_security_struct *fsec; 3730 + u32 sid = current_sid(); 3731 + int rc; 3732 + 3733 + /* init_module */ 3734 + if (file == NULL) 3735 + return avc_has_perm(sid, sid, SECCLASS_SYSTEM, 3736 + SYSTEM__MODULE_LOAD, NULL); 3737 + 3738 + /* finit_module */ 3739 + ad.type = LSM_AUDIT_DATA_PATH; 3740 + ad.u.path = file->f_path; 3741 + 3742 + isec = inode_security(file_inode(file)); 3743 + fsec = file->f_security; 3744 + 3745 + if (sid != fsec->sid) { 3746 + rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); 3747 + if (rc) 3748 + return rc; 3749 + } 3750 + 3751 + return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM, 3752 + SYSTEM__MODULE_LOAD, &ad); 3753 + } 3754 + 3755 + static int selinux_kernel_read_file(struct file *file, 3756 + enum kernel_read_file_id id) 3757 + { 3758 + int rc = 0; 3759 + 3760 + switch (id) { 3761 + case READING_MODULE: 3762 + rc = selinux_kernel_module_from_file(file); 3763 + break; 3764 + default: 3765 + break; 3766 + } 3767 + 3768 + return rc; 3769 + } 3770 + 3725 3771 static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) 3726 3772 { 3727 3773 return current_has_perm(p, PROCESS__SETPGID); ··· 6064 6018 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as), 6065 6019 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as), 6066 6020 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request), 6021 + LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file), 6067 6022 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid), 6068 6023 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid), 6069 6024 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
+1 -1
security/selinux/include/classmap.h
··· 32 32 "setsockcreate", NULL } }, 33 33 { "system", 34 34 { "ipc_info", "syslog_read", "syslog_mod", 35 - "syslog_console", "module_request", NULL } }, 35 + "syslog_console", "module_request", "module_load", NULL } }, 36 36 { "capability", 37 37 { "chown", "dac_override", "dac_read_search", 38 38 "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap",