aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c212
1 files changed, 176 insertions, 36 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 819fd6858b49..33fd061305c4 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -17,6 +17,7 @@
17 * Paul Moore <paul@paul-moore.com> 17 * Paul Moore <paul@paul-moore.com>
18 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. 18 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
19 * Yuichi Nakamura <ynakam@hitachisoft.jp> 19 * Yuichi Nakamura <ynakam@hitachisoft.jp>
20 * Copyright (C) 2016 Mellanox Technologies
20 * 21 *
21 * This program is free software; you can redistribute it and/or modify 22 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2, 23 * it under the terms of the GNU General Public License version 2,
@@ -90,6 +91,7 @@
90#include "netif.h" 91#include "netif.h"
91#include "netnode.h" 92#include "netnode.h"
92#include "netport.h" 93#include "netport.h"
94#include "ibpkey.h"
93#include "xfrm.h" 95#include "xfrm.h"
94#include "netlabel.h" 96#include "netlabel.h"
95#include "audit.h" 97#include "audit.h"
@@ -171,6 +173,16 @@ static int selinux_netcache_avc_callback(u32 event)
171 return 0; 173 return 0;
172} 174}
173 175
176static int selinux_lsm_notifier_avc_callback(u32 event)
177{
178 if (event == AVC_CALLBACK_RESET) {
179 sel_ib_pkey_flush();
180 call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
181 }
182
183 return 0;
184}
185
174/* 186/*
175 * initialise the security for the init task 187 * initialise the security for the init task
176 */ 188 */
@@ -398,18 +410,6 @@ static void superblock_free_security(struct super_block *sb)
398 kfree(sbsec); 410 kfree(sbsec);
399} 411}
400 412
401/* The file system's label must be initialized prior to use. */
402
403static const char *labeling_behaviors[7] = {
404 "uses xattr",
405 "uses transition SIDs",
406 "uses task SIDs",
407 "uses genfs_contexts",
408 "not configured for labeling",
409 "uses mountpoint labeling",
410 "uses native labeling",
411};
412
413static inline int inode_doinit(struct inode *inode) 413static inline int inode_doinit(struct inode *inode)
414{ 414{
415 return inode_doinit_with_dentry(inode, NULL); 415 return inode_doinit_with_dentry(inode, NULL);
@@ -524,13 +524,17 @@ static int sb_finish_set_opts(struct super_block *sb)
524 } 524 }
525 } 525 }
526 526
527 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
528 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
529 sb->s_id, sb->s_type->name);
530
531 sbsec->flags |= SE_SBINITIALIZED; 527 sbsec->flags |= SE_SBINITIALIZED;
528
529 /*
530 * Explicitly set or clear SBLABEL_MNT. It's not sufficient to simply
531 * leave the flag untouched because sb_clone_mnt_opts might be handing
532 * us a superblock that needs the flag to be cleared.
533 */
532 if (selinux_is_sblabel_mnt(sb)) 534 if (selinux_is_sblabel_mnt(sb))
533 sbsec->flags |= SBLABEL_MNT; 535 sbsec->flags |= SBLABEL_MNT;
536 else
537 sbsec->flags &= ~SBLABEL_MNT;
534 538
535 /* Initialize the root inode. */ 539 /* Initialize the root inode. */
536 rc = inode_doinit_with_dentry(root_inode, root); 540 rc = inode_doinit_with_dentry(root_inode, root);
@@ -809,6 +813,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
809 sbsec->flags |= SE_SBPROC | SE_SBGENFS; 813 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
810 814
811 if (!strcmp(sb->s_type->name, "debugfs") || 815 if (!strcmp(sb->s_type->name, "debugfs") ||
816 !strcmp(sb->s_type->name, "tracefs") ||
812 !strcmp(sb->s_type->name, "sysfs") || 817 !strcmp(sb->s_type->name, "sysfs") ||
813 !strcmp(sb->s_type->name, "pstore")) 818 !strcmp(sb->s_type->name, "pstore"))
814 sbsec->flags |= SE_SBGENFS; 819 sbsec->flags |= SE_SBGENFS;
@@ -963,8 +968,11 @@ mismatch:
963} 968}
964 969
965static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, 970static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
966 struct super_block *newsb) 971 struct super_block *newsb,
972 unsigned long kern_flags,
973 unsigned long *set_kern_flags)
967{ 974{
975 int rc = 0;
968 const struct superblock_security_struct *oldsbsec = oldsb->s_security; 976 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
969 struct superblock_security_struct *newsbsec = newsb->s_security; 977 struct superblock_security_struct *newsbsec = newsb->s_security;
970 978
@@ -979,6 +987,13 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
979 if (!ss_initialized) 987 if (!ss_initialized)
980 return 0; 988 return 0;
981 989
990 /*
991 * Specifying internal flags without providing a place to
992 * place the results is not allowed.
993 */
994 if (kern_flags && !set_kern_flags)
995 return -EINVAL;
996
982 /* how can we clone if the old one wasn't set up?? */ 997 /* how can we clone if the old one wasn't set up?? */
983 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); 998 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
984 999
@@ -994,6 +1009,18 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
994 newsbsec->def_sid = oldsbsec->def_sid; 1009 newsbsec->def_sid = oldsbsec->def_sid;
995 newsbsec->behavior = oldsbsec->behavior; 1010 newsbsec->behavior = oldsbsec->behavior;
996 1011
1012 if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
1013 !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
1014 rc = security_fs_use(newsb);
1015 if (rc)
1016 goto out;
1017 }
1018
1019 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !set_context) {
1020 newsbsec->behavior = SECURITY_FS_USE_NATIVE;
1021 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
1022 }
1023
997 if (set_context) { 1024 if (set_context) {
998 u32 sid = oldsbsec->mntpoint_sid; 1025 u32 sid = oldsbsec->mntpoint_sid;
999 1026
@@ -1013,8 +1040,9 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
1013 } 1040 }
1014 1041
1015 sb_finish_set_opts(newsb); 1042 sb_finish_set_opts(newsb);
1043out:
1016 mutex_unlock(&newsbsec->lock); 1044 mutex_unlock(&newsbsec->lock);
1017 return 0; 1045 return rc;
1018} 1046}
1019 1047
1020static int selinux_parse_opts_str(char *options, 1048static int selinux_parse_opts_str(char *options,
@@ -2062,8 +2090,9 @@ static inline u32 file_to_av(struct file *file)
2062static inline u32 open_file_to_av(struct file *file) 2090static inline u32 open_file_to_av(struct file *file)
2063{ 2091{
2064 u32 av = file_to_av(file); 2092 u32 av = file_to_av(file);
2093 struct inode *inode = file_inode(file);
2065 2094
2066 if (selinux_policycap_openperm) 2095 if (selinux_policycap_openperm && inode->i_sb->s_magic != SOCKFS_MAGIC)
2067 av |= FILE__OPEN; 2096 av |= FILE__OPEN;
2068 2097
2069 return av; 2098 return av;
@@ -3058,6 +3087,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
3058static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) 3087static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3059{ 3088{
3060 const struct cred *cred = current_cred(); 3089 const struct cred *cred = current_cred();
3090 struct inode *inode = d_backing_inode(dentry);
3061 unsigned int ia_valid = iattr->ia_valid; 3091 unsigned int ia_valid = iattr->ia_valid;
3062 __u32 av = FILE__WRITE; 3092 __u32 av = FILE__WRITE;
3063 3093
@@ -3073,8 +3103,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3073 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) 3103 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
3074 return dentry_has_perm(cred, dentry, FILE__SETATTR); 3104 return dentry_has_perm(cred, dentry, FILE__SETATTR);
3075 3105
3076 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE) 3106 if (selinux_policycap_openperm &&
3077 && !(ia_valid & ATTR_FILE)) 3107 inode->i_sb->s_magic != SOCKFS_MAGIC &&
3108 (ia_valid & ATTR_SIZE) &&
3109 !(ia_valid & ATTR_FILE))
3078 av |= FILE__OPEN; 3110 av |= FILE__OPEN;
3079 3111
3080 return dentry_has_perm(cred, dentry, av); 3112 return dentry_has_perm(cred, dentry, av);
@@ -3106,6 +3138,18 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
3106 return dentry_has_perm(cred, dentry, FILE__SETATTR); 3138 return dentry_has_perm(cred, dentry, FILE__SETATTR);
3107} 3139}
3108 3140
3141static bool has_cap_mac_admin(bool audit)
3142{
3143 const struct cred *cred = current_cred();
3144 int cap_audit = audit ? SECURITY_CAP_AUDIT : SECURITY_CAP_NOAUDIT;
3145
3146 if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, cap_audit))
3147 return false;
3148 if (cred_has_capability(cred, CAP_MAC_ADMIN, cap_audit, true))
3149 return false;
3150 return true;
3151}
3152
3109static int selinux_inode_setxattr(struct dentry *dentry, const char *name, 3153static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3110 const void *value, size_t size, int flags) 3154 const void *value, size_t size, int flags)
3111{ 3155{
@@ -3137,7 +3181,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3137 3181
3138 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL); 3182 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
3139 if (rc == -EINVAL) { 3183 if (rc == -EINVAL) {
3140 if (!capable(CAP_MAC_ADMIN)) { 3184 if (!has_cap_mac_admin(true)) {
3141 struct audit_buffer *ab; 3185 struct audit_buffer *ab;
3142 size_t audit_size; 3186 size_t audit_size;
3143 const char *str; 3187 const char *str;
@@ -3263,13 +3307,8 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
3263 * and lack of permission just means that we fall back to the 3307 * and lack of permission just means that we fall back to the
3264 * in-core context value, not a denial. 3308 * in-core context value, not a denial.
3265 */ 3309 */
3266 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3267 SECURITY_CAP_NOAUDIT);
3268 if (!error)
3269 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
3270 SECURITY_CAP_NOAUDIT, true);
3271 isec = inode_security(inode); 3310 isec = inode_security(inode);
3272 if (!error) 3311 if (has_cap_mac_admin(false))
3273 error = security_sid_to_context_force(isec->sid, &context, 3312 error = security_sid_to_context_force(isec->sid, &context,
3274 &size); 3313 &size);
3275 else 3314 else
@@ -3549,6 +3588,18 @@ static int selinux_mmap_addr(unsigned long addr)
3549static int selinux_mmap_file(struct file *file, unsigned long reqprot, 3588static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3550 unsigned long prot, unsigned long flags) 3589 unsigned long prot, unsigned long flags)
3551{ 3590{
3591 struct common_audit_data ad;
3592 int rc;
3593
3594 if (file) {
3595 ad.type = LSM_AUDIT_DATA_FILE;
3596 ad.u.file = file;
3597 rc = inode_has_perm(current_cred(), file_inode(file),
3598 FILE__MAP, &ad);
3599 if (rc)
3600 return rc;
3601 }
3602
3552 if (selinux_checkreqprot) 3603 if (selinux_checkreqprot)
3553 prot = reqprot; 3604 prot = reqprot;
3554 3605
@@ -3709,7 +3760,8 @@ static int selinux_file_open(struct file *file, const struct cred *cred)
3709 3760
3710/* task security operations */ 3761/* task security operations */
3711 3762
3712static int selinux_task_create(unsigned long clone_flags) 3763static int selinux_task_alloc(struct task_struct *task,
3764 unsigned long clone_flags)
3713{ 3765{
3714 u32 sid = current_sid(); 3766 u32 sid = current_sid();
3715 3767
@@ -5917,7 +5969,7 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
5917 } 5969 }
5918 error = security_context_to_sid(value, size, &sid, GFP_KERNEL); 5970 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
5919 if (error == -EINVAL && !strcmp(name, "fscreate")) { 5971 if (error == -EINVAL && !strcmp(name, "fscreate")) {
5920 if (!capable(CAP_MAC_ADMIN)) { 5972 if (!has_cap_mac_admin(true)) {
5921 struct audit_buffer *ab; 5973 struct audit_buffer *ab;
5922 size_t audit_size; 5974 size_t audit_size;
5923 5975
@@ -6127,7 +6179,70 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
6127 *_buffer = context; 6179 *_buffer = context;
6128 return rc; 6180 return rc;
6129} 6181}
6182#endif
6183
6184#ifdef CONFIG_SECURITY_INFINIBAND
6185static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
6186{
6187 struct common_audit_data ad;
6188 int err;
6189 u32 sid = 0;
6190 struct ib_security_struct *sec = ib_sec;
6191 struct lsm_ibpkey_audit ibpkey;
6192
6193 err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
6194 if (err)
6195 return err;
6196
6197 ad.type = LSM_AUDIT_DATA_IBPKEY;
6198 ibpkey.subnet_prefix = subnet_prefix;
6199 ibpkey.pkey = pkey_val;
6200 ad.u.ibpkey = &ibpkey;
6201 return avc_has_perm(sec->sid, sid,
6202 SECCLASS_INFINIBAND_PKEY,
6203 INFINIBAND_PKEY__ACCESS, &ad);
6204}
6205
6206static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
6207 u8 port_num)
6208{
6209 struct common_audit_data ad;
6210 int err;
6211 u32 sid = 0;
6212 struct ib_security_struct *sec = ib_sec;
6213 struct lsm_ibendport_audit ibendport;
6214
6215 err = security_ib_endport_sid(dev_name, port_num, &sid);
6216
6217 if (err)
6218 return err;
6219
6220 ad.type = LSM_AUDIT_DATA_IBENDPORT;
6221 strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
6222 ibendport.port = port_num;
6223 ad.u.ibendport = &ibendport;
6224 return avc_has_perm(sec->sid, sid,
6225 SECCLASS_INFINIBAND_ENDPORT,
6226 INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
6227}
6228
6229static int selinux_ib_alloc_security(void **ib_sec)
6230{
6231 struct ib_security_struct *sec;
6130 6232
6233 sec = kzalloc(sizeof(*sec), GFP_KERNEL);
6234 if (!sec)
6235 return -ENOMEM;
6236 sec->sid = current_sid();
6237
6238 *ib_sec = sec;
6239 return 0;
6240}
6241
6242static void selinux_ib_free_security(void *ib_sec)
6243{
6244 kfree(ib_sec);
6245}
6131#endif 6246#endif
6132 6247
6133static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { 6248static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
@@ -6212,7 +6327,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
6212 6327
6213 LSM_HOOK_INIT(file_open, selinux_file_open), 6328 LSM_HOOK_INIT(file_open, selinux_file_open),
6214 6329
6215 LSM_HOOK_INIT(task_create, selinux_task_create), 6330 LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
6216 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank), 6331 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
6217 LSM_HOOK_INIT(cred_free, selinux_cred_free), 6332 LSM_HOOK_INIT(cred_free, selinux_cred_free),
6218 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare), 6333 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
@@ -6314,7 +6429,13 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
6314 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue), 6429 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6315 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach), 6430 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6316 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open), 6431 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
6317 6432#ifdef CONFIG_SECURITY_INFINIBAND
6433 LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
6434 LSM_HOOK_INIT(ib_endport_manage_subnet,
6435 selinux_ib_endport_manage_subnet),
6436 LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
6437 LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
6438#endif
6318#ifdef CONFIG_SECURITY_NETWORK_XFRM 6439#ifdef CONFIG_SECURITY_NETWORK_XFRM
6319 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc), 6440 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6320 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone), 6441 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
@@ -6378,6 +6499,9 @@ static __init int selinux_init(void)
6378 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) 6499 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6379 panic("SELinux: Unable to register AVC netcache callback\n"); 6500 panic("SELinux: Unable to register AVC netcache callback\n");
6380 6501
6502 if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
6503 panic("SELinux: Unable to register AVC LSM notifier callback\n");
6504
6381 if (selinux_enforcing) 6505 if (selinux_enforcing)
6382 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n"); 6506 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
6383 else 6507 else
@@ -6447,6 +6571,23 @@ static struct nf_hook_ops selinux_nf_ops[] = {
6447#endif /* IPV6 */ 6571#endif /* IPV6 */
6448}; 6572};
6449 6573
6574static int __net_init selinux_nf_register(struct net *net)
6575{
6576 return nf_register_net_hooks(net, selinux_nf_ops,
6577 ARRAY_SIZE(selinux_nf_ops));
6578}
6579
6580static void __net_exit selinux_nf_unregister(struct net *net)
6581{
6582 nf_unregister_net_hooks(net, selinux_nf_ops,
6583 ARRAY_SIZE(selinux_nf_ops));
6584}
6585
6586static struct pernet_operations selinux_net_ops = {
6587 .init = selinux_nf_register,
6588 .exit = selinux_nf_unregister,
6589};
6590
6450static int __init selinux_nf_ip_init(void) 6591static int __init selinux_nf_ip_init(void)
6451{ 6592{
6452 int err; 6593 int err;
@@ -6456,13 +6597,12 @@ static int __init selinux_nf_ip_init(void)
6456 6597
6457 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); 6598 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6458 6599
6459 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops)); 6600 err = register_pernet_subsys(&selinux_net_ops);
6460 if (err) 6601 if (err)
6461 panic("SELinux: nf_register_hooks: error %d\n", err); 6602 panic("SELinux: register_pernet_subsys: error %d\n", err);
6462 6603
6463 return 0; 6604 return 0;
6464} 6605}
6465
6466__initcall(selinux_nf_ip_init); 6606__initcall(selinux_nf_ip_init);
6467 6607
6468#ifdef CONFIG_SECURITY_SELINUX_DISABLE 6608#ifdef CONFIG_SECURITY_SELINUX_DISABLE
@@ -6470,7 +6610,7 @@ static void selinux_nf_ip_exit(void)
6470{ 6610{
6471 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); 6611 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
6472 6612
6473 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops)); 6613 unregister_pernet_subsys(&selinux_net_ops);
6474} 6614}
6475#endif 6615#endif
6476 6616