diff options
-rw-r--r-- | security/security.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/security/security.c b/security/security.c index 3b11b3b72fe2..3efc9b12aef4 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -660,36 +660,46 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
660 | return security_ops->file_ioctl(file, cmd, arg); | 660 | return security_ops->file_ioctl(file, cmd, arg); |
661 | } | 661 | } |
662 | 662 | ||
663 | int security_mmap_file(struct file *file, unsigned long prot, | 663 | static inline unsigned long mmap_prot(struct file *file, unsigned long prot) |
664 | unsigned long flags) | ||
665 | { | 664 | { |
666 | unsigned long reqprot = prot; | ||
667 | int ret; | ||
668 | /* | 665 | /* |
669 | * Does the application expect PROT_READ to imply PROT_EXEC? | 666 | * Does we have PROT_READ and does the application expect |
670 | * | 667 | * it to imply PROT_EXEC? If not, nothing to talk about... |
671 | * (the exception is when the underlying filesystem is noexec | ||
672 | * mounted, in which case we dont add PROT_EXEC.) | ||
673 | */ | 668 | */ |
674 | if (!(reqprot & PROT_READ)) | 669 | if ((prot & (PROT_READ | PROT_EXEC)) != PROT_READ) |
675 | goto out; | 670 | return prot; |
676 | if (!(current->personality & READ_IMPLIES_EXEC)) | 671 | if (!(current->personality & READ_IMPLIES_EXEC)) |
677 | goto out; | 672 | return prot; |
678 | if (!file) { | 673 | /* |
679 | prot |= PROT_EXEC; | 674 | * if that's an anonymous mapping, let it. |
680 | } else if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) { | 675 | */ |
676 | if (!file) | ||
677 | return prot | PROT_EXEC; | ||
678 | /* | ||
679 | * ditto if it's not on noexec mount, except that on !MMU we need | ||
680 | * BDI_CAP_EXEC_MMAP (== VM_MAYEXEC) in this case | ||
681 | */ | ||
682 | if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) { | ||
681 | #ifndef CONFIG_MMU | 683 | #ifndef CONFIG_MMU |
682 | unsigned long caps = 0; | 684 | unsigned long caps = 0; |
683 | struct address_space *mapping = file->f_mapping; | 685 | struct address_space *mapping = file->f_mapping; |
684 | if (mapping && mapping->backing_dev_info) | 686 | if (mapping && mapping->backing_dev_info) |
685 | caps = mapping->backing_dev_info->capabilities; | 687 | caps = mapping->backing_dev_info->capabilities; |
686 | if (!(caps & BDI_CAP_EXEC_MAP)) | 688 | if (!(caps & BDI_CAP_EXEC_MAP)) |
687 | goto out; | 689 | return prot; |
688 | #endif | 690 | #endif |
689 | prot |= PROT_EXEC; | 691 | return prot | PROT_EXEC; |
690 | } | 692 | } |
691 | out: | 693 | /* anything on noexec mount won't get PROT_EXEC */ |
692 | ret = security_ops->mmap_file(file, reqprot, prot, flags); | 694 | return prot; |
695 | } | ||
696 | |||
697 | int security_mmap_file(struct file *file, unsigned long prot, | ||
698 | unsigned long flags) | ||
699 | { | ||
700 | int ret; | ||
701 | ret = security_ops->mmap_file(file, prot, | ||
702 | mmap_prot(file, prot), flags); | ||
693 | if (ret) | 703 | if (ret) |
694 | return ret; | 704 | return ret; |
695 | return ima_file_mmap(file, prot); | 705 | return ima_file_mmap(file, prot); |