Commit a296cadd authored by James Morris's avatar James Morris Committed by Linus Torvalds

[PATCH] SELinux: fix bugs in mprotect hook

The patch below by Roland McGrath fixes two bugs in the implementation of
the selinux_file_mprotect hook:

  It calls selinux_file_mmap, which has two problems.  First, the stacked
  security module will get both mmap and mprotect callbacks for an
  mprotect call, which is wrong.  Secondly, the vm_flags value contains 
  VM_* bits, and these do not match the MAP_* bits of the same name or
  function, so it passes bogus flags and causes every mprotect to be 
  treated as if MAP_SHARED were in use.

  The patch shares the common code while not having one function call the
  other, and fixes these two bugs.
Signed-off-by: default avatarJames Morris <jmorris@redhat.com>
Signed-off-by: default avatarRoland McGrath <roland@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5334d6a1
...@@ -2466,21 +2466,14 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, ...@@ -2466,21 +2466,14 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
return error; return error;
} }
static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned long flags) static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
{ {
u32 av;
int rc;
rc = secondary_ops->file_mmap(file, prot, flags);
if (rc)
return rc;
if (file) { if (file) {
/* read access is always possible with a mapping */ /* read access is always possible with a mapping */
av = FILE__READ; u32 av = FILE__READ;
/* write access only matters if the mapping is shared */ /* write access only matters if the mapping is shared */
if ((flags & MAP_TYPE) == MAP_SHARED && (prot & PROT_WRITE)) if (shared && (prot & PROT_WRITE))
av |= FILE__WRITE; av |= FILE__WRITE;
if (prot & PROT_EXEC) if (prot & PROT_EXEC)
...@@ -2491,6 +2484,18 @@ static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned lon ...@@ -2491,6 +2484,18 @@ static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned lon
return 0; return 0;
} }
static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned long flags)
{
int rc;
rc = secondary_ops->file_mmap(file, prot, flags);
if (rc)
return rc;
return file_map_prot_check(file, prot,
(flags & MAP_TYPE) == MAP_SHARED);
}
static int selinux_file_mprotect(struct vm_area_struct *vma, static int selinux_file_mprotect(struct vm_area_struct *vma,
unsigned long prot) unsigned long prot)
{ {
...@@ -2500,7 +2505,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, ...@@ -2500,7 +2505,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
if (rc) if (rc)
return rc; return rc;
return selinux_file_mmap(vma->vm_file, prot, vma->vm_flags); return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
} }
static int selinux_file_lock(struct file *file, unsigned int cmd) static int selinux_file_lock(struct file *file, unsigned int cmd)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment