From: James Morris 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: James Morris Signed-off-by: Roland McGrath Signed-off-by: Andrew Morton --- 25-akpm/security/selinux/hooks.c | 27 ++++++++++++++++----------- 1 files changed, 16 insertions(+), 11 deletions(-) diff -puN security/selinux/hooks.c~fix-bugs-in-selinux-mprotect-hook security/selinux/hooks.c --- 25/security/selinux/hooks.c~fix-bugs-in-selinux-mprotect-hook Thu Sep 30 16:10:25 2004 +++ 25-akpm/security/selinux/hooks.c Thu Sep 30 16:10:25 2004 @@ -2458,21 +2458,14 @@ static int selinux_file_ioctl(struct fil 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) { /* read access is always possible with a mapping */ - av = FILE__READ; + u32 av = FILE__READ; /* 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; if (prot & PROT_EXEC) @@ -2483,6 +2476,18 @@ static int selinux_file_mmap(struct file 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, unsigned long prot) { @@ -2492,7 +2497,7 @@ static int selinux_file_mprotect(struct if (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) _