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.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 81fbfa5b80d4..bd3293021488 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -282,8 +282,13 @@ static int __inode_security_revalidate(struct inode *inode,
might_sleep_if(may_sleep);
+ /*
+ * The check of isec->initialized below is racy but
+ * inode_doinit_with_dentry() will recheck with
+ * isec->lock held.
+ */
if (selinux_initialized() &&
- isec->initialized != LABEL_INITIALIZED) {
+ data_race(isec->initialized != LABEL_INITIALIZED)) {
if (!may_sleep)
return -ECHILD;
@@ -3845,7 +3850,17 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
if (default_noexec &&
(prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
int rc = 0;
- if (vma_is_initial_heap(vma)) {
+ /*
+ * We don't use the vma_is_initial_heap() helper as it has
+ * a history of problems and is currently broken on systems
+ * where there is no heap, e.g. brk == start_brk. Before
+ * replacing the conditional below with vma_is_initial_heap(),
+ * or something similar, please ensure that the logic is the
+ * same as what we have below or you have tested every possible
+ * corner case you can think to test.
+ */
+ if (vma->vm_start >= vma->vm_mm->start_brk &&
+ vma->vm_end <= vma->vm_mm->brk) {
rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
PROCESS__EXECHEAP, NULL);
} else if (!vma->vm_file && (vma_is_initial_stack(vma) ||
@@ -3933,7 +3948,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
struct file_security_struct *fsec;
/* struct fown_struct is never outside the context of a struct file */
- file = container_of(fown, struct file, f_owner);
+ file = fown->file;
fsec = selinux_file(file);
@@ -6626,8 +6641,8 @@ static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen
*/
static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
{
- return __vfs_setxattr_noperm(&nop_mnt_idmap, dentry, XATTR_NAME_SELINUX,
- ctx, ctxlen, 0);
+ return __vfs_setxattr_locked(&nop_mnt_idmap, dentry, XATTR_NAME_SELINUX,
+ ctx, ctxlen, 0, NULL);
}
static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)