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); |
