From 3c4ed7bdf5997d8020cbb8d4abbef2fcfb9f1284 Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Sat, 2 May 2015 15:10:46 -0700 Subject: LSM: Split security.h The security.h header file serves two purposes, interfaces for users of the security modules and interfaces for security modules. Users of the security modules don't need to know about what's in the security_operations structure, so pull it out into it's own header, lsm_hooks.h Signed-off-by: Casey Schaufler Acked-by: John Johansen Acked-by: Kees Cook Acked-by: Paul Moore Acked-by: Stephen Smalley Acked-by: Tetsuo Handa Signed-off-by: James Morris --- security/selinux/hooks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7dade28affba..40e3f7757ec7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3-59-g8ed1b From e20b043a6902ecb61c2c84355c3bae5149f391db Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Sat, 2 May 2015 15:11:36 -0700 Subject: LSM: Add security module hook list heads Add a list header for each security hook. They aren't used until later in the patch series. They are grouped together in a structure so that there doesn't need to be an external address for each. Macro-ize the initialization of the security_operations for each security module in anticipation of changing out the security_operations structure. Signed-off-by: Casey Schaufler Acked-by: John Johansen Acked-by: Kees Cook Acked-by: Paul Moore Acked-by: Stephen Smalley Acked-by: Tetsuo Handa Signed-off-by: James Morris --- include/linux/lsm_hooks.h | 220 +++++++++++++++++++++++++ security/apparmor/lsm.c | 84 +++++----- security/selinux/hooks.c | 398 +++++++++++++++++++++++---------------------- security/smack/smack_lsm.c | 258 ++++++++++++++--------------- security/tomoyo/tomoyo.c | 58 +++---- security/yama/yama_lsm.c | 10 +- 6 files changed, 626 insertions(+), 402 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index b4c91de510c2..27dd6fcacccc 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1626,6 +1626,226 @@ struct security_operations { #endif /* CONFIG_AUDIT */ }; +struct security_hook_heads { + struct list_head binder_set_context_mgr; + struct list_head binder_transaction; + struct list_head binder_transfer_binder; + struct list_head binder_transfer_file; + struct list_head ptrace_access_check; + struct list_head ptrace_traceme; + struct list_head capget; + struct list_head capset; + struct list_head capable; + struct list_head quotactl; + struct list_head quota_on; + struct list_head syslog; + struct list_head settime; + struct list_head vm_enough_memory; + struct list_head bprm_set_creds; + struct list_head bprm_check_security; + struct list_head bprm_secureexec; + struct list_head bprm_committing_creds; + struct list_head bprm_committed_creds; + struct list_head sb_alloc_security; + struct list_head sb_free_security; + struct list_head sb_copy_data; + struct list_head sb_remount; + struct list_head sb_kern_mount; + struct list_head sb_show_options; + struct list_head sb_statfs; + struct list_head sb_mount; + struct list_head sb_umount; + struct list_head sb_pivotroot; + struct list_head sb_set_mnt_opts; + struct list_head sb_clone_mnt_opts; + struct list_head sb_parse_opts_str; + struct list_head dentry_init_security; +#ifdef CONFIG_SECURITY_PATH + struct list_head path_unlink; + struct list_head path_mkdir; + struct list_head path_rmdir; + struct list_head path_mknod; + struct list_head path_truncate; + struct list_head path_symlink; + struct list_head path_link; + struct list_head path_rename; + struct list_head path_chmod; + struct list_head path_chown; + struct list_head path_chroot; +#endif + struct list_head inode_alloc_security; + struct list_head inode_free_security; + struct list_head inode_init_security; + struct list_head inode_create; + struct list_head inode_link; + struct list_head inode_unlink; + struct list_head inode_symlink; + struct list_head inode_mkdir; + struct list_head inode_rmdir; + struct list_head inode_mknod; + struct list_head inode_rename; + struct list_head inode_readlink; + struct list_head inode_follow_link; + struct list_head inode_permission; + struct list_head inode_setattr; + struct list_head inode_getattr; + struct list_head inode_setxattr; + struct list_head inode_post_setxattr; + struct list_head inode_getxattr; + struct list_head inode_listxattr; + struct list_head inode_removexattr; + struct list_head inode_need_killpriv; + struct list_head inode_killpriv; + struct list_head inode_getsecurity; + struct list_head inode_setsecurity; + struct list_head inode_listsecurity; + struct list_head inode_getsecid; + struct list_head file_permission; + struct list_head file_alloc_security; + struct list_head file_free_security; + struct list_head file_ioctl; + struct list_head mmap_addr; + struct list_head mmap_file; + struct list_head file_mprotect; + struct list_head file_lock; + struct list_head file_fcntl; + struct list_head file_set_fowner; + struct list_head file_send_sigiotask; + struct list_head file_receive; + struct list_head file_open; + struct list_head task_create; + struct list_head task_free; + struct list_head cred_alloc_blank; + struct list_head cred_free; + struct list_head cred_prepare; + struct list_head cred_transfer; + struct list_head kernel_act_as; + struct list_head kernel_create_files_as; + struct list_head kernel_fw_from_file; + struct list_head kernel_module_request; + struct list_head kernel_module_from_file; + struct list_head task_fix_setuid; + struct list_head task_setpgid; + struct list_head task_getpgid; + struct list_head task_getsid; + struct list_head task_getsecid; + struct list_head task_setnice; + struct list_head task_setioprio; + struct list_head task_getioprio; + struct list_head task_setrlimit; + struct list_head task_setscheduler; + struct list_head task_getscheduler; + struct list_head task_movememory; + struct list_head task_kill; + struct list_head task_wait; + struct list_head task_prctl; + struct list_head task_to_inode; + struct list_head ipc_permission; + struct list_head ipc_getsecid; + struct list_head msg_msg_alloc_security; + struct list_head msg_msg_free_security; + struct list_head msg_queue_alloc_security; + struct list_head msg_queue_free_security; + struct list_head msg_queue_associate; + struct list_head msg_queue_msgctl; + struct list_head msg_queue_msgsnd; + struct list_head msg_queue_msgrcv; + struct list_head shm_alloc_security; + struct list_head shm_free_security; + struct list_head shm_associate; + struct list_head shm_shmctl; + struct list_head shm_shmat; + struct list_head sem_alloc_security; + struct list_head sem_free_security; + struct list_head sem_associate; + struct list_head sem_semctl; + struct list_head sem_semop; + struct list_head netlink_send; + struct list_head d_instantiate; + struct list_head getprocattr; + struct list_head setprocattr; + struct list_head ismaclabel; + struct list_head secid_to_secctx; + struct list_head secctx_to_secid; + struct list_head release_secctx; + struct list_head inode_notifysecctx; + struct list_head inode_setsecctx; + struct list_head inode_getsecctx; +#ifdef CONFIG_SECURITY_NETWORK + struct list_head unix_stream_connect; + struct list_head unix_may_send; + struct list_head socket_create; + struct list_head socket_post_create; + struct list_head socket_bind; + struct list_head socket_connect; + struct list_head socket_listen; + struct list_head socket_accept; + struct list_head socket_sendmsg; + struct list_head socket_recvmsg; + struct list_head socket_getsockname; + struct list_head socket_getpeername; + struct list_head socket_getsockopt; + struct list_head socket_setsockopt; + struct list_head socket_shutdown; + struct list_head socket_sock_rcv_skb; + struct list_head socket_getpeersec_stream; + struct list_head socket_getpeersec_dgram; + struct list_head sk_alloc_security; + struct list_head sk_free_security; + struct list_head sk_clone_security; + struct list_head sk_getsecid; + struct list_head sock_graft; + struct list_head inet_conn_request; + struct list_head inet_csk_clone; + struct list_head inet_conn_established; + struct list_head secmark_relabel_packet; + struct list_head secmark_refcount_inc; + struct list_head secmark_refcount_dec; + struct list_head req_classify_flow; + struct list_head tun_dev_alloc_security; + struct list_head tun_dev_free_security; + struct list_head tun_dev_create; + struct list_head tun_dev_attach_queue; + struct list_head tun_dev_attach; + struct list_head tun_dev_open; + struct list_head skb_owned_by; +#endif /* CONFIG_SECURITY_NETWORK */ +#ifdef CONFIG_SECURITY_NETWORK_XFRM + struct list_head xfrm_policy_alloc_security; + struct list_head xfrm_policy_clone_security; + struct list_head xfrm_policy_free_security; + struct list_head xfrm_policy_delete_security; + struct list_head xfrm_state_alloc; + struct list_head xfrm_state_alloc_acquire; + struct list_head xfrm_state_free_security; + struct list_head xfrm_state_delete_security; + struct list_head xfrm_policy_lookup; + struct list_head xfrm_state_pol_flow_match; + struct list_head xfrm_decode_session; +#endif /* CONFIG_SECURITY_NETWORK_XFRM */ +#ifdef CONFIG_KEYS + struct list_head key_alloc; + struct list_head key_free; + struct list_head key_permission; + struct list_head key_getsecurity; +#endif /* CONFIG_KEYS */ +#ifdef CONFIG_AUDIT + struct list_head audit_rule_init; + struct list_head audit_rule_known; + struct list_head audit_rule_match; + struct list_head audit_rule_free; +#endif /* CONFIG_AUDIT */ +}; + +/* + * Initializing a security_hook_list structure takes + * up a lot of space in a source file. This macro takes + * care of the common case and reduces the amount of + * text involved. + * Casey says: Comment is true in the next patch. + */ +#define LSM_HOOK_INIT(HEAD, HOOK) .HEAD = HOOK + /* prototypes */ extern int security_module_enable(struct security_operations *ops); extern int register_security(struct security_operations *ops); diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index fead41bd0440..f54253258fb8 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -616,48 +616,48 @@ static int apparmor_task_setrlimit(struct task_struct *task, } static struct security_operations apparmor_ops = { - .name = "apparmor", - - .ptrace_access_check = apparmor_ptrace_access_check, - .ptrace_traceme = apparmor_ptrace_traceme, - .capget = apparmor_capget, - .capable = apparmor_capable, - - .path_link = apparmor_path_link, - .path_unlink = apparmor_path_unlink, - .path_symlink = apparmor_path_symlink, - .path_mkdir = apparmor_path_mkdir, - .path_rmdir = apparmor_path_rmdir, - .path_mknod = apparmor_path_mknod, - .path_rename = apparmor_path_rename, - .path_chmod = apparmor_path_chmod, - .path_chown = apparmor_path_chown, - .path_truncate = apparmor_path_truncate, - .inode_getattr = apparmor_inode_getattr, - - .file_open = apparmor_file_open, - .file_permission = apparmor_file_permission, - .file_alloc_security = apparmor_file_alloc_security, - .file_free_security = apparmor_file_free_security, - .mmap_file = apparmor_mmap_file, - .mmap_addr = cap_mmap_addr, - .file_mprotect = apparmor_file_mprotect, - .file_lock = apparmor_file_lock, - - .getprocattr = apparmor_getprocattr, - .setprocattr = apparmor_setprocattr, - - .cred_alloc_blank = apparmor_cred_alloc_blank, - .cred_free = apparmor_cred_free, - .cred_prepare = apparmor_cred_prepare, - .cred_transfer = apparmor_cred_transfer, - - .bprm_set_creds = apparmor_bprm_set_creds, - .bprm_committing_creds = apparmor_bprm_committing_creds, - .bprm_committed_creds = apparmor_bprm_committed_creds, - .bprm_secureexec = apparmor_bprm_secureexec, - - .task_setrlimit = apparmor_task_setrlimit, + LSM_HOOK_INIT(name, "apparmor"), + + LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), + LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), + LSM_HOOK_INIT(capget, apparmor_capget), + LSM_HOOK_INIT(capable, apparmor_capable), + + LSM_HOOK_INIT(path_link, apparmor_path_link), + LSM_HOOK_INIT(path_unlink, apparmor_path_unlink), + LSM_HOOK_INIT(path_symlink, apparmor_path_symlink), + LSM_HOOK_INIT(path_mkdir, apparmor_path_mkdir), + LSM_HOOK_INIT(path_rmdir, apparmor_path_rmdir), + LSM_HOOK_INIT(path_mknod, apparmor_path_mknod), + LSM_HOOK_INIT(path_rename, apparmor_path_rename), + LSM_HOOK_INIT(path_chmod, apparmor_path_chmod), + LSM_HOOK_INIT(path_chown, apparmor_path_chown), + LSM_HOOK_INIT(path_truncate, apparmor_path_truncate), + LSM_HOOK_INIT(inode_getattr, apparmor_inode_getattr), + + LSM_HOOK_INIT(file_open, apparmor_file_open), + LSM_HOOK_INIT(file_permission, apparmor_file_permission), + LSM_HOOK_INIT(file_alloc_security, apparmor_file_alloc_security), + LSM_HOOK_INIT(file_free_security, apparmor_file_free_security), + LSM_HOOK_INIT(mmap_file, apparmor_mmap_file), + LSM_HOOK_INIT(mmap_addr, cap_mmap_addr), + LSM_HOOK_INIT(file_mprotect, apparmor_file_mprotect), + LSM_HOOK_INIT(file_lock, apparmor_file_lock), + + LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), + LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), + + LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank), + LSM_HOOK_INIT(cred_free, apparmor_cred_free), + LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare), + LSM_HOOK_INIT(cred_transfer, apparmor_cred_transfer), + + LSM_HOOK_INIT(bprm_set_creds, apparmor_bprm_set_creds), + LSM_HOOK_INIT(bprm_committing_creds, apparmor_bprm_committing_creds), + LSM_HOOK_INIT(bprm_committed_creds, apparmor_bprm_committed_creds), + LSM_HOOK_INIT(bprm_secureexec, apparmor_bprm_secureexec), + + LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit), }; /* diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 40e3f7757ec7..0cf105f346d4 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5841,211 +5841,215 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) #endif static struct security_operations selinux_ops = { - .name = "selinux", - - .binder_set_context_mgr = selinux_binder_set_context_mgr, - .binder_transaction = selinux_binder_transaction, - .binder_transfer_binder = selinux_binder_transfer_binder, - .binder_transfer_file = selinux_binder_transfer_file, - - .ptrace_access_check = selinux_ptrace_access_check, - .ptrace_traceme = selinux_ptrace_traceme, - .capget = selinux_capget, - .capset = selinux_capset, - .capable = selinux_capable, - .quotactl = selinux_quotactl, - .quota_on = selinux_quota_on, - .syslog = selinux_syslog, - .vm_enough_memory = selinux_vm_enough_memory, - - .netlink_send = selinux_netlink_send, - - .bprm_set_creds = selinux_bprm_set_creds, - .bprm_committing_creds = selinux_bprm_committing_creds, - .bprm_committed_creds = selinux_bprm_committed_creds, - .bprm_secureexec = selinux_bprm_secureexec, - - .sb_alloc_security = selinux_sb_alloc_security, - .sb_free_security = selinux_sb_free_security, - .sb_copy_data = selinux_sb_copy_data, - .sb_remount = selinux_sb_remount, - .sb_kern_mount = selinux_sb_kern_mount, - .sb_show_options = selinux_sb_show_options, - .sb_statfs = selinux_sb_statfs, - .sb_mount = selinux_mount, - .sb_umount = selinux_umount, - .sb_set_mnt_opts = selinux_set_mnt_opts, - .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, - .sb_parse_opts_str = selinux_parse_opts_str, - - .dentry_init_security = selinux_dentry_init_security, - - .inode_alloc_security = selinux_inode_alloc_security, - .inode_free_security = selinux_inode_free_security, - .inode_init_security = selinux_inode_init_security, - .inode_create = selinux_inode_create, - .inode_link = selinux_inode_link, - .inode_unlink = selinux_inode_unlink, - .inode_symlink = selinux_inode_symlink, - .inode_mkdir = selinux_inode_mkdir, - .inode_rmdir = selinux_inode_rmdir, - .inode_mknod = selinux_inode_mknod, - .inode_rename = selinux_inode_rename, - .inode_readlink = selinux_inode_readlink, - .inode_follow_link = selinux_inode_follow_link, - .inode_permission = selinux_inode_permission, - .inode_setattr = selinux_inode_setattr, - .inode_getattr = selinux_inode_getattr, - .inode_setxattr = selinux_inode_setxattr, - .inode_post_setxattr = selinux_inode_post_setxattr, - .inode_getxattr = selinux_inode_getxattr, - .inode_listxattr = selinux_inode_listxattr, - .inode_removexattr = selinux_inode_removexattr, - .inode_getsecurity = selinux_inode_getsecurity, - .inode_setsecurity = selinux_inode_setsecurity, - .inode_listsecurity = selinux_inode_listsecurity, - .inode_getsecid = selinux_inode_getsecid, - - .file_permission = selinux_file_permission, - .file_alloc_security = selinux_file_alloc_security, - .file_free_security = selinux_file_free_security, - .file_ioctl = selinux_file_ioctl, - .mmap_file = selinux_mmap_file, - .mmap_addr = selinux_mmap_addr, - .file_mprotect = selinux_file_mprotect, - .file_lock = selinux_file_lock, - .file_fcntl = selinux_file_fcntl, - .file_set_fowner = selinux_file_set_fowner, - .file_send_sigiotask = selinux_file_send_sigiotask, - .file_receive = selinux_file_receive, - - .file_open = selinux_file_open, - - .task_create = selinux_task_create, - .cred_alloc_blank = selinux_cred_alloc_blank, - .cred_free = selinux_cred_free, - .cred_prepare = selinux_cred_prepare, - .cred_transfer = selinux_cred_transfer, - .kernel_act_as = selinux_kernel_act_as, - .kernel_create_files_as = selinux_kernel_create_files_as, - .kernel_module_request = selinux_kernel_module_request, - .task_setpgid = selinux_task_setpgid, - .task_getpgid = selinux_task_getpgid, - .task_getsid = selinux_task_getsid, - .task_getsecid = selinux_task_getsecid, - .task_setnice = selinux_task_setnice, - .task_setioprio = selinux_task_setioprio, - .task_getioprio = selinux_task_getioprio, - .task_setrlimit = selinux_task_setrlimit, - .task_setscheduler = selinux_task_setscheduler, - .task_getscheduler = selinux_task_getscheduler, - .task_movememory = selinux_task_movememory, - .task_kill = selinux_task_kill, - .task_wait = selinux_task_wait, - .task_to_inode = selinux_task_to_inode, - - .ipc_permission = selinux_ipc_permission, - .ipc_getsecid = selinux_ipc_getsecid, - - .msg_msg_alloc_security = selinux_msg_msg_alloc_security, - .msg_msg_free_security = selinux_msg_msg_free_security, - - .msg_queue_alloc_security = selinux_msg_queue_alloc_security, - .msg_queue_free_security = selinux_msg_queue_free_security, - .msg_queue_associate = selinux_msg_queue_associate, - .msg_queue_msgctl = selinux_msg_queue_msgctl, - .msg_queue_msgsnd = selinux_msg_queue_msgsnd, - .msg_queue_msgrcv = selinux_msg_queue_msgrcv, - - .shm_alloc_security = selinux_shm_alloc_security, - .shm_free_security = selinux_shm_free_security, - .shm_associate = selinux_shm_associate, - .shm_shmctl = selinux_shm_shmctl, - .shm_shmat = selinux_shm_shmat, - - .sem_alloc_security = selinux_sem_alloc_security, - .sem_free_security = selinux_sem_free_security, - .sem_associate = selinux_sem_associate, - .sem_semctl = selinux_sem_semctl, - .sem_semop = selinux_sem_semop, - - .d_instantiate = selinux_d_instantiate, - - .getprocattr = selinux_getprocattr, - .setprocattr = selinux_setprocattr, - - .ismaclabel = selinux_ismaclabel, - .secid_to_secctx = selinux_secid_to_secctx, - .secctx_to_secid = selinux_secctx_to_secid, - .release_secctx = selinux_release_secctx, - .inode_notifysecctx = selinux_inode_notifysecctx, - .inode_setsecctx = selinux_inode_setsecctx, - .inode_getsecctx = selinux_inode_getsecctx, - - .unix_stream_connect = selinux_socket_unix_stream_connect, - .unix_may_send = selinux_socket_unix_may_send, - - .socket_create = selinux_socket_create, - .socket_post_create = selinux_socket_post_create, - .socket_bind = selinux_socket_bind, - .socket_connect = selinux_socket_connect, - .socket_listen = selinux_socket_listen, - .socket_accept = selinux_socket_accept, - .socket_sendmsg = selinux_socket_sendmsg, - .socket_recvmsg = selinux_socket_recvmsg, - .socket_getsockname = selinux_socket_getsockname, - .socket_getpeername = selinux_socket_getpeername, - .socket_getsockopt = selinux_socket_getsockopt, - .socket_setsockopt = selinux_socket_setsockopt, - .socket_shutdown = selinux_socket_shutdown, - .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb, - .socket_getpeersec_stream = selinux_socket_getpeersec_stream, - .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram, - .sk_alloc_security = selinux_sk_alloc_security, - .sk_free_security = selinux_sk_free_security, - .sk_clone_security = selinux_sk_clone_security, - .sk_getsecid = selinux_sk_getsecid, - .sock_graft = selinux_sock_graft, - .inet_conn_request = selinux_inet_conn_request, - .inet_csk_clone = selinux_inet_csk_clone, - .inet_conn_established = selinux_inet_conn_established, - .secmark_relabel_packet = selinux_secmark_relabel_packet, - .secmark_refcount_inc = selinux_secmark_refcount_inc, - .secmark_refcount_dec = selinux_secmark_refcount_dec, - .req_classify_flow = selinux_req_classify_flow, - .tun_dev_alloc_security = selinux_tun_dev_alloc_security, - .tun_dev_free_security = selinux_tun_dev_free_security, - .tun_dev_create = selinux_tun_dev_create, - .tun_dev_attach_queue = selinux_tun_dev_attach_queue, - .tun_dev_attach = selinux_tun_dev_attach, - .tun_dev_open = selinux_tun_dev_open, + LSM_HOOK_INIT(name, "selinux"), + + LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), + LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), + LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder), + LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file), + + LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check), + LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme), + LSM_HOOK_INIT(capget, selinux_capget), + LSM_HOOK_INIT(capset, selinux_capset), + LSM_HOOK_INIT(capable, selinux_capable), + LSM_HOOK_INIT(quotactl, selinux_quotactl), + LSM_HOOK_INIT(quota_on, selinux_quota_on), + LSM_HOOK_INIT(syslog, selinux_syslog), + LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory), + + LSM_HOOK_INIT(netlink_send, selinux_netlink_send), + + LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds), + LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds), + LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds), + LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec), + + LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security), + LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security), + LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data), + LSM_HOOK_INIT(sb_remount, selinux_sb_remount), + LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount), + LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options), + LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs), + LSM_HOOK_INIT(sb_mount, selinux_mount), + LSM_HOOK_INIT(sb_umount, selinux_umount), + LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts), + LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts), + LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str), + + LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security), + + LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security), + LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security), + LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security), + LSM_HOOK_INIT(inode_create, selinux_inode_create), + LSM_HOOK_INIT(inode_link, selinux_inode_link), + LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink), + LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink), + LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir), + LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir), + LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod), + LSM_HOOK_INIT(inode_rename, selinux_inode_rename), + LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink), + LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link), + LSM_HOOK_INIT(inode_permission, selinux_inode_permission), + LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr), + LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr), + LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr), + LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr), + LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr), + LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr), + LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr), + LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity), + LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity), + LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity), + LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid), + + LSM_HOOK_INIT(file_permission, selinux_file_permission), + LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security), + LSM_HOOK_INIT(file_free_security, selinux_file_free_security), + LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl), + LSM_HOOK_INIT(mmap_file, selinux_mmap_file), + LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr), + LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect), + LSM_HOOK_INIT(file_lock, selinux_file_lock), + LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl), + LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner), + LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask), + LSM_HOOK_INIT(file_receive, selinux_file_receive), + + LSM_HOOK_INIT(file_open, selinux_file_open), + + LSM_HOOK_INIT(task_create, selinux_task_create), + LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank), + LSM_HOOK_INIT(cred_free, selinux_cred_free), + LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare), + LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer), + LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as), + LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as), + LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request), + LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid), + LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid), + LSM_HOOK_INIT(task_getsid, selinux_task_getsid), + LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid), + LSM_HOOK_INIT(task_setnice, selinux_task_setnice), + LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio), + LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio), + LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit), + LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler), + LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler), + LSM_HOOK_INIT(task_movememory, selinux_task_movememory), + LSM_HOOK_INIT(task_kill, selinux_task_kill), + LSM_HOOK_INIT(task_wait, selinux_task_wait), + LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode), + + LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission), + LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid), + + LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security), + LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security), + + LSM_HOOK_INIT(msg_queue_alloc_security, + selinux_msg_queue_alloc_security), + LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security), + LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate), + LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl), + LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd), + LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv), + + LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security), + LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security), + LSM_HOOK_INIT(shm_associate, selinux_shm_associate), + LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl), + LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat), + + LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security), + LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security), + LSM_HOOK_INIT(sem_associate, selinux_sem_associate), + LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl), + LSM_HOOK_INIT(sem_semop, selinux_sem_semop), + + LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate), + + LSM_HOOK_INIT(getprocattr, selinux_getprocattr), + LSM_HOOK_INIT(setprocattr, selinux_setprocattr), + + LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel), + LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx), + LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid), + LSM_HOOK_INIT(release_secctx, selinux_release_secctx), + LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx), + LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx), + LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx), + + LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect), + LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send), + + LSM_HOOK_INIT(socket_create, selinux_socket_create), + LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create), + LSM_HOOK_INIT(socket_bind, selinux_socket_bind), + LSM_HOOK_INIT(socket_connect, selinux_socket_connect), + LSM_HOOK_INIT(socket_listen, selinux_socket_listen), + LSM_HOOK_INIT(socket_accept, selinux_socket_accept), + LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg), + LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg), + LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname), + LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername), + LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt), + LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt), + LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown), + LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb), + LSM_HOOK_INIT(socket_getpeersec_stream, + selinux_socket_getpeersec_stream), + LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram), + LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security), + LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security), + LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security), + LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid), + LSM_HOOK_INIT(sock_graft, selinux_sock_graft), + LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request), + LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone), + LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established), + LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet), + LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc), + LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec), + LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow), + LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security), + LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security), + LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create), + LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue), + LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach), + LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open), #ifdef CONFIG_SECURITY_NETWORK_XFRM - .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, - .xfrm_policy_clone_security = selinux_xfrm_policy_clone, - .xfrm_policy_free_security = selinux_xfrm_policy_free, - .xfrm_policy_delete_security = selinux_xfrm_policy_delete, - .xfrm_state_alloc = selinux_xfrm_state_alloc, - .xfrm_state_alloc_acquire = selinux_xfrm_state_alloc_acquire, - .xfrm_state_free_security = selinux_xfrm_state_free, - .xfrm_state_delete_security = selinux_xfrm_state_delete, - .xfrm_policy_lookup = selinux_xfrm_policy_lookup, - .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match, - .xfrm_decode_session = selinux_xfrm_decode_session, + LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc), + LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone), + LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free), + LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete), + LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc), + LSM_HOOK_INIT(xfrm_state_alloc_acquire, + selinux_xfrm_state_alloc_acquire), + LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free), + LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete), + LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup), + LSM_HOOK_INIT(xfrm_state_pol_flow_match, + selinux_xfrm_state_pol_flow_match), + LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session), #endif #ifdef CONFIG_KEYS - .key_alloc = selinux_key_alloc, - .key_free = selinux_key_free, - .key_permission = selinux_key_permission, - .key_getsecurity = selinux_key_getsecurity, + LSM_HOOK_INIT(key_alloc, selinux_key_alloc), + LSM_HOOK_INIT(key_free, selinux_key_free), + LSM_HOOK_INIT(key_permission, selinux_key_permission), + LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity), #endif #ifdef CONFIG_AUDIT - .audit_rule_init = selinux_audit_rule_init, - .audit_rule_known = selinux_audit_rule_known, - .audit_rule_match = selinux_audit_rule_match, - .audit_rule_free = selinux_audit_rule_free, + LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init), + LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known), + LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match), + LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free), #endif }; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index b644757886bc..4313bf44c3f0 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4267,146 +4267,146 @@ static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) } struct security_operations smack_ops = { - .name = "smack", - - .ptrace_access_check = smack_ptrace_access_check, - .ptrace_traceme = smack_ptrace_traceme, - .syslog = smack_syslog, - - .sb_alloc_security = smack_sb_alloc_security, - .sb_free_security = smack_sb_free_security, - .sb_copy_data = smack_sb_copy_data, - .sb_kern_mount = smack_sb_kern_mount, - .sb_statfs = smack_sb_statfs, - - .bprm_set_creds = smack_bprm_set_creds, - .bprm_committing_creds = smack_bprm_committing_creds, - .bprm_secureexec = smack_bprm_secureexec, - - .inode_alloc_security = smack_inode_alloc_security, - .inode_free_security = smack_inode_free_security, - .inode_init_security = smack_inode_init_security, - .inode_link = smack_inode_link, - .inode_unlink = smack_inode_unlink, - .inode_rmdir = smack_inode_rmdir, - .inode_rename = smack_inode_rename, - .inode_permission = smack_inode_permission, - .inode_setattr = smack_inode_setattr, - .inode_getattr = smack_inode_getattr, - .inode_setxattr = smack_inode_setxattr, - .inode_post_setxattr = smack_inode_post_setxattr, - .inode_getxattr = smack_inode_getxattr, - .inode_removexattr = smack_inode_removexattr, - .inode_getsecurity = smack_inode_getsecurity, - .inode_setsecurity = smack_inode_setsecurity, - .inode_listsecurity = smack_inode_listsecurity, - .inode_getsecid = smack_inode_getsecid, - - .file_permission = smack_file_permission, - .file_alloc_security = smack_file_alloc_security, - .file_free_security = smack_file_free_security, - .file_ioctl = smack_file_ioctl, - .file_lock = smack_file_lock, - .file_fcntl = smack_file_fcntl, - .mmap_file = smack_mmap_file, - .mmap_addr = cap_mmap_addr, - .file_set_fowner = smack_file_set_fowner, - .file_send_sigiotask = smack_file_send_sigiotask, - .file_receive = smack_file_receive, - - .file_open = smack_file_open, - - .cred_alloc_blank = smack_cred_alloc_blank, - .cred_free = smack_cred_free, - .cred_prepare = smack_cred_prepare, - .cred_transfer = smack_cred_transfer, - .kernel_act_as = smack_kernel_act_as, - .kernel_create_files_as = smack_kernel_create_files_as, - .task_setpgid = smack_task_setpgid, - .task_getpgid = smack_task_getpgid, - .task_getsid = smack_task_getsid, - .task_getsecid = smack_task_getsecid, - .task_setnice = smack_task_setnice, - .task_setioprio = smack_task_setioprio, - .task_getioprio = smack_task_getioprio, - .task_setscheduler = smack_task_setscheduler, - .task_getscheduler = smack_task_getscheduler, - .task_movememory = smack_task_movememory, - .task_kill = smack_task_kill, - .task_wait = smack_task_wait, - .task_to_inode = smack_task_to_inode, - - .ipc_permission = smack_ipc_permission, - .ipc_getsecid = smack_ipc_getsecid, - - .msg_msg_alloc_security = smack_msg_msg_alloc_security, - .msg_msg_free_security = smack_msg_msg_free_security, - - .msg_queue_alloc_security = smack_msg_queue_alloc_security, - .msg_queue_free_security = smack_msg_queue_free_security, - .msg_queue_associate = smack_msg_queue_associate, - .msg_queue_msgctl = smack_msg_queue_msgctl, - .msg_queue_msgsnd = smack_msg_queue_msgsnd, - .msg_queue_msgrcv = smack_msg_queue_msgrcv, - - .shm_alloc_security = smack_shm_alloc_security, - .shm_free_security = smack_shm_free_security, - .shm_associate = smack_shm_associate, - .shm_shmctl = smack_shm_shmctl, - .shm_shmat = smack_shm_shmat, - - .sem_alloc_security = smack_sem_alloc_security, - .sem_free_security = smack_sem_free_security, - .sem_associate = smack_sem_associate, - .sem_semctl = smack_sem_semctl, - .sem_semop = smack_sem_semop, - - .d_instantiate = smack_d_instantiate, - - .getprocattr = smack_getprocattr, - .setprocattr = smack_setprocattr, - - .unix_stream_connect = smack_unix_stream_connect, - .unix_may_send = smack_unix_may_send, - - .socket_post_create = smack_socket_post_create, + LSM_HOOK_INIT(name, "smack"), + + LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), + LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), + LSM_HOOK_INIT(syslog, smack_syslog), + + LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security), + LSM_HOOK_INIT(sb_free_security, smack_sb_free_security), + LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data), + LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount), + LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), + + LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), + LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds), + LSM_HOOK_INIT(bprm_secureexec, smack_bprm_secureexec), + + LSM_HOOK_INIT(inode_alloc_security, smack_inode_alloc_security), + LSM_HOOK_INIT(inode_free_security, smack_inode_free_security), + LSM_HOOK_INIT(inode_init_security, smack_inode_init_security), + LSM_HOOK_INIT(inode_link, smack_inode_link), + LSM_HOOK_INIT(inode_unlink, smack_inode_unlink), + LSM_HOOK_INIT(inode_rmdir, smack_inode_rmdir), + LSM_HOOK_INIT(inode_rename, smack_inode_rename), + LSM_HOOK_INIT(inode_permission, smack_inode_permission), + LSM_HOOK_INIT(inode_setattr, smack_inode_setattr), + LSM_HOOK_INIT(inode_getattr, smack_inode_getattr), + LSM_HOOK_INIT(inode_setxattr, smack_inode_setxattr), + LSM_HOOK_INIT(inode_post_setxattr, smack_inode_post_setxattr), + LSM_HOOK_INIT(inode_getxattr, smack_inode_getxattr), + LSM_HOOK_INIT(inode_removexattr, smack_inode_removexattr), + LSM_HOOK_INIT(inode_getsecurity, smack_inode_getsecurity), + LSM_HOOK_INIT(inode_setsecurity, smack_inode_setsecurity), + LSM_HOOK_INIT(inode_listsecurity, smack_inode_listsecurity), + LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid), + + LSM_HOOK_INIT(file_permission, smack_file_permission), + LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security), + LSM_HOOK_INIT(file_free_security, smack_file_free_security), + LSM_HOOK_INIT(file_ioctl, smack_file_ioctl), + LSM_HOOK_INIT(file_lock, smack_file_lock), + LSM_HOOK_INIT(file_fcntl, smack_file_fcntl), + LSM_HOOK_INIT(mmap_file, smack_mmap_file), + LSM_HOOK_INIT(mmap_addr, cap_mmap_addr), + LSM_HOOK_INIT(file_set_fowner, smack_file_set_fowner), + LSM_HOOK_INIT(file_send_sigiotask, smack_file_send_sigiotask), + LSM_HOOK_INIT(file_receive, smack_file_receive), + + LSM_HOOK_INIT(file_open, smack_file_open), + + LSM_HOOK_INIT(cred_alloc_blank, smack_cred_alloc_blank), + LSM_HOOK_INIT(cred_free, smack_cred_free), + LSM_HOOK_INIT(cred_prepare, smack_cred_prepare), + LSM_HOOK_INIT(cred_transfer, smack_cred_transfer), + LSM_HOOK_INIT(kernel_act_as, smack_kernel_act_as), + LSM_HOOK_INIT(kernel_create_files_as, smack_kernel_create_files_as), + LSM_HOOK_INIT(task_setpgid, smack_task_setpgid), + LSM_HOOK_INIT(task_getpgid, smack_task_getpgid), + LSM_HOOK_INIT(task_getsid, smack_task_getsid), + LSM_HOOK_INIT(task_getsecid, smack_task_getsecid), + LSM_HOOK_INIT(task_setnice, smack_task_setnice), + LSM_HOOK_INIT(task_setioprio, smack_task_setioprio), + LSM_HOOK_INIT(task_getioprio, smack_task_getioprio), + LSM_HOOK_INIT(task_setscheduler, smack_task_setscheduler), + LSM_HOOK_INIT(task_getscheduler, smack_task_getscheduler), + LSM_HOOK_INIT(task_movememory, smack_task_movememory), + LSM_HOOK_INIT(task_kill, smack_task_kill), + LSM_HOOK_INIT(task_wait, smack_task_wait), + LSM_HOOK_INIT(task_to_inode, smack_task_to_inode), + + LSM_HOOK_INIT(ipc_permission, smack_ipc_permission), + LSM_HOOK_INIT(ipc_getsecid, smack_ipc_getsecid), + + LSM_HOOK_INIT(msg_msg_alloc_security, smack_msg_msg_alloc_security), + LSM_HOOK_INIT(msg_msg_free_security, smack_msg_msg_free_security), + + LSM_HOOK_INIT(msg_queue_alloc_security, smack_msg_queue_alloc_security), + LSM_HOOK_INIT(msg_queue_free_security, smack_msg_queue_free_security), + LSM_HOOK_INIT(msg_queue_associate, smack_msg_queue_associate), + LSM_HOOK_INIT(msg_queue_msgctl, smack_msg_queue_msgctl), + LSM_HOOK_INIT(msg_queue_msgsnd, smack_msg_queue_msgsnd), + LSM_HOOK_INIT(msg_queue_msgrcv, smack_msg_queue_msgrcv), + + LSM_HOOK_INIT(shm_alloc_security, smack_shm_alloc_security), + LSM_HOOK_INIT(shm_free_security, smack_shm_free_security), + LSM_HOOK_INIT(shm_associate, smack_shm_associate), + LSM_HOOK_INIT(shm_shmctl, smack_shm_shmctl), + LSM_HOOK_INIT(shm_shmat, smack_shm_shmat), + + LSM_HOOK_INIT(sem_alloc_security, smack_sem_alloc_security), + LSM_HOOK_INIT(sem_free_security, smack_sem_free_security), + LSM_HOOK_INIT(sem_associate, smack_sem_associate), + LSM_HOOK_INIT(sem_semctl, smack_sem_semctl), + LSM_HOOK_INIT(sem_semop, smack_sem_semop), + + LSM_HOOK_INIT(d_instantiate, smack_d_instantiate), + + LSM_HOOK_INIT(getprocattr, smack_getprocattr), + LSM_HOOK_INIT(setprocattr, smack_setprocattr), + + LSM_HOOK_INIT(unix_stream_connect, smack_unix_stream_connect), + LSM_HOOK_INIT(unix_may_send, smack_unix_may_send), + + LSM_HOOK_INIT(socket_post_create, smack_socket_post_create), #ifndef CONFIG_SECURITY_SMACK_NETFILTER - .socket_bind = smack_socket_bind, + LSM_HOOK_INIT(socket_bind, smack_socket_bind), #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ - .socket_connect = smack_socket_connect, - .socket_sendmsg = smack_socket_sendmsg, - .socket_sock_rcv_skb = smack_socket_sock_rcv_skb, - .socket_getpeersec_stream = smack_socket_getpeersec_stream, - .socket_getpeersec_dgram = smack_socket_getpeersec_dgram, - .sk_alloc_security = smack_sk_alloc_security, - .sk_free_security = smack_sk_free_security, - .sock_graft = smack_sock_graft, - .inet_conn_request = smack_inet_conn_request, - .inet_csk_clone = smack_inet_csk_clone, + LSM_HOOK_INIT(socket_connect, smack_socket_connect), + LSM_HOOK_INIT(socket_sendmsg, smack_socket_sendmsg), + LSM_HOOK_INIT(socket_sock_rcv_skb, smack_socket_sock_rcv_skb), + LSM_HOOK_INIT(socket_getpeersec_stream, smack_socket_getpeersec_stream), + LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram), + LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security), + LSM_HOOK_INIT(sk_free_security, smack_sk_free_security), + LSM_HOOK_INIT(sock_graft, smack_sock_graft), + LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request), + LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone), /* key management security hooks */ #ifdef CONFIG_KEYS - .key_alloc = smack_key_alloc, - .key_free = smack_key_free, - .key_permission = smack_key_permission, - .key_getsecurity = smack_key_getsecurity, + LSM_HOOK_INIT(key_alloc, smack_key_alloc), + LSM_HOOK_INIT(key_free, smack_key_free), + LSM_HOOK_INIT(key_permission, smack_key_permission), + LSM_HOOK_INIT(key_getsecurity, smack_key_getsecurity), #endif /* CONFIG_KEYS */ /* Audit hooks */ #ifdef CONFIG_AUDIT - .audit_rule_init = smack_audit_rule_init, - .audit_rule_known = smack_audit_rule_known, - .audit_rule_match = smack_audit_rule_match, - .audit_rule_free = smack_audit_rule_free, + LSM_HOOK_INIT(audit_rule_init, smack_audit_rule_init), + LSM_HOOK_INIT(audit_rule_known, smack_audit_rule_known), + LSM_HOOK_INIT(audit_rule_match, smack_audit_rule_match), + LSM_HOOK_INIT(audit_rule_free, smack_audit_rule_free), #endif /* CONFIG_AUDIT */ - .ismaclabel = smack_ismaclabel, - .secid_to_secctx = smack_secid_to_secctx, - .secctx_to_secid = smack_secctx_to_secid, - .release_secctx = smack_release_secctx, - .inode_notifysecctx = smack_inode_notifysecctx, - .inode_setsecctx = smack_inode_setsecctx, - .inode_getsecctx = smack_inode_getsecctx, + LSM_HOOK_INIT(ismaclabel, smack_ismaclabel), + LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx), + LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid), + LSM_HOOK_INIT(release_secctx, smack_release_secctx), + LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx), + LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx), + LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx), }; diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 2f7b46855f48..bce13583efda 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -503,35 +503,35 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, * registering TOMOYO. */ static struct security_operations tomoyo_security_ops = { - .name = "tomoyo", - .cred_alloc_blank = tomoyo_cred_alloc_blank, - .cred_prepare = tomoyo_cred_prepare, - .cred_transfer = tomoyo_cred_transfer, - .cred_free = tomoyo_cred_free, - .bprm_set_creds = tomoyo_bprm_set_creds, - .bprm_check_security = tomoyo_bprm_check_security, - .file_fcntl = tomoyo_file_fcntl, - .file_open = tomoyo_file_open, - .path_truncate = tomoyo_path_truncate, - .path_unlink = tomoyo_path_unlink, - .path_mkdir = tomoyo_path_mkdir, - .path_rmdir = tomoyo_path_rmdir, - .path_symlink = tomoyo_path_symlink, - .path_mknod = tomoyo_path_mknod, - .path_link = tomoyo_path_link, - .path_rename = tomoyo_path_rename, - .inode_getattr = tomoyo_inode_getattr, - .file_ioctl = tomoyo_file_ioctl, - .path_chmod = tomoyo_path_chmod, - .path_chown = tomoyo_path_chown, - .path_chroot = tomoyo_path_chroot, - .sb_mount = tomoyo_sb_mount, - .sb_umount = tomoyo_sb_umount, - .sb_pivotroot = tomoyo_sb_pivotroot, - .socket_bind = tomoyo_socket_bind, - .socket_connect = tomoyo_socket_connect, - .socket_listen = tomoyo_socket_listen, - .socket_sendmsg = tomoyo_socket_sendmsg, + LSM_HOOK_INIT(name, "tomoyo"), + LSM_HOOK_INIT(cred_alloc_blank, tomoyo_cred_alloc_blank), + LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare), + LSM_HOOK_INIT(cred_transfer, tomoyo_cred_transfer), + LSM_HOOK_INIT(cred_free, tomoyo_cred_free), + LSM_HOOK_INIT(bprm_set_creds, tomoyo_bprm_set_creds), + LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security), + LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl), + LSM_HOOK_INIT(file_open, tomoyo_file_open), + LSM_HOOK_INIT(path_truncate, tomoyo_path_truncate), + LSM_HOOK_INIT(path_unlink, tomoyo_path_unlink), + LSM_HOOK_INIT(path_mkdir, tomoyo_path_mkdir), + LSM_HOOK_INIT(path_rmdir, tomoyo_path_rmdir), + LSM_HOOK_INIT(path_symlink, tomoyo_path_symlink), + LSM_HOOK_INIT(path_mknod, tomoyo_path_mknod), + LSM_HOOK_INIT(path_link, tomoyo_path_link), + LSM_HOOK_INIT(path_rename, tomoyo_path_rename), + LSM_HOOK_INIT(inode_getattr, tomoyo_inode_getattr), + LSM_HOOK_INIT(file_ioctl, tomoyo_file_ioctl), + LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod), + LSM_HOOK_INIT(path_chown, tomoyo_path_chown), + LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot), + LSM_HOOK_INIT(sb_mount, tomoyo_sb_mount), + LSM_HOOK_INIT(sb_umount, tomoyo_sb_umount), + LSM_HOOK_INIT(sb_pivotroot, tomoyo_sb_pivotroot), + LSM_HOOK_INIT(socket_bind, tomoyo_socket_bind), + LSM_HOOK_INIT(socket_connect, tomoyo_socket_connect), + LSM_HOOK_INIT(socket_listen, tomoyo_socket_listen), + LSM_HOOK_INIT(socket_sendmsg, tomoyo_socket_sendmsg), }; /* Lock for GC. */ diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 14557ffa7b4d..23dd4c6246b2 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -366,12 +366,12 @@ int yama_ptrace_traceme(struct task_struct *parent) #ifndef CONFIG_SECURITY_YAMA_STACKED static struct security_operations yama_ops = { - .name = "yama", + LSM_HOOK_INIT(name, "yama"), - .ptrace_access_check = yama_ptrace_access_check, - .ptrace_traceme = yama_ptrace_traceme, - .task_prctl = yama_task_prctl, - .task_free = yama_task_free, + LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check), + LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme), + LSM_HOOK_INIT(task_prctl, yama_task_prctl), + LSM_HOOK_INIT(task_free, yama_task_free), }; #endif -- cgit v1.2.3-59-g8ed1b From b1d9e6b0646d0e5ee5d9050bd236b6c65d66faef Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Sat, 2 May 2015 15:11:42 -0700 Subject: LSM: Switch to lists of hooks Instead of using a vector of security operations with explicit, special case stacking of the capability and yama hooks use lists of hooks with capability and yama hooks included as appropriate. The security_operations structure is no longer required. Instead, there is a union of the function pointers that allows all the hooks lists to use a common mechanism for list management while retaining typing. Each module supplies an array describing the hooks it provides instead of a sparsely populated security_operations structure. The description includes the element that gets put on the hook list, avoiding the issues surrounding individual element allocation. The method for registering security modules is changed to reflect the information available. The method for removing a module, currently only used by SELinux, has also changed. It should be generic now, however if there are potential race conditions based on ordering of hook removal that needs to be addressed by the calling module. The security hooks are called from the lists and the first failure is returned. Signed-off-by: Casey Schaufler Acked-by: John Johansen Acked-by: Kees Cook Acked-by: Paul Moore Acked-by: Stephen Smalley Acked-by: Tetsuo Handa Signed-off-by: James Morris --- include/linux/lsm_hooks.h | 77 ++++-- include/linux/security.h | 46 +--- security/Makefile | 2 +- security/apparmor/domain.c | 12 +- security/apparmor/lsm.c | 51 ++-- security/commoncap.c | 41 +++- security/security.c | 570 +++++++++++++++++++++++++++++++++++++-------- security/selinux/hooks.c | 94 ++------ security/smack/smack.h | 2 - security/smack/smack_lsm.c | 53 +---- security/smack/smackfs.c | 2 +- security/tomoyo/tomoyo.c | 14 +- security/yama/yama_lsm.c | 50 ++-- 13 files changed, 627 insertions(+), 387 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 27dd6fcacccc..f014f2596e22 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -25,21 +25,10 @@ #define __LINUX_LSM_HOOKS_H #include - -/* Maximum number of letters for an LSM name string */ -#define SECURITY_NAME_MAX 10 - -#ifdef CONFIG_SECURITY +#include +#include /** - * struct security_operations - main security structure - * - * Security module identifier. - * - * @name: - * A string that acts as a unique identifier for the LSM with max number - * of characters = SECURITY_NAME_MAX. - * * Security hooks for program execution operations. * * @bprm_set_creds: @@ -1310,9 +1299,7 @@ * This is the main security structure. */ -struct security_operations { - char name[SECURITY_NAME_MAX + 1]; - +union security_list_options { int (*binder_set_context_mgr)(struct task_struct *mgr); int (*binder_transaction)(struct task_struct *from, struct task_struct *to); @@ -1837,21 +1824,63 @@ struct security_hook_heads { #endif /* CONFIG_AUDIT */ }; +/* + * Security module hook list structure. + * For use with generic list macros for common operations. + */ +struct security_hook_list { + struct list_head list; + struct list_head *head; + union security_list_options hook; +}; + /* * Initializing a security_hook_list structure takes * up a lot of space in a source file. This macro takes * care of the common case and reduces the amount of * text involved. - * Casey says: Comment is true in the next patch. */ -#define LSM_HOOK_INIT(HEAD, HOOK) .HEAD = HOOK +#define LSM_HOOK_INIT(HEAD, HOOK) \ + { .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } } + +extern struct security_hook_heads security_hook_heads; + +static inline void security_add_hooks(struct security_hook_list *hooks, + int count) +{ + int i; -/* prototypes */ -extern int security_module_enable(struct security_operations *ops); -extern int register_security(struct security_operations *ops); -extern void __init security_fixup_ops(struct security_operations *ops); -extern void reset_security_ops(void); + for (i = 0; i < count; i++) + list_add_tail_rcu(&hooks[i].list, hooks[i].head); +} -#endif /* CONFIG_SECURITY */ +#ifdef CONFIG_SECURITY_SELINUX_DISABLE +/* + * Assuring the safety of deleting a security module is up to + * the security module involved. This may entail ordering the + * module's hook list in a particular way, refusing to disable + * the module once a policy is loaded or any number of other + * actions better imagined than described. + * + * The name of the configuration option reflects the only module + * that currently uses the mechanism. Any developer who thinks + * disabling their module is a good idea needs to be at least as + * careful as the SELinux team. + */ +static inline void security_delete_hooks(struct security_hook_list *hooks, + int count) +{ + int i; + + for (i = 0; i < count; i++) + list_del_rcu(&hooks[i].list); +} +#endif /* CONFIG_SECURITY_SELINUX_DISABLE */ + +extern int __init security_module_enable(const char *module); +extern void __init capability_add_hooks(void); +#ifdef CONFIG_SECURITY_YAMA_STACKED +void __init yama_add_hooks(void); +#endif #endif /* ! __LINUX_LSM_HOOKS_H */ diff --git a/include/linux/security.h b/include/linux/security.h index a2a100e7ac6e..8c8175d41b4c 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -27,6 +27,7 @@ #include #include #include +#include struct linux_binprm; struct cred; @@ -54,9 +55,6 @@ struct xattr; struct xfrm_sec_ctx; struct mm_struct; -/* Maximum number of letters for an LSM name string */ -#define SECURITY_NAME_MAX 10 - /* If capable should audit the security request */ #define SECURITY_CAP_NOAUDIT 0 #define SECURITY_CAP_AUDIT 1 @@ -69,10 +67,7 @@ struct audit_krule; struct user_namespace; struct timezone; -/* - * These functions are in security/capability.c and are used - * as the default capabilities functions - */ +/* These functions are in security/commoncap.c */ extern int cap_capable(const struct cred *cred, struct user_namespace *ns, int cap, int audit); extern int cap_settime(const struct timespec *ts, const struct timezone *tz); @@ -114,8 +109,6 @@ struct xfrm_state; struct xfrm_user_sec_ctx; struct seq_file; -extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb); - #ifdef CONFIG_MMU extern unsigned long mmap_min_addr; extern unsigned long dac_mmap_min_addr; @@ -472,7 +465,7 @@ static inline int security_settime(const struct timespec *ts, static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) { - return cap_vm_enough_memory(mm, pages); + return __vm_enough_memory(mm, pages, cap_vm_enough_memory(mm, pages)); } static inline int security_bprm_set_creds(struct linux_binprm *bprm) @@ -1075,7 +1068,7 @@ static inline int security_setprocattr(struct task_struct *p, char *name, void * static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb) { - return cap_netlink_send(sk, skb); + return 0; } static inline int security_ismaclabel(const char *name) @@ -1643,36 +1636,5 @@ static inline void free_secdata(void *secdata) { } #endif /* CONFIG_SECURITY */ -#ifdef CONFIG_SECURITY_YAMA -extern int yama_ptrace_access_check(struct task_struct *child, - unsigned int mode); -extern int yama_ptrace_traceme(struct task_struct *parent); -extern void yama_task_free(struct task_struct *task); -extern int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5); -#else -static inline int yama_ptrace_access_check(struct task_struct *child, - unsigned int mode) -{ - return 0; -} - -static inline int yama_ptrace_traceme(struct task_struct *parent) -{ - return 0; -} - -static inline void yama_task_free(struct task_struct *task) -{ -} - -static inline int yama_task_prctl(int option, unsigned long arg2, - unsigned long arg3, unsigned long arg4, - unsigned long arg5) -{ - return -ENOSYS; -} -#endif /* CONFIG_SECURITY_YAMA */ - #endif /* ! __LINUX_SECURITY_H */ diff --git a/security/Makefile b/security/Makefile index 05f1c934d74b..c9bfbc84ff50 100644 --- a/security/Makefile +++ b/security/Makefile @@ -14,7 +14,7 @@ obj-y += commoncap.o obj-$(CONFIG_MMU) += min_addr.o # Object file lists -obj-$(CONFIG_SECURITY) += security.o capability.o +obj-$(CONFIG_SECURITY) += security.o obj-$(CONFIG_SECURITYFS) += inode.o obj-$(CONFIG_SECURITY_SELINUX) += selinux/ obj-$(CONFIG_SECURITY_SMACK) += smack/ diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index d97cba3e3849..dc0027b28b04 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -347,9 +347,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) file_inode(bprm->file)->i_mode }; const char *name = NULL, *target = NULL, *info = NULL; - int error = cap_bprm_set_creds(bprm); - if (error) - return error; + int error = 0; if (bprm->cred_prepared) return 0; @@ -531,15 +529,13 @@ cleanup: */ int apparmor_bprm_secureexec(struct linux_binprm *bprm) { - int ret = cap_bprm_secureexec(bprm); - /* the decision to use secure exec is computed in set_creds * and stored in bprm->unsafe. */ - if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED)) - ret = 1; + if (bprm->unsafe & AA_SECURE_X_NEEDED) + return 1; - return ret; + return 0; } /** diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index f54253258fb8..5696874e8062 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -96,19 +96,11 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old) static int apparmor_ptrace_access_check(struct task_struct *child, unsigned int mode) { - int error = cap_ptrace_access_check(child, mode); - if (error) - return error; - return aa_ptrace(current, child, mode); } static int apparmor_ptrace_traceme(struct task_struct *parent) { - int error = cap_ptrace_traceme(parent); - if (error) - return error; - return aa_ptrace(parent, current, PTRACE_MODE_ATTACH); } @@ -123,10 +115,10 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, cred = __task_cred(target); profile = aa_cred_profile(cred); - *effective = cred->cap_effective; - *inheritable = cred->cap_inheritable; - *permitted = cred->cap_permitted; - + /* + * cap_capget is stacked ahead of this and will + * initialize effective and permitted. + */ if (!unconfined(profile) && !COMPLAIN_MODE(profile)) { *effective = cap_intersect(*effective, profile->caps.allow); *permitted = cap_intersect(*permitted, profile->caps.allow); @@ -140,13 +132,11 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, int cap, int audit) { struct aa_profile *profile; - /* cap_capable returns 0 on success, else -EPERM */ - int error = cap_capable(cred, ns, cap, audit); - if (!error) { - profile = aa_cred_profile(cred); - if (!unconfined(profile)) - error = aa_capable(profile, cap, audit); - } + int error = 0; + + profile = aa_cred_profile(cred); + if (!unconfined(profile)) + error = aa_capable(profile, cap, audit); return error; } @@ -615,9 +605,7 @@ static int apparmor_task_setrlimit(struct task_struct *task, return error; } -static struct security_operations apparmor_ops = { - LSM_HOOK_INIT(name, "apparmor"), - +static struct security_hook_list apparmor_hooks[] = { LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), LSM_HOOK_INIT(capget, apparmor_capget), @@ -640,7 +628,6 @@ static struct security_operations apparmor_ops = { LSM_HOOK_INIT(file_alloc_security, apparmor_file_alloc_security), LSM_HOOK_INIT(file_free_security, apparmor_file_free_security), LSM_HOOK_INIT(mmap_file, apparmor_mmap_file), - LSM_HOOK_INIT(mmap_addr, cap_mmap_addr), LSM_HOOK_INIT(file_mprotect, apparmor_file_mprotect), LSM_HOOK_INIT(file_lock, apparmor_file_lock), @@ -898,7 +885,7 @@ static int __init apparmor_init(void) { int error; - if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) { + if (!apparmor_enabled || !security_module_enable("apparmor")) { aa_info_message("AppArmor disabled by boot time parameter"); apparmor_enabled = 0; return 0; @@ -913,17 +900,10 @@ static int __init apparmor_init(void) error = set_init_cxt(); if (error) { AA_ERROR("Failed to set context on init task\n"); - goto register_security_out; - } - - error = register_security(&apparmor_ops); - if (error) { - struct cred *cred = (struct cred *)current->real_cred; - aa_free_task_context(cred_cxt(cred)); - cred_cxt(cred) = NULL; - AA_ERROR("Unable to register AppArmor\n"); - goto register_security_out; + aa_free_root_ns(); + goto alloc_out; } + security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks)); /* Report that AppArmor successfully initialized */ apparmor_initialized = 1; @@ -936,9 +916,6 @@ static int __init apparmor_init(void) return error; -register_security_out: - aa_free_root_ns(); - alloc_out: aa_destroy_aafs(); diff --git a/security/commoncap.c b/security/commoncap.c index f2875cd9f677..d103f5a4043d 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -53,11 +53,6 @@ static void warn_setuid_and_fcaps_mixed(const char *fname) } } -int cap_netlink_send(struct sock *sk, struct sk_buff *skb) -{ - return 0; -} - /** * cap_capable - Determine whether a task has a particular effective capability * @cred: The credentials to use @@ -941,7 +936,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, * @pages: The size of the mapping * * Determine whether the allocation of a new virtual mapping by the current - * task is permitted, returning 0 if permission is granted, -ve if not. + * task is permitted, returning 1 if permission is granted, 0 if not. */ int cap_vm_enough_memory(struct mm_struct *mm, long pages) { @@ -950,7 +945,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages) if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT) == 0) cap_sys_admin = 1; - return __vm_enough_memory(mm, pages, cap_sys_admin); + return cap_sys_admin; } /* @@ -981,3 +976,33 @@ int cap_mmap_file(struct file *file, unsigned long reqprot, { return 0; } + +#ifdef CONFIG_SECURITY + +struct security_hook_list capability_hooks[] = { + LSM_HOOK_INIT(capable, cap_capable), + LSM_HOOK_INIT(settime, cap_settime), + LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check), + LSM_HOOK_INIT(ptrace_traceme, cap_ptrace_traceme), + LSM_HOOK_INIT(capget, cap_capget), + LSM_HOOK_INIT(capset, cap_capset), + LSM_HOOK_INIT(bprm_set_creds, cap_bprm_set_creds), + LSM_HOOK_INIT(bprm_secureexec, cap_bprm_secureexec), + LSM_HOOK_INIT(inode_need_killpriv, cap_inode_need_killpriv), + LSM_HOOK_INIT(inode_killpriv, cap_inode_killpriv), + LSM_HOOK_INIT(mmap_addr, cap_mmap_addr), + LSM_HOOK_INIT(mmap_file, cap_mmap_file), + LSM_HOOK_INIT(task_fix_setuid, cap_task_fix_setuid), + LSM_HOOK_INIT(task_prctl, cap_task_prctl), + LSM_HOOK_INIT(task_setscheduler, cap_task_setscheduler), + LSM_HOOK_INIT(task_setioprio, cap_task_setioprio), + LSM_HOOK_INIT(task_setnice, cap_task_setnice), + LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory), +}; + +void __init capability_add_hooks(void) +{ + security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks)); +} + +#endif /* CONFIG_SECURITY */ diff --git a/security/security.c b/security/security.c index 02dc72006afa..bd4c5f6a5b78 100644 --- a/security/security.c +++ b/security/security.c @@ -29,24 +29,13 @@ #define MAX_LSM_EVM_XATTR 2 +/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10 + /* Boot-time LSM user choice */ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = CONFIG_DEFAULT_SECURITY; -static struct security_operations *security_ops; -static struct security_operations default_security_ops = { - .name = "default", -}; - -static inline int __init verify(struct security_operations *ops) -{ - /* verify the security_operations structure exists */ - if (!ops) - return -EINVAL; - security_fixup_ops(ops); - return 0; -} - static void __init do_security_initcalls(void) { initcall_t *call; @@ -64,20 +53,27 @@ static void __init do_security_initcalls(void) */ int __init security_init(void) { - printk(KERN_INFO "Security Framework initialized\n"); + pr_info("Security Framework initialized\n"); - security_fixup_ops(&default_security_ops); - security_ops = &default_security_ops; + /* + * Always load the capability module. + */ + capability_add_hooks(); +#ifdef CONFIG_SECURITY_YAMA_STACKED + /* + * If Yama is configured for stacking load it next. + */ + yama_add_hooks(); +#endif + /* + * Load the chosen module if there is one. + * This will also find yama if it is stacking + */ do_security_initcalls(); return 0; } -void reset_security_ops(void) -{ - security_ops = &default_security_ops; -} - /* Save user chosen LSM */ static int __init choose_lsm(char *str) { @@ -88,7 +84,7 @@ __setup("security=", choose_lsm); /** * security_module_enable - Load given security module on boot ? - * @ops: a pointer to the struct security_operations that is to be checked. + * @module: the name of the module * * Each LSM must pass this method before registering its own operations * to avoid security registration races. This method may also be used @@ -100,41 +96,13 @@ __setup("security=", choose_lsm); * choose an alternate LSM at boot time. * Otherwise, return false. */ -int __init security_module_enable(struct security_operations *ops) +int __init security_module_enable(const char *module) { - return !strcmp(ops->name, chosen_lsm); -} - -/** - * register_security - registers a security framework with the kernel - * @ops: a pointer to the struct security_options that is to be registered - * - * This function allows a security module to register itself with the - * kernel security subsystem. Some rudimentary checking is done on the @ops - * value passed to this function. You'll need to check first if your LSM - * is allowed to register its @ops by calling security_module_enable(@ops). - * - * If there is already a security module registered with the kernel, - * an error will be returned. Otherwise %0 is returned on success. - */ -int __init register_security(struct security_operations *ops) -{ - if (verify(ops)) { - printk(KERN_DEBUG "%s could not verify " - "security_operations structure.\n", __func__); - return -EINVAL; - } - - if (security_ops != &default_security_ops) - return -EAGAIN; - - security_ops = ops; - - return 0; + return !strcmp(module, chosen_lsm); } /* - * Hook operation macros. + * Hook list operation macros. * * call_void_hook: * This is a hook that does not return a value. @@ -143,8 +111,27 @@ int __init register_security(struct security_operations *ops) * This is a hook that returns a value. */ -#define call_void_hook(FUNC, ...) security_ops->FUNC(__VA_ARGS__) -#define call_int_hook(FUNC, IRC, ...) security_ops->FUNC(__VA_ARGS__) +#define call_void_hook(FUNC, ...) \ + do { \ + struct security_hook_list *P; \ + \ + list_for_each_entry(P, &security_hook_heads.FUNC, list) \ + P->hook.FUNC(__VA_ARGS__); \ + } while (0) + +#define call_int_hook(FUNC, IRC, ...) ({ \ + int RC = IRC; \ + do { \ + struct security_hook_list *P; \ + \ + list_for_each_entry(P, &security_hook_heads.FUNC, list) { \ + RC = P->hook.FUNC(__VA_ARGS__); \ + if (RC != 0) \ + break; \ + } \ + } while (0); \ + RC; \ +}) /* Security operations */ @@ -173,23 +160,11 @@ int security_binder_transfer_file(struct task_struct *from, int security_ptrace_access_check(struct task_struct *child, unsigned int mode) { -#ifdef CONFIG_SECURITY_YAMA_STACKED - int rc; - rc = yama_ptrace_access_check(child, mode); - if (rc) - return rc; -#endif return call_int_hook(ptrace_access_check, 0, child, mode); } int security_ptrace_traceme(struct task_struct *parent) { -#ifdef CONFIG_SECURITY_YAMA_STACKED - int rc; - rc = yama_ptrace_traceme(parent); - if (rc) - return rc; -#endif return call_int_hook(ptrace_traceme, 0, parent); } @@ -245,7 +220,25 @@ int security_settime(const struct timespec *ts, const struct timezone *tz) int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) { - return call_int_hook(vm_enough_memory, 0, mm, pages); + struct security_hook_list *hp; + int cap_sys_admin = 1; + int rc; + + /* + * The module will respond with a positive value if + * it thinks the __vm_enough_memory() call should be + * made with the cap_sys_admin set. If all of the modules + * agree that it should be set it will. If any module + * thinks it should not be set it won't. + */ + list_for_each_entry(hp, &security_hook_heads.vm_enough_memory, list) { + rc = hp->hook.vm_enough_memory(mm, pages); + if (rc <= 0) { + cap_sys_admin = 0; + break; + } + } + return __vm_enough_memory(mm, pages, cap_sys_admin); } int security_bprm_set_creds(struct linux_binprm *bprm) @@ -335,8 +328,9 @@ int security_sb_set_mnt_opts(struct super_block *sb, unsigned long kern_flags, unsigned long *set_kern_flags) { - return call_int_hook(sb_set_mnt_opts, 0, sb, opts, kern_flags, - set_kern_flags); + return call_int_hook(sb_set_mnt_opts, + opts->num_mnt_opts ? -EOPNOTSUPP : 0, sb, + opts, kern_flags, set_kern_flags); } EXPORT_SYMBOL(security_sb_set_mnt_opts); @@ -369,8 +363,8 @@ int security_dentry_init_security(struct dentry *dentry, int mode, struct qstr *name, void **ctx, u32 *ctxlen) { - return call_int_hook(dentry_init_security, 0, dentry, mode, name, - ctx, ctxlen); + return call_int_hook(dentry_init_security, -EOPNOTSUPP, dentry, mode, + name, ctx, ctxlen); } EXPORT_SYMBOL(security_dentry_init_security); @@ -390,7 +384,7 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, NULL, NULL, NULL); memset(new_xattrs, 0, sizeof(new_xattrs)); lsm_xattr = new_xattrs; - ret = call_int_hook(inode_init_security, 0, inode, dir, qstr, + ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr, &lsm_xattr->name, &lsm_xattr->value, &lsm_xattr->value_len); @@ -636,8 +630,15 @@ int security_inode_setxattr(struct dentry *dentry, const char *name, if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - ret = call_int_hook(inode_setxattr, 0, dentry, name, value, size, + /* + * SELinux and Smack integrate the cap call, + * so assume that all LSMs supplying this call do so. + */ + ret = call_int_hook(inode_setxattr, 1, dentry, name, value, size, flags); + + if (ret == 1) + ret = cap_inode_setxattr(dentry, name, value, size, flags); if (ret) return ret; ret = ima_inode_setxattr(dentry, name, value, size); @@ -675,7 +676,13 @@ int security_inode_removexattr(struct dentry *dentry, const char *name) if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - ret = call_int_hook(inode_removexattr, 0, dentry, name); + /* + * SELinux and Smack integrate the cap call, + * so assume that all LSMs supplying this call do so. + */ + ret = call_int_hook(inode_removexattr, 1, dentry, name); + if (ret == 1) + ret = cap_inode_removexattr(dentry, name); if (ret) return ret; ret = ima_inode_removexattr(dentry, name); @@ -698,15 +705,16 @@ int security_inode_getsecurity(const struct inode *inode, const char *name, void { if (unlikely(IS_PRIVATE(inode))) return -EOPNOTSUPP; - return call_int_hook(inode_getsecurity, 0, inode, name, buffer, alloc); + return call_int_hook(inode_getsecurity, -EOPNOTSUPP, inode, name, + buffer, alloc); } int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) { if (unlikely(IS_PRIVATE(inode))) return -EOPNOTSUPP; - return call_int_hook(inode_setsecurity, 0, inode, name, value, size, - flags); + return call_int_hook(inode_setsecurity, -EOPNOTSUPP, inode, name, + value, size, flags); } int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) @@ -847,9 +855,6 @@ int security_task_create(unsigned long clone_flags) void security_task_free(struct task_struct *task) { -#ifdef CONFIG_SECURITY_YAMA_STACKED - yama_task_free(task); -#endif call_void_hook(task_free, task); } @@ -932,6 +937,7 @@ int security_task_getsid(struct task_struct *p) void security_task_getsecid(struct task_struct *p, u32 *secid) { + *secid = 0; call_void_hook(task_getsecid, p, secid); } EXPORT_SYMBOL(security_task_getsecid); @@ -986,13 +992,19 @@ int security_task_wait(struct task_struct *p) int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { -#ifdef CONFIG_SECURITY_YAMA_STACKED - int rc; - rc = yama_task_prctl(option, arg2, arg3, arg4, arg5); - if (rc != -ENOSYS) - return rc; -#endif - return call_int_hook(task_prctl, 0, option, arg2, arg3, arg4, arg5); + int thisrc; + int rc = -ENOSYS; + struct security_hook_list *hp; + + list_for_each_entry(hp, &security_hook_heads.task_prctl, list) { + thisrc = hp->hook.task_prctl(option, arg2, arg3, arg4, arg5); + if (thisrc != -ENOSYS) { + rc = thisrc; + if (thisrc != 0) + break; + } + } + return rc; } void security_task_to_inode(struct task_struct *p, struct inode *inode) @@ -1007,6 +1019,7 @@ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag) void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) { + *secid = 0; call_void_hook(ipc_getsecid, ipcp, secid); } @@ -1113,12 +1126,12 @@ EXPORT_SYMBOL(security_d_instantiate); int security_getprocattr(struct task_struct *p, char *name, char **value) { - return call_int_hook(getprocattr, 0, p, name, value); + return call_int_hook(getprocattr, -EINVAL, p, name, value); } int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size) { - return call_int_hook(setprocattr, 0, p, name, value, size); + return call_int_hook(setprocattr, -EINVAL, p, name, value, size); } int security_netlink_send(struct sock *sk, struct sk_buff *skb) @@ -1134,12 +1147,14 @@ EXPORT_SYMBOL(security_ismaclabel); int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { - return call_int_hook(secid_to_secctx, 0, secid, secdata, seclen); + return call_int_hook(secid_to_secctx, -EOPNOTSUPP, secid, secdata, + seclen); } EXPORT_SYMBOL(security_secid_to_secctx); int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) { + *secid = 0; return call_int_hook(secctx_to_secid, 0, secdata, seclen, secid); } EXPORT_SYMBOL(security_secctx_to_secid); @@ -1164,7 +1179,7 @@ EXPORT_SYMBOL(security_inode_setsecctx); int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) { - return call_int_hook(inode_getsecctx, 0, inode, ctx, ctxlen); + return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, ctx, ctxlen); } EXPORT_SYMBOL(security_inode_getsecctx); @@ -1259,8 +1274,8 @@ EXPORT_SYMBOL(security_sock_rcv_skb); int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, int __user *optlen, unsigned len) { - return call_int_hook(socket_getpeersec_stream, 0, sock, optval, - optlen, len); + return call_int_hook(socket_getpeersec_stream, -ENOPROTOOPT, sock, + optval, optlen, len); } int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) @@ -1438,7 +1453,24 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp, const struct flowi *fl) { - return call_int_hook(xfrm_state_pol_flow_match, 0, x, xp, fl); + struct security_hook_list *hp; + int rc = 1; + + /* + * Since this function is expected to return 0 or 1, the judgment + * becomes difficult if multiple LSMs supply this call. Fortunately, + * we can use the first LSM's judgment because currently only SELinux + * supplies this call. + * + * For speed optimization, we explicitly break the loop rather than + * using the macro + */ + list_for_each_entry(hp, &security_hook_heads.xfrm_state_pol_flow_match, + list) { + rc = hp->hook.xfrm_state_pol_flow_match(x, xp, fl); + break; + } + return rc; } int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) @@ -1478,6 +1510,7 @@ int security_key_permission(key_ref_t key_ref, int security_key_getsecurity(struct key *key, char **_buffer) { + *_buffer = NULL; return call_int_hook(key_getsecurity, 0, key, _buffer); } @@ -1506,5 +1539,350 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule, actx); } +#endif /* CONFIG_AUDIT */ +struct security_hook_heads security_hook_heads = { + .binder_set_context_mgr = + LIST_HEAD_INIT(security_hook_heads.binder_set_context_mgr), + .binder_transaction = + LIST_HEAD_INIT(security_hook_heads.binder_transaction), + .binder_transfer_binder = + LIST_HEAD_INIT(security_hook_heads.binder_transfer_binder), + .binder_transfer_file = + LIST_HEAD_INIT(security_hook_heads.binder_transfer_file), + + .ptrace_access_check = + LIST_HEAD_INIT(security_hook_heads.ptrace_access_check), + .ptrace_traceme = + LIST_HEAD_INIT(security_hook_heads.ptrace_traceme), + .capget = LIST_HEAD_INIT(security_hook_heads.capget), + .capset = LIST_HEAD_INIT(security_hook_heads.capset), + .capable = LIST_HEAD_INIT(security_hook_heads.capable), + .quotactl = LIST_HEAD_INIT(security_hook_heads.quotactl), + .quota_on = LIST_HEAD_INIT(security_hook_heads.quota_on), + .syslog = LIST_HEAD_INIT(security_hook_heads.syslog), + .settime = LIST_HEAD_INIT(security_hook_heads.settime), + .vm_enough_memory = + LIST_HEAD_INIT(security_hook_heads.vm_enough_memory), + .bprm_set_creds = + LIST_HEAD_INIT(security_hook_heads.bprm_set_creds), + .bprm_check_security = + LIST_HEAD_INIT(security_hook_heads.bprm_check_security), + .bprm_secureexec = + LIST_HEAD_INIT(security_hook_heads.bprm_secureexec), + .bprm_committing_creds = + LIST_HEAD_INIT(security_hook_heads.bprm_committing_creds), + .bprm_committed_creds = + LIST_HEAD_INIT(security_hook_heads.bprm_committed_creds), + .sb_alloc_security = + LIST_HEAD_INIT(security_hook_heads.sb_alloc_security), + .sb_free_security = + LIST_HEAD_INIT(security_hook_heads.sb_free_security), + .sb_copy_data = LIST_HEAD_INIT(security_hook_heads.sb_copy_data), + .sb_remount = LIST_HEAD_INIT(security_hook_heads.sb_remount), + .sb_kern_mount = + LIST_HEAD_INIT(security_hook_heads.sb_kern_mount), + .sb_show_options = + LIST_HEAD_INIT(security_hook_heads.sb_show_options), + .sb_statfs = LIST_HEAD_INIT(security_hook_heads.sb_statfs), + .sb_mount = LIST_HEAD_INIT(security_hook_heads.sb_mount), + .sb_umount = LIST_HEAD_INIT(security_hook_heads.sb_umount), + .sb_pivotroot = LIST_HEAD_INIT(security_hook_heads.sb_pivotroot), + .sb_set_mnt_opts = + LIST_HEAD_INIT(security_hook_heads.sb_set_mnt_opts), + .sb_clone_mnt_opts = + LIST_HEAD_INIT(security_hook_heads.sb_clone_mnt_opts), + .sb_parse_opts_str = + LIST_HEAD_INIT(security_hook_heads.sb_parse_opts_str), + .dentry_init_security = + LIST_HEAD_INIT(security_hook_heads.dentry_init_security), +#ifdef CONFIG_SECURITY_PATH + .path_unlink = LIST_HEAD_INIT(security_hook_heads.path_unlink), + .path_mkdir = LIST_HEAD_INIT(security_hook_heads.path_mkdir), + .path_rmdir = LIST_HEAD_INIT(security_hook_heads.path_rmdir), + .path_mknod = LIST_HEAD_INIT(security_hook_heads.path_mknod), + .path_truncate = + LIST_HEAD_INIT(security_hook_heads.path_truncate), + .path_symlink = LIST_HEAD_INIT(security_hook_heads.path_symlink), + .path_link = LIST_HEAD_INIT(security_hook_heads.path_link), + .path_rename = LIST_HEAD_INIT(security_hook_heads.path_rename), + .path_chmod = LIST_HEAD_INIT(security_hook_heads.path_chmod), + .path_chown = LIST_HEAD_INIT(security_hook_heads.path_chown), + .path_chroot = LIST_HEAD_INIT(security_hook_heads.path_chroot), +#endif + .inode_alloc_security = + LIST_HEAD_INIT(security_hook_heads.inode_alloc_security), + .inode_free_security = + LIST_HEAD_INIT(security_hook_heads.inode_free_security), + .inode_init_security = + LIST_HEAD_INIT(security_hook_heads.inode_init_security), + .inode_create = LIST_HEAD_INIT(security_hook_heads.inode_create), + .inode_link = LIST_HEAD_INIT(security_hook_heads.inode_link), + .inode_unlink = LIST_HEAD_INIT(security_hook_heads.inode_unlink), + .inode_symlink = + LIST_HEAD_INIT(security_hook_heads.inode_symlink), + .inode_mkdir = LIST_HEAD_INIT(security_hook_heads.inode_mkdir), + .inode_rmdir = LIST_HEAD_INIT(security_hook_heads.inode_rmdir), + .inode_mknod = LIST_HEAD_INIT(security_hook_heads.inode_mknod), + .inode_rename = LIST_HEAD_INIT(security_hook_heads.inode_rename), + .inode_readlink = + LIST_HEAD_INIT(security_hook_heads.inode_readlink), + .inode_follow_link = + LIST_HEAD_INIT(security_hook_heads.inode_follow_link), + .inode_permission = + LIST_HEAD_INIT(security_hook_heads.inode_permission), + .inode_setattr = + LIST_HEAD_INIT(security_hook_heads.inode_setattr), + .inode_getattr = + LIST_HEAD_INIT(security_hook_heads.inode_getattr), + .inode_setxattr = + LIST_HEAD_INIT(security_hook_heads.inode_setxattr), + .inode_post_setxattr = + LIST_HEAD_INIT(security_hook_heads.inode_post_setxattr), + .inode_getxattr = + LIST_HEAD_INIT(security_hook_heads.inode_getxattr), + .inode_listxattr = + LIST_HEAD_INIT(security_hook_heads.inode_listxattr), + .inode_removexattr = + LIST_HEAD_INIT(security_hook_heads.inode_removexattr), + .inode_need_killpriv = + LIST_HEAD_INIT(security_hook_heads.inode_need_killpriv), + .inode_killpriv = + LIST_HEAD_INIT(security_hook_heads.inode_killpriv), + .inode_getsecurity = + LIST_HEAD_INIT(security_hook_heads.inode_getsecurity), + .inode_setsecurity = + LIST_HEAD_INIT(security_hook_heads.inode_setsecurity), + .inode_listsecurity = + LIST_HEAD_INIT(security_hook_heads.inode_listsecurity), + .inode_getsecid = + LIST_HEAD_INIT(security_hook_heads.inode_getsecid), + .file_permission = + LIST_HEAD_INIT(security_hook_heads.file_permission), + .file_alloc_security = + LIST_HEAD_INIT(security_hook_heads.file_alloc_security), + .file_free_security = + LIST_HEAD_INIT(security_hook_heads.file_free_security), + .file_ioctl = LIST_HEAD_INIT(security_hook_heads.file_ioctl), + .mmap_addr = LIST_HEAD_INIT(security_hook_heads.mmap_addr), + .mmap_file = LIST_HEAD_INIT(security_hook_heads.mmap_file), + .file_mprotect = + LIST_HEAD_INIT(security_hook_heads.file_mprotect), + .file_lock = LIST_HEAD_INIT(security_hook_heads.file_lock), + .file_fcntl = LIST_HEAD_INIT(security_hook_heads.file_fcntl), + .file_set_fowner = + LIST_HEAD_INIT(security_hook_heads.file_set_fowner), + .file_send_sigiotask = + LIST_HEAD_INIT(security_hook_heads.file_send_sigiotask), + .file_receive = LIST_HEAD_INIT(security_hook_heads.file_receive), + .file_open = LIST_HEAD_INIT(security_hook_heads.file_open), + .task_create = LIST_HEAD_INIT(security_hook_heads.task_create), + .task_free = LIST_HEAD_INIT(security_hook_heads.task_free), + .cred_alloc_blank = + LIST_HEAD_INIT(security_hook_heads.cred_alloc_blank), + .cred_free = LIST_HEAD_INIT(security_hook_heads.cred_free), + .cred_prepare = LIST_HEAD_INIT(security_hook_heads.cred_prepare), + .cred_transfer = + LIST_HEAD_INIT(security_hook_heads.cred_transfer), + .kernel_act_as = + LIST_HEAD_INIT(security_hook_heads.kernel_act_as), + .kernel_create_files_as = + LIST_HEAD_INIT(security_hook_heads.kernel_create_files_as), + .kernel_fw_from_file = + LIST_HEAD_INIT(security_hook_heads.kernel_fw_from_file), + .kernel_module_request = + LIST_HEAD_INIT(security_hook_heads.kernel_module_request), + .kernel_module_from_file = + LIST_HEAD_INIT(security_hook_heads.kernel_module_from_file), + .task_fix_setuid = + LIST_HEAD_INIT(security_hook_heads.task_fix_setuid), + .task_setpgid = LIST_HEAD_INIT(security_hook_heads.task_setpgid), + .task_getpgid = LIST_HEAD_INIT(security_hook_heads.task_getpgid), + .task_getsid = LIST_HEAD_INIT(security_hook_heads.task_getsid), + .task_getsecid = + LIST_HEAD_INIT(security_hook_heads.task_getsecid), + .task_setnice = LIST_HEAD_INIT(security_hook_heads.task_setnice), + .task_setioprio = + LIST_HEAD_INIT(security_hook_heads.task_setioprio), + .task_getioprio = + LIST_HEAD_INIT(security_hook_heads.task_getioprio), + .task_setrlimit = + LIST_HEAD_INIT(security_hook_heads.task_setrlimit), + .task_setscheduler = + LIST_HEAD_INIT(security_hook_heads.task_setscheduler), + .task_getscheduler = + LIST_HEAD_INIT(security_hook_heads.task_getscheduler), + .task_movememory = + LIST_HEAD_INIT(security_hook_heads.task_movememory), + .task_kill = LIST_HEAD_INIT(security_hook_heads.task_kill), + .task_wait = LIST_HEAD_INIT(security_hook_heads.task_wait), + .task_prctl = LIST_HEAD_INIT(security_hook_heads.task_prctl), + .task_to_inode = + LIST_HEAD_INIT(security_hook_heads.task_to_inode), + .ipc_permission = + LIST_HEAD_INIT(security_hook_heads.ipc_permission), + .ipc_getsecid = LIST_HEAD_INIT(security_hook_heads.ipc_getsecid), + .msg_msg_alloc_security = + LIST_HEAD_INIT(security_hook_heads.msg_msg_alloc_security), + .msg_msg_free_security = + LIST_HEAD_INIT(security_hook_heads.msg_msg_free_security), + .msg_queue_alloc_security = + LIST_HEAD_INIT(security_hook_heads.msg_queue_alloc_security), + .msg_queue_free_security = + LIST_HEAD_INIT(security_hook_heads.msg_queue_free_security), + .msg_queue_associate = + LIST_HEAD_INIT(security_hook_heads.msg_queue_associate), + .msg_queue_msgctl = + LIST_HEAD_INIT(security_hook_heads.msg_queue_msgctl), + .msg_queue_msgsnd = + LIST_HEAD_INIT(security_hook_heads.msg_queue_msgsnd), + .msg_queue_msgrcv = + LIST_HEAD_INIT(security_hook_heads.msg_queue_msgrcv), + .shm_alloc_security = + LIST_HEAD_INIT(security_hook_heads.shm_alloc_security), + .shm_free_security = + LIST_HEAD_INIT(security_hook_heads.shm_free_security), + .shm_associate = + LIST_HEAD_INIT(security_hook_heads.shm_associate), + .shm_shmctl = LIST_HEAD_INIT(security_hook_heads.shm_shmctl), + .shm_shmat = LIST_HEAD_INIT(security_hook_heads.shm_shmat), + .sem_alloc_security = + LIST_HEAD_INIT(security_hook_heads.sem_alloc_security), + .sem_free_security = + LIST_HEAD_INIT(security_hook_heads.sem_free_security), + .sem_associate = + LIST_HEAD_INIT(security_hook_heads.sem_associate), + .sem_semctl = LIST_HEAD_INIT(security_hook_heads.sem_semctl), + .sem_semop = LIST_HEAD_INIT(security_hook_heads.sem_semop), + .netlink_send = LIST_HEAD_INIT(security_hook_heads.netlink_send), + .d_instantiate = + LIST_HEAD_INIT(security_hook_heads.d_instantiate), + .getprocattr = LIST_HEAD_INIT(security_hook_heads.getprocattr), + .setprocattr = LIST_HEAD_INIT(security_hook_heads.setprocattr), + .ismaclabel = LIST_HEAD_INIT(security_hook_heads.ismaclabel), + .secid_to_secctx = + LIST_HEAD_INIT(security_hook_heads.secid_to_secctx), + .secctx_to_secid = + LIST_HEAD_INIT(security_hook_heads.secctx_to_secid), + .release_secctx = + LIST_HEAD_INIT(security_hook_heads.release_secctx), + .inode_notifysecctx = + LIST_HEAD_INIT(security_hook_heads.inode_notifysecctx), + .inode_setsecctx = + LIST_HEAD_INIT(security_hook_heads.inode_setsecctx), + .inode_getsecctx = + LIST_HEAD_INIT(security_hook_heads.inode_getsecctx), +#ifdef CONFIG_SECURITY_NETWORK + .unix_stream_connect = + LIST_HEAD_INIT(security_hook_heads.unix_stream_connect), + .unix_may_send = + LIST_HEAD_INIT(security_hook_heads.unix_may_send), + .socket_create = + LIST_HEAD_INIT(security_hook_heads.socket_create), + .socket_post_create = + LIST_HEAD_INIT(security_hook_heads.socket_post_create), + .socket_bind = LIST_HEAD_INIT(security_hook_heads.socket_bind), + .socket_connect = + LIST_HEAD_INIT(security_hook_heads.socket_connect), + .socket_listen = + LIST_HEAD_INIT(security_hook_heads.socket_listen), + .socket_accept = + LIST_HEAD_INIT(security_hook_heads.socket_accept), + .socket_sendmsg = + LIST_HEAD_INIT(security_hook_heads.socket_sendmsg), + .socket_recvmsg = + LIST_HEAD_INIT(security_hook_heads.socket_recvmsg), + .socket_getsockname = + LIST_HEAD_INIT(security_hook_heads.socket_getsockname), + .socket_getpeername = + LIST_HEAD_INIT(security_hook_heads.socket_getpeername), + .socket_getsockopt = + LIST_HEAD_INIT(security_hook_heads.socket_getsockopt), + .socket_setsockopt = + LIST_HEAD_INIT(security_hook_heads.socket_setsockopt), + .socket_shutdown = + LIST_HEAD_INIT(security_hook_heads.socket_shutdown), + .socket_sock_rcv_skb = + LIST_HEAD_INIT(security_hook_heads.socket_sock_rcv_skb), + .socket_getpeersec_stream = + LIST_HEAD_INIT(security_hook_heads.socket_getpeersec_stream), + .socket_getpeersec_dgram = + LIST_HEAD_INIT(security_hook_heads.socket_getpeersec_dgram), + .sk_alloc_security = + LIST_HEAD_INIT(security_hook_heads.sk_alloc_security), + .sk_free_security = + LIST_HEAD_INIT(security_hook_heads.sk_free_security), + .sk_clone_security = + LIST_HEAD_INIT(security_hook_heads.sk_clone_security), + .sk_getsecid = LIST_HEAD_INIT(security_hook_heads.sk_getsecid), + .sock_graft = LIST_HEAD_INIT(security_hook_heads.sock_graft), + .inet_conn_request = + LIST_HEAD_INIT(security_hook_heads.inet_conn_request), + .inet_csk_clone = + LIST_HEAD_INIT(security_hook_heads.inet_csk_clone), + .inet_conn_established = + LIST_HEAD_INIT(security_hook_heads.inet_conn_established), + .secmark_relabel_packet = + LIST_HEAD_INIT(security_hook_heads.secmark_relabel_packet), + .secmark_refcount_inc = + LIST_HEAD_INIT(security_hook_heads.secmark_refcount_inc), + .secmark_refcount_dec = + LIST_HEAD_INIT(security_hook_heads.secmark_refcount_dec), + .req_classify_flow = + LIST_HEAD_INIT(security_hook_heads.req_classify_flow), + .tun_dev_alloc_security = + LIST_HEAD_INIT(security_hook_heads.tun_dev_alloc_security), + .tun_dev_free_security = + LIST_HEAD_INIT(security_hook_heads.tun_dev_free_security), + .tun_dev_create = + LIST_HEAD_INIT(security_hook_heads.tun_dev_create), + .tun_dev_attach_queue = + LIST_HEAD_INIT(security_hook_heads.tun_dev_attach_queue), + .tun_dev_attach = + LIST_HEAD_INIT(security_hook_heads.tun_dev_attach), + .tun_dev_open = LIST_HEAD_INIT(security_hook_heads.tun_dev_open), + .skb_owned_by = LIST_HEAD_INIT(security_hook_heads.skb_owned_by), +#endif /* CONFIG_SECURITY_NETWORK */ +#ifdef CONFIG_SECURITY_NETWORK_XFRM + .xfrm_policy_alloc_security = + LIST_HEAD_INIT(security_hook_heads.xfrm_policy_alloc_security), + .xfrm_policy_clone_security = + LIST_HEAD_INIT(security_hook_heads.xfrm_policy_clone_security), + .xfrm_policy_free_security = + LIST_HEAD_INIT(security_hook_heads.xfrm_policy_free_security), + .xfrm_policy_delete_security = + LIST_HEAD_INIT(security_hook_heads.xfrm_policy_delete_security), + .xfrm_state_alloc = + LIST_HEAD_INIT(security_hook_heads.xfrm_state_alloc), + .xfrm_state_alloc_acquire = + LIST_HEAD_INIT(security_hook_heads.xfrm_state_alloc_acquire), + .xfrm_state_free_security = + LIST_HEAD_INIT(security_hook_heads.xfrm_state_free_security), + .xfrm_state_delete_security = + LIST_HEAD_INIT(security_hook_heads.xfrm_state_delete_security), + .xfrm_policy_lookup = + LIST_HEAD_INIT(security_hook_heads.xfrm_policy_lookup), + .xfrm_state_pol_flow_match = + LIST_HEAD_INIT(security_hook_heads.xfrm_state_pol_flow_match), + .xfrm_decode_session = + LIST_HEAD_INIT(security_hook_heads.xfrm_decode_session), +#endif /* CONFIG_SECURITY_NETWORK_XFRM */ +#ifdef CONFIG_KEYS + .key_alloc = LIST_HEAD_INIT(security_hook_heads.key_alloc), + .key_free = LIST_HEAD_INIT(security_hook_heads.key_free), + .key_permission = + LIST_HEAD_INIT(security_hook_heads.key_permission), + .key_getsecurity = + LIST_HEAD_INIT(security_hook_heads.key_getsecurity), +#endif /* CONFIG_KEYS */ +#ifdef CONFIG_AUDIT + .audit_rule_init = + LIST_HEAD_INIT(security_hook_heads.audit_rule_init), + .audit_rule_known = + LIST_HEAD_INIT(security_hook_heads.audit_rule_known), + .audit_rule_match = + LIST_HEAD_INIT(security_hook_heads.audit_rule_match), + .audit_rule_free = + LIST_HEAD_INIT(security_hook_heads.audit_rule_free), #endif /* CONFIG_AUDIT */ +}; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0cf105f346d4..06c9dd962c3c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1990,12 +1990,6 @@ static int selinux_binder_transfer_file(struct task_struct *from, static int selinux_ptrace_access_check(struct task_struct *child, unsigned int mode) { - int rc; - - rc = cap_ptrace_access_check(child, mode); - if (rc) - return rc; - if (mode & PTRACE_MODE_READ) { u32 sid = current_sid(); u32 csid = task_sid(child); @@ -2007,25 +2001,13 @@ static int selinux_ptrace_access_check(struct task_struct *child, static int selinux_ptrace_traceme(struct task_struct *parent) { - int rc; - - rc = cap_ptrace_traceme(parent); - if (rc) - return rc; - return task_has_perm(parent, current, PROCESS__PTRACE); } static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { - int error; - - error = current_has_perm(target, PROCESS__GETCAP); - if (error) - return error; - - return cap_capget(target, effective, inheritable, permitted); + return current_has_perm(target, PROCESS__GETCAP); } static int selinux_capset(struct cred *new, const struct cred *old, @@ -2033,13 +2015,6 @@ static int selinux_capset(struct cred *new, const struct cred *old, const kernel_cap_t *inheritable, const kernel_cap_t *permitted) { - int error; - - error = cap_capset(new, old, - effective, inheritable, permitted); - if (error) - return error; - return cred_has_perm(old, new, PROCESS__SETCAP); } @@ -2056,12 +2031,6 @@ static int selinux_capset(struct cred *new, const struct cred *old, static int selinux_capable(const struct cred *cred, struct user_namespace *ns, int cap, int audit) { - int rc; - - rc = cap_capable(cred, ns, cap, audit); - if (rc) - return rc; - return cred_has_capability(cred, cap, audit); } @@ -2139,12 +2108,12 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) { int rc, cap_sys_admin = 0; - rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, - SECURITY_CAP_NOAUDIT); + rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN, + SECURITY_CAP_NOAUDIT); if (rc == 0) cap_sys_admin = 1; - return __vm_enough_memory(mm, pages, cap_sys_admin); + return cap_sys_admin; } /* binprm security operations */ @@ -2193,10 +2162,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) struct inode *inode = file_inode(bprm->file); int rc; - rc = cap_bprm_set_creds(bprm); - if (rc) - return rc; - /* SELinux context only depends on initial program or script and not * the script interpreter */ if (bprm->cred_prepared) @@ -2320,7 +2285,7 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm) PROCESS__NOATSECURE, NULL); } - return (atsecure || cap_bprm_secureexec(bprm)); + return !!atsecure; } static int match_file(const void *p, struct file *file, unsigned fd) @@ -3132,8 +3097,11 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name * and lack of permission just means that we fall back to the * in-core context value, not a denial. */ - error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN, - SECURITY_CAP_NOAUDIT); + error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN, + SECURITY_CAP_NOAUDIT); + if (!error) + error = cred_has_capability(current_cred(), CAP_MAC_ADMIN, + SECURITY_CAP_NOAUDIT); if (!error) error = security_sid_to_context_force(isec->sid, &context, &size); @@ -3318,12 +3286,7 @@ error: static int selinux_mmap_addr(unsigned long addr) { - int rc; - - /* do DAC check on address space usage */ - rc = cap_mmap_addr(addr); - if (rc) - return rc; + int rc = 0; if (addr < CONFIG_LSM_MMAP_MIN_ADDR) { u32 sid = current_sid(); @@ -3639,23 +3602,11 @@ static void selinux_task_getsecid(struct task_struct *p, u32 *secid) static int selinux_task_setnice(struct task_struct *p, int nice) { - int rc; - - rc = cap_task_setnice(p, nice); - if (rc) - return rc; - return current_has_perm(p, PROCESS__SETSCHED); } static int selinux_task_setioprio(struct task_struct *p, int ioprio) { - int rc; - - rc = cap_task_setioprio(p, ioprio); - if (rc) - return rc; - return current_has_perm(p, PROCESS__SETSCHED); } @@ -3681,12 +3632,6 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, static int selinux_task_setscheduler(struct task_struct *p) { - int rc; - - rc = cap_task_setscheduler(p); - if (rc) - return rc; - return current_has_perm(p, PROCESS__SETSCHED); } @@ -5097,12 +5042,6 @@ static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops, static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) { - int err; - - err = cap_netlink_send(sk, skb); - if (err) - return err; - return selinux_nlmsg_perm(sk, skb); } @@ -5840,9 +5779,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) #endif -static struct security_operations selinux_ops = { - LSM_HOOK_INIT(name, "selinux"), - +static struct security_hook_list selinux_hooks[] = { LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder), @@ -6055,7 +5992,7 @@ static struct security_operations selinux_ops = { static __init int selinux_init(void) { - if (!security_module_enable(&selinux_ops)) { + if (!security_module_enable("selinux")) { selinux_enabled = 0; return 0; } @@ -6077,8 +6014,7 @@ static __init int selinux_init(void) 0, SLAB_PANIC, NULL); avc_init(); - if (register_security(&selinux_ops)) - panic("SELinux: Unable to register with kernel.\n"); + security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks)); if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) panic("SELinux: Unable to register AVC netcache callback\n"); @@ -6206,7 +6142,7 @@ int selinux_disable(void) selinux_disabled = 1; selinux_enabled = 0; - reset_security_ops(); + security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks)); /* Try to destroy the avc node cache */ avc_disable(); diff --git a/security/smack/smack.h b/security/smack/smack.h index 262dad8dfbc6..b8c1a869d85e 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -276,8 +276,6 @@ extern struct mutex smack_known_lock; extern struct list_head smack_known_list; extern struct list_head smk_netlbladdr_list; -extern struct security_operations smack_ops; - #define SMACK_HASH_SLOTS 16 extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS]; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 4313bf44c3f0..5eae42c8d0d5 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -436,17 +436,11 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, */ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) { - int rc; struct smack_known *skp; - rc = cap_ptrace_access_check(ctp, mode); - if (rc != 0) - return rc; - skp = smk_of_task_struct(ctp); - rc = smk_ptrace_rule_check(current, skp, mode, __func__); - return rc; + return smk_ptrace_rule_check(current, skp, mode, __func__); } /** @@ -462,10 +456,6 @@ static int smack_ptrace_traceme(struct task_struct *ptp) int rc; struct smack_known *skp; - rc = cap_ptrace_traceme(ptp); - if (rc != 0) - return rc; - skp = smk_of_task(current_security()); rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__); @@ -721,10 +711,6 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) struct inode_smack *isp; int rc; - rc = cap_bprm_set_creds(bprm); - if (rc != 0) - return rc; - if (bprm->cred_prepared) return 0; @@ -779,12 +765,11 @@ static void smack_bprm_committing_creds(struct linux_binprm *bprm) static int smack_bprm_secureexec(struct linux_binprm *bprm) { struct task_smack *tsp = current_security(); - int ret = cap_bprm_secureexec(bprm); - if (!ret && (tsp->smk_task != tsp->smk_forked)) - ret = 1; + if (tsp->smk_task != tsp->smk_forked) + return 1; - return ret; + return 0; } /* @@ -1934,12 +1919,7 @@ static void smack_task_getsecid(struct task_struct *p, u32 *secid) */ static int smack_task_setnice(struct task_struct *p, int nice) { - int rc; - - rc = cap_task_setnice(p, nice); - if (rc == 0) - rc = smk_curacc_on_task(p, MAY_WRITE, __func__); - return rc; + return smk_curacc_on_task(p, MAY_WRITE, __func__); } /** @@ -1951,12 +1931,7 @@ static int smack_task_setnice(struct task_struct *p, int nice) */ static int smack_task_setioprio(struct task_struct *p, int ioprio) { - int rc; - - rc = cap_task_setioprio(p, ioprio); - if (rc == 0) - rc = smk_curacc_on_task(p, MAY_WRITE, __func__); - return rc; + return smk_curacc_on_task(p, MAY_WRITE, __func__); } /** @@ -1980,12 +1955,7 @@ static int smack_task_getioprio(struct task_struct *p) */ static int smack_task_setscheduler(struct task_struct *p) { - int rc; - - rc = cap_task_setscheduler(p); - if (rc == 0) - rc = smk_curacc_on_task(p, MAY_WRITE, __func__); - return rc; + return smk_curacc_on_task(p, MAY_WRITE, __func__); } /** @@ -4266,9 +4236,7 @@ static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) return 0; } -struct security_operations smack_ops = { - LSM_HOOK_INIT(name, "smack"), - +struct security_hook_list smack_hooks[] = { LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), LSM_HOOK_INIT(syslog, smack_syslog), @@ -4451,7 +4419,7 @@ static __init int smack_init(void) struct cred *cred; struct task_smack *tsp; - if (!security_module_enable(&smack_ops)) + if (!security_module_enable("smack")) return 0; smack_enabled = 1; @@ -4481,8 +4449,7 @@ static __init int smack_init(void) /* * Register with LSM */ - if (register_security(&smack_ops)) - panic("smack: Unable to register with kernel.\n"); + security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks)); return 0; } diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index d9682985349e..4aa12c8d3c63 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -2547,7 +2547,7 @@ static int __init init_smk_fs(void) int err; int rc; - if (!security_module_enable(&smack_ops)) + if (!security_module_enable("smack")) return 0; err = smk_init_sysfs(); diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index bce13583efda..cbf3df422c87 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -72,12 +72,6 @@ static void tomoyo_cred_free(struct cred *cred) */ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) { - int rc; - - rc = cap_bprm_set_creds(bprm); - if (rc) - return rc; - /* * Do only if this function is called for the first time of an execve * operation. @@ -502,8 +496,7 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, * tomoyo_security_ops is a "struct security_operations" which is used for * registering TOMOYO. */ -static struct security_operations tomoyo_security_ops = { - LSM_HOOK_INIT(name, "tomoyo"), +static struct security_hook_list tomoyo_hooks[] = { LSM_HOOK_INIT(cred_alloc_blank, tomoyo_cred_alloc_blank), LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare), LSM_HOOK_INIT(cred_transfer, tomoyo_cred_transfer), @@ -546,11 +539,10 @@ static int __init tomoyo_init(void) { struct cred *cred = (struct cred *) current_cred(); - if (!security_module_enable(&tomoyo_security_ops)) + if (!security_module_enable("tomoyo")) return 0; /* register ourselves with the security framework */ - if (register_security(&tomoyo_security_ops)) - panic("Failure registering TOMOYO Linux"); + security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks)); printk(KERN_INFO "TOMOYO Linux initialized\n"); cred->security = &tomoyo_kernel_domain; tomoyo_mm_init(); diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 23dd4c6246b2..9ed32502470e 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -154,13 +154,9 @@ void yama_task_free(struct task_struct *task) int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { - int rc; + int rc = -ENOSYS; struct task_struct *myself = current; - rc = cap_task_prctl(option, arg2, arg3, arg4, arg5); - if (rc != -ENOSYS) - return rc; - switch (option) { case PR_SET_PTRACER: /* Since a thread can call prctl(), find the group leader @@ -279,17 +275,10 @@ static int ptracer_exception_found(struct task_struct *tracer, * * Returns 0 if following the ptrace is allowed, -ve on error. */ -int yama_ptrace_access_check(struct task_struct *child, +static int yama_ptrace_access_check(struct task_struct *child, unsigned int mode) { - int rc; - - /* If standard caps disallows it, so does Yama. We should - * only tighten restrictions further. - */ - rc = cap_ptrace_access_check(child, mode); - if (rc) - return rc; + int rc = 0; /* require ptrace target be a child of ptracer on attach */ if (mode == PTRACE_MODE_ATTACH) { @@ -335,14 +324,7 @@ int yama_ptrace_access_check(struct task_struct *child, */ int yama_ptrace_traceme(struct task_struct *parent) { - int rc; - - /* If standard caps disallows it, so does Yama. We should - * only tighten restrictions further. - */ - rc = cap_ptrace_traceme(parent); - if (rc) - return rc; + int rc = 0; /* Only disallow PTRACE_TRACEME on more aggressive settings. */ switch (ptrace_scope) { @@ -364,16 +346,17 @@ int yama_ptrace_traceme(struct task_struct *parent) return rc; } -#ifndef CONFIG_SECURITY_YAMA_STACKED -static struct security_operations yama_ops = { - LSM_HOOK_INIT(name, "yama"), - +static struct security_hook_list yama_hooks[] = { LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme), LSM_HOOK_INIT(task_prctl, yama_task_prctl), LSM_HOOK_INIT(task_free, yama_task_free), }; -#endif + +void __init yama_add_hooks(void) +{ + security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks)); +} #ifdef CONFIG_SYSCTL static int yama_dointvec_minmax(struct ctl_table *table, int write, @@ -418,16 +401,13 @@ static struct ctl_table yama_sysctl_table[] = { static __init int yama_init(void) { #ifndef CONFIG_SECURITY_YAMA_STACKED - if (!security_module_enable(&yama_ops)) + /* + * If yama is being stacked this is already taken care of. + */ + if (!security_module_enable("yama")) return 0; #endif - - printk(KERN_INFO "Yama: becoming mindful.\n"); - -#ifndef CONFIG_SECURITY_YAMA_STACKED - if (register_security(&yama_ops)) - panic("Yama: kernel registration failed.\n"); -#endif + pr_info("Yama: becoming mindful.\n"); #ifdef CONFIG_SYSCTL if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table)) -- cgit v1.2.3-59-g8ed1b From cded3fffbeab777e6ad2ec05d4a3b62c5caca0f3 Mon Sep 17 00:00:00 2001 From: Marek Milkovic Date: Thu, 4 Jun 2015 16:22:16 -0400 Subject: selinux: Print 'sclass' as string when unrecognized netlink message occurs This prints the 'sclass' field as string instead of index in unrecognized netlink message. The textual representation makes it easier to distinguish the right class. Signed-off-by: Marek Milkovic Acked-by: Stephen Smalley [PM: 80-char width fixes] Signed-off-by: Paul Moore --- security/selinux/hooks.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 06c9dd962c3c..99c4a00cce4e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4713,8 +4713,9 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) if (err == -EINVAL) { printk(KERN_WARNING "SELinux: unrecognized netlink message:" - " protocol=%hu nlmsg_type=%hu sclass=%hu\n", - sk->sk_protocol, nlh->nlmsg_type, sksec->sclass); + " protocol=%hu nlmsg_type=%hu sclass=%s\n", + sk->sk_protocol, nlh->nlmsg_type, + secclass_map[sksec->sclass - 1].name); if (!selinux_enforcing || security_get_allow_unknown()) err = 0; } -- cgit v1.2.3-59-g8ed1b From 9e7c8f8c62c1e1cda203b5bfaba4575b141e42e7 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 4 Jun 2015 16:22:16 -0400 Subject: signals: don't abuse __flush_signals() in selinux_bprm_committed_creds() selinux_bprm_committed_creds()->__flush_signals() is not right, we shouldn't clear TIF_SIGPENDING unconditionally. There can be other reasons for signal_pending(): freezing(), JOBCTL_PENDING_MASK, and potentially more. Also change this code to check fatal_signal_pending() rather than SIGNAL_GROUP_EXIT, it looks a bit better. Now we can kill __flush_signals() before it finds another buggy user. Note: this code looks racy, we can flush a signal which was sent after the task SID has been updated. Signed-off-by: Oleg Nesterov Signed-off-by: Paul Moore --- include/linux/sched.h | 1 - kernel/signal.c | 13 ++++--------- security/selinux/hooks.c | 6 ++++-- 3 files changed, 8 insertions(+), 12 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/include/linux/sched.h b/include/linux/sched.h index 8222ae40ecb0..4f84aade8b4d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2373,7 +2373,6 @@ extern void sched_dead(struct task_struct *p); extern void proc_caches_init(void); extern void flush_signals(struct task_struct *); -extern void __flush_signals(struct task_struct *); extern void ignore_signals(struct task_struct *); extern void flush_signal_handlers(struct task_struct *, int force_default); extern int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info); diff --git a/kernel/signal.c b/kernel/signal.c index d51c5ddd855c..d4972504f2f1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -414,21 +414,16 @@ void flush_sigqueue(struct sigpending *queue) } /* - * Flush all pending signals for a task. + * Flush all pending signals for this kthread. */ -void __flush_signals(struct task_struct *t) -{ - clear_tsk_thread_flag(t, TIF_SIGPENDING); - flush_sigqueue(&t->pending); - flush_sigqueue(&t->signal->shared_pending); -} - void flush_signals(struct task_struct *t) { unsigned long flags; spin_lock_irqsave(&t->sighand->siglock, flags); - __flush_signals(t); + clear_tsk_thread_flag(t, TIF_SIGPENDING); + flush_sigqueue(&t->pending); + flush_sigqueue(&t->signal->shared_pending); spin_unlock_irqrestore(&t->sighand->siglock, flags); } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 99c4a00cce4e..8abbd548ece9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2416,10 +2416,12 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm) for (i = 0; i < 3; i++) do_setitimer(i, &itimer, NULL); spin_lock_irq(¤t->sighand->siglock); - if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) { - __flush_signals(current); + if (!fatal_signal_pending(current)) { + flush_sigqueue(¤t->pending); + flush_sigqueue(¤t->signal->shared_pending); flush_signal_handlers(current, 1); sigemptyset(¤t->blocked); + recalc_sigpending(); } spin_unlock_irq(¤t->sighand->siglock); } -- cgit v1.2.3-59-g8ed1b From 6c6d2e9bde1c1c87a7ead806f8f5e2181d41a652 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Thu, 4 Jun 2015 16:22:16 -0400 Subject: selinux: update netlink socket classes Update the set of SELinux netlink socket class definitions to match the set of netlink protocols implemented by the kernel. The ip_queue implementation for the NETLINK_FIREWALL and NETLINK_IP6_FW protocols was removed in d16cf20e2f2f13411eece7f7fb72c17d141c4a84, so we can remove the corresponding class definitions as this is dead code. Add new classes for NETLINK_ISCSI, NETLINK_FIB_LOOKUP, NETLINK_CONNECTOR, NETLINK_NETFILTER, NETLINK_GENERIC, NETLINK_SCSITRANSPORT, NETLINK_RDMA, and NETLINK_CRYPTO so that we can distinguish among sockets created for each of these protocols. This change does not define the finer-grained nlsmsg_read/write permissions or map specific nlmsg_type values to those permissions in the SELinux nlmsgtab; if finer-grained control of these sockets is desired/required, that can be added as a follow-on change. We do not define a SELinux class for NETLINK_ECRYPTFS as the implementation was removed in 624ae5284516870657505103ada531c64dba2a9a. Signed-off-by: Stephen Smalley Signed-off-by: Paul Moore --- security/selinux/hooks.c | 20 ++++++++++++++++---- security/selinux/include/classmap.h | 22 ++++++++++++++++------ 2 files changed, 32 insertions(+), 10 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8abbd548ece9..cf2cc0dca9b7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1188,8 +1188,6 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc switch (protocol) { case NETLINK_ROUTE: return SECCLASS_NETLINK_ROUTE_SOCKET; - case NETLINK_FIREWALL: - return SECCLASS_NETLINK_FIREWALL_SOCKET; case NETLINK_SOCK_DIAG: return SECCLASS_NETLINK_TCPDIAG_SOCKET; case NETLINK_NFLOG: @@ -1198,14 +1196,28 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc return SECCLASS_NETLINK_XFRM_SOCKET; case NETLINK_SELINUX: return SECCLASS_NETLINK_SELINUX_SOCKET; + case NETLINK_ISCSI: + return SECCLASS_NETLINK_ISCSI_SOCKET; case NETLINK_AUDIT: return SECCLASS_NETLINK_AUDIT_SOCKET; - case NETLINK_IP6_FW: - return SECCLASS_NETLINK_IP6FW_SOCKET; + case NETLINK_FIB_LOOKUP: + return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET; + case NETLINK_CONNECTOR: + return SECCLASS_NETLINK_CONNECTOR_SOCKET; + case NETLINK_NETFILTER: + return SECCLASS_NETLINK_NETFILTER_SOCKET; case NETLINK_DNRTMSG: return SECCLASS_NETLINK_DNRT_SOCKET; case NETLINK_KOBJECT_UEVENT: return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET; + case NETLINK_GENERIC: + return SECCLASS_NETLINK_GENERIC_SOCKET; + case NETLINK_SCSITRANSPORT: + return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET; + case NETLINK_RDMA: + return SECCLASS_NETLINK_RDMA_SOCKET; + case NETLINK_CRYPTO: + return SECCLASS_NETLINK_CRYPTO_SOCKET; default: return SECCLASS_NETLINK_SOCKET; } diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index eccd61b3de8a..1d8b924cc134 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -107,9 +107,6 @@ struct security_class_mapping secclass_map[] = { { "netlink_route_socket", { COMMON_SOCK_PERMS, "nlmsg_read", "nlmsg_write", NULL } }, - { "netlink_firewall_socket", - { COMMON_SOCK_PERMS, - "nlmsg_read", "nlmsg_write", NULL } }, { "netlink_tcpdiag_socket", { COMMON_SOCK_PERMS, "nlmsg_read", "nlmsg_write", NULL } }, @@ -120,19 +117,32 @@ struct security_class_mapping secclass_map[] = { "nlmsg_read", "nlmsg_write", NULL } }, { "netlink_selinux_socket", { COMMON_SOCK_PERMS, NULL } }, + { "netlink_iscsi_socket", + { COMMON_SOCK_PERMS, NULL } }, { "netlink_audit_socket", { COMMON_SOCK_PERMS, "nlmsg_read", "nlmsg_write", "nlmsg_relay", "nlmsg_readpriv", "nlmsg_tty_audit", NULL } }, - { "netlink_ip6fw_socket", - { COMMON_SOCK_PERMS, - "nlmsg_read", "nlmsg_write", NULL } }, + { "netlink_fib_lookup_socket", + { COMMON_SOCK_PERMS, NULL } }, + { "netlink_connector_socket", + { COMMON_SOCK_PERMS, NULL } }, + { "netlink_netfilter_socket", + { COMMON_SOCK_PERMS, NULL } }, { "netlink_dnrt_socket", { COMMON_SOCK_PERMS, NULL } }, { "association", { "sendto", "recvfrom", "setcontext", "polmatch", NULL } }, { "netlink_kobject_uevent_socket", { COMMON_SOCK_PERMS, NULL } }, + { "netlink_generic_socket", + { COMMON_SOCK_PERMS, NULL } }, + { "netlink_scsitransport_socket", + { COMMON_SOCK_PERMS, NULL } }, + { "netlink_rdma_socket", + { COMMON_SOCK_PERMS, NULL } }, + { "netlink_crypto_socket", + { COMMON_SOCK_PERMS, NULL } }, { "appletalk_socket", { COMMON_SOCK_PERMS, NULL } }, { "packet", -- cgit v1.2.3-59-g8ed1b From 134509d54e4e98888be2697a92cb4b48957b792b Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Thu, 4 Jun 2015 16:22:17 -0400 Subject: selinux: enable per-file labeling for debugfs files. Add support for per-file labeling of debugfs files so that we can distinguish them in policy. This is particularly important in Android where certain debugfs files have to be writable by apps and therefore the debugfs directory tree can be read and searched by all. Since debugfs is entirely kernel-generated, the directory tree is immutable by userspace, and the inodes are pinned in memory, we can simply use the same approach as with proc and label the inodes from policy based on pathname from the root of the debugfs filesystem. Generalize the existing labeling support used for proc and reuse it for debugfs too. Signed-off-by: Stephen Smalley Signed-off-by: Paul Moore --- security/selinux/hooks.c | 43 ++++++++++++++++++------------------- security/selinux/include/security.h | 1 + 2 files changed, 22 insertions(+), 22 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index cf2cc0dca9b7..ec39b9ab6569 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -724,7 +724,10 @@ static int selinux_set_mnt_opts(struct super_block *sb, } if (strcmp(sb->s_type->name, "proc") == 0) - sbsec->flags |= SE_SBPROC; + sbsec->flags |= SE_SBPROC | SE_SBGENFS; + + if (strcmp(sb->s_type->name, "debugfs") == 0) + sbsec->flags |= SE_SBGENFS; if (!sbsec->behavior) { /* @@ -1232,12 +1235,13 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc return SECCLASS_SOCKET; } -#ifdef CONFIG_PROC_FS -static int selinux_proc_get_sid(struct dentry *dentry, - u16 tclass, - u32 *sid) +static int selinux_genfs_get_sid(struct dentry *dentry, + u16 tclass, + u16 flags, + u32 *sid) { int rc; + struct super_block *sb = dentry->d_inode->i_sb; char *buffer, *path; buffer = (char *)__get_free_page(GFP_KERNEL); @@ -1248,26 +1252,20 @@ static int selinux_proc_get_sid(struct dentry *dentry, if (IS_ERR(path)) rc = PTR_ERR(path); else { - /* each process gets a /proc/PID/ entry. Strip off the - * PID part to get a valid selinux labeling. - * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ - while (path[1] >= '0' && path[1] <= '9') { - path[1] = '/'; - path++; + if (flags & SE_SBPROC) { + /* each process gets a /proc/PID/ entry. Strip off the + * PID part to get a valid selinux labeling. + * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ + while (path[1] >= '0' && path[1] <= '9') { + path[1] = '/'; + path++; + } } - rc = security_genfs_sid("proc", path, tclass, sid); + rc = security_genfs_sid(sb->s_type->name, path, tclass, sid); } free_page((unsigned long)buffer); return rc; } -#else -static int selinux_proc_get_sid(struct dentry *dentry, - u16 tclass, - u32 *sid) -{ - return -EINVAL; -} -#endif /* The inode's security attributes must be initialized before first use. */ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) @@ -1424,7 +1422,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent /* Default to the fs superblock SID. */ isec->sid = sbsec->sid; - if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { + if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) { /* We must have a dentry to determine the label on * procfs inodes */ if (opt_dentry) @@ -1447,7 +1445,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent if (!dentry) goto out_unlock; isec->sclass = inode_mode_to_security_class(inode->i_mode); - rc = selinux_proc_get_sid(dentry, isec->sclass, &sid); + rc = selinux_genfs_get_sid(dentry, isec->sclass, + sbsec->flags, &sid); dput(dentry); if (rc) goto out_unlock; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index d1e0b239b602..36993ad1c067 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -56,6 +56,7 @@ /* Non-mount related flags */ #define SE_SBINITIALIZED 0x0100 #define SE_SBPROC 0x0200 +#define SE_SBGENFS 0x0400 #define CONTEXT_STR "context=" #define FSCONTEXT_STR "fscontext=" -- cgit v1.2.3-59-g8ed1b From 8e01472078763ebc1eaea089a1adab75dd982ccd Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Thu, 4 Jun 2015 16:22:17 -0400 Subject: selinux: enable genfscon labeling for sysfs and pstore files Support per-file labeling of sysfs and pstore files based on genfscon policy entries. This is safe because the sysfs and pstore directory tree cannot be manipulated by userspace, except to unlink pstore entries. This provides an alternative method of assigning per-file labeling to sysfs or pstore files without needing to set the labels from userspace on each boot. The advantages of this approach are that the labels are assigned as soon as the dentry is first instantiated and userspace does not need to walk the sysfs or pstore tree and set the labels on each boot. The limitations of this approach are that the labels can only be assigned based on pathname prefix matching. You can initially assign labels using this mechanism and then change them at runtime via setxattr if allowed to do so by policy. Signed-off-by: Stephen Smalley Suggested-by: Dominick Grift Acked-by: Jeff Vander Stoep Signed-off-by: Paul Moore --- security/selinux/hooks.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ec39b9ab6569..daf59b4bc02b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -726,7 +726,9 @@ static int selinux_set_mnt_opts(struct super_block *sb, if (strcmp(sb->s_type->name, "proc") == 0) sbsec->flags |= SE_SBPROC | SE_SBGENFS; - if (strcmp(sb->s_type->name, "debugfs") == 0) + if (!strcmp(sb->s_type->name, "debugfs") || + !strcmp(sb->s_type->name, "sysfs") || + !strcmp(sb->s_type->name, "pstore")) sbsec->flags |= SE_SBGENFS; if (!sbsec->behavior) { -- cgit v1.2.3-59-g8ed1b From 9fc2b4b436cff7d8403034676014f1be9d534942 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 4 Jun 2015 15:57:25 -0400 Subject: selinux: fix setting of security labels on NFS Before calling into the filesystem, vfs_setxattr calls security_inode_setxattr, which ends up calling selinux_inode_setxattr in our case. That returns -EOPNOTSUPP whenever SBLABEL_MNT is not set. SBLABEL_MNT was supposed to be set by sb_finish_set_opts, which sets it only if selinux_is_sblabel_mnt returns true. The selinux_is_sblabel_mnt logic was broken by eadcabc697e9 "SELinux: do all flags twiddling in one place", which didn't take into the account the SECURITY_FS_USE_NATIVE behavior that had been introduced for nfs with eb9ae686507b "SELinux: Add new labeling type native labels". This caused setxattr's of security labels over NFSv4.2 to fail. Cc: stable@kernel.org # 3.13 Cc: Eric Paris Cc: David Quigley Reported-by: Richard Chan Signed-off-by: J. Bruce Fields Acked-by: Stephen Smalley [PM: added the stable dependency] Signed-off-by: Paul Moore --- security/selinux/hooks.c | 1 + 1 file changed, 1 insertion(+) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index daf59b4bc02b..312537d48050 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -403,6 +403,7 @@ static int selinux_is_sblabel_mnt(struct super_block *sb) return sbsec->behavior == SECURITY_FS_USE_XATTR || sbsec->behavior == SECURITY_FS_USE_TRANS || sbsec->behavior == SECURITY_FS_USE_TASK || + sbsec->behavior == SECURITY_FS_USE_NATIVE || /* Special handling. Genfs but also in-core setxattr handler */ !strcmp(sb->s_type->name, "sysfs") || !strcmp(sb->s_type->name, "pstore") || -- cgit v1.2.3-59-g8ed1b