diff options
author | James Morris <james.l.morris@oracle.com> | 2014-04-13 21:23:14 -0400 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2014-04-13 21:23:14 -0400 |
commit | ecd740c6f2f092b90b95fa35f757973589eaaca2 (patch) | |
tree | ce02b1e18c4fc5729699251460cd8be7604d8401 /security/selinux/hooks.c | |
parent | f64410ec665479d7b4b77b7519e814253ed0f686 (diff) | |
parent | 455c6fdbd219161bd09b1165f11699d6d73de11c (diff) |
Merge commit 'v3.14' into next
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d5d67c93b65c..869c2f1e0da1 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -233,6 +233,14 @@ static int inode_alloc_security(struct inode *inode) | |||
233 | return 0; | 233 | return 0; |
234 | } | 234 | } |
235 | 235 | ||
236 | static void inode_free_rcu(struct rcu_head *head) | ||
237 | { | ||
238 | struct inode_security_struct *isec; | ||
239 | |||
240 | isec = container_of(head, struct inode_security_struct, rcu); | ||
241 | kmem_cache_free(sel_inode_cache, isec); | ||
242 | } | ||
243 | |||
236 | static void inode_free_security(struct inode *inode) | 244 | static void inode_free_security(struct inode *inode) |
237 | { | 245 | { |
238 | struct inode_security_struct *isec = inode->i_security; | 246 | struct inode_security_struct *isec = inode->i_security; |
@@ -243,8 +251,16 @@ static void inode_free_security(struct inode *inode) | |||
243 | list_del_init(&isec->list); | 251 | list_del_init(&isec->list); |
244 | spin_unlock(&sbsec->isec_lock); | 252 | spin_unlock(&sbsec->isec_lock); |
245 | 253 | ||
246 | inode->i_security = NULL; | 254 | /* |
247 | kmem_cache_free(sel_inode_cache, isec); | 255 | * The inode may still be referenced in a path walk and |
256 | * a call to selinux_inode_permission() can be made | ||
257 | * after inode_free_security() is called. Ideally, the VFS | ||
258 | * wouldn't do this, but fixing that is a much harder | ||
259 | * job. For now, simply free the i_security via RCU, and | ||
260 | * leave the current inode->i_security pointer intact. | ||
261 | * The inode will be freed after the RCU grace period too. | ||
262 | */ | ||
263 | call_rcu(&isec->rcu, inode_free_rcu); | ||
248 | } | 264 | } |
249 | 265 | ||
250 | static int file_alloc_security(struct file *file) | 266 | static int file_alloc_security(struct file *file) |
@@ -652,7 +668,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
652 | if (flags[i] == SBLABEL_MNT) | 668 | if (flags[i] == SBLABEL_MNT) |
653 | continue; | 669 | continue; |
654 | rc = security_context_to_sid(mount_options[i], | 670 | rc = security_context_to_sid(mount_options[i], |
655 | strlen(mount_options[i]), &sid); | 671 | strlen(mount_options[i]), &sid, GFP_KERNEL); |
656 | if (rc) { | 672 | if (rc) { |
657 | printk(KERN_WARNING "SELinux: security_context_to_sid" | 673 | printk(KERN_WARNING "SELinux: security_context_to_sid" |
658 | "(%s) failed for (dev %s, type %s) errno=%d\n", | 674 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
@@ -2491,7 +2507,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data) | |||
2491 | if (flags[i] == SBLABEL_MNT) | 2507 | if (flags[i] == SBLABEL_MNT) |
2492 | continue; | 2508 | continue; |
2493 | len = strlen(mount_options[i]); | 2509 | len = strlen(mount_options[i]); |
2494 | rc = security_context_to_sid(mount_options[i], len, &sid); | 2510 | rc = security_context_to_sid(mount_options[i], len, &sid, |
2511 | GFP_KERNEL); | ||
2495 | if (rc) { | 2512 | if (rc) { |
2496 | printk(KERN_WARNING "SELinux: security_context_to_sid" | 2513 | printk(KERN_WARNING "SELinux: security_context_to_sid" |
2497 | "(%s) failed for (dev %s, type %s) errno=%d\n", | 2514 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
@@ -2895,7 +2912,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2895 | if (rc) | 2912 | if (rc) |
2896 | return rc; | 2913 | return rc; |
2897 | 2914 | ||
2898 | rc = security_context_to_sid(value, size, &newsid); | 2915 | rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL); |
2899 | if (rc == -EINVAL) { | 2916 | if (rc == -EINVAL) { |
2900 | if (!capable(CAP_MAC_ADMIN)) { | 2917 | if (!capable(CAP_MAC_ADMIN)) { |
2901 | struct audit_buffer *ab; | 2918 | struct audit_buffer *ab; |
@@ -3052,7 +3069,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
3052 | if (!value || !size) | 3069 | if (!value || !size) |
3053 | return -EACCES; | 3070 | return -EACCES; |
3054 | 3071 | ||
3055 | rc = security_context_to_sid((void *)value, size, &newsid); | 3072 | rc = security_context_to_sid((void *)value, size, &newsid, GFP_KERNEL); |
3056 | if (rc) | 3073 | if (rc) |
3057 | return rc; | 3074 | return rc; |
3058 | 3075 | ||
@@ -5527,7 +5544,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5527 | str[size-1] = 0; | 5544 | str[size-1] = 0; |
5528 | size--; | 5545 | size--; |
5529 | } | 5546 | } |
5530 | error = security_context_to_sid(value, size, &sid); | 5547 | error = security_context_to_sid(value, size, &sid, GFP_KERNEL); |
5531 | if (error == -EINVAL && !strcmp(name, "fscreate")) { | 5548 | if (error == -EINVAL && !strcmp(name, "fscreate")) { |
5532 | if (!capable(CAP_MAC_ADMIN)) { | 5549 | if (!capable(CAP_MAC_ADMIN)) { |
5533 | struct audit_buffer *ab; | 5550 | struct audit_buffer *ab; |
@@ -5636,7 +5653,7 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | |||
5636 | 5653 | ||
5637 | static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) | 5654 | static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) |
5638 | { | 5655 | { |
5639 | return security_context_to_sid(secdata, seclen, secid); | 5656 | return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL); |
5640 | } | 5657 | } |
5641 | 5658 | ||
5642 | static void selinux_release_secctx(char *secdata, u32 seclen) | 5659 | static void selinux_release_secctx(char *secdata, u32 seclen) |