diff options
Diffstat (limited to 'security/security.c')
-rw-r--r-- | security/security.c | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/security/security.c b/security/security.c index 5497a57fba01..3efc9b12aef4 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -20,6 +20,9 @@ | |||
20 | #include <linux/ima.h> | 20 | #include <linux/ima.h> |
21 | #include <linux/evm.h> | 21 | #include <linux/evm.h> |
22 | #include <linux/fsnotify.h> | 22 | #include <linux/fsnotify.h> |
23 | #include <linux/mman.h> | ||
24 | #include <linux/mount.h> | ||
25 | #include <linux/personality.h> | ||
23 | #include <net/flow.h> | 26 | #include <net/flow.h> |
24 | 27 | ||
25 | #define MAX_LSM_EVM_XATTR 2 | 28 | #define MAX_LSM_EVM_XATTR 2 |
@@ -657,18 +660,56 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
657 | return security_ops->file_ioctl(file, cmd, arg); | 660 | return security_ops->file_ioctl(file, cmd, arg); |
658 | } | 661 | } |
659 | 662 | ||
660 | int security_file_mmap(struct file *file, unsigned long reqprot, | 663 | static inline unsigned long mmap_prot(struct file *file, unsigned long prot) |
661 | unsigned long prot, unsigned long flags, | ||
662 | unsigned long addr, unsigned long addr_only) | ||
663 | { | 664 | { |
664 | int ret; | 665 | /* |
666 | * Does we have PROT_READ and does the application expect | ||
667 | * it to imply PROT_EXEC? If not, nothing to talk about... | ||
668 | */ | ||
669 | if ((prot & (PROT_READ | PROT_EXEC)) != PROT_READ) | ||
670 | return prot; | ||
671 | if (!(current->personality & READ_IMPLIES_EXEC)) | ||
672 | return prot; | ||
673 | /* | ||
674 | * if that's an anonymous mapping, let it. | ||
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)) { | ||
683 | #ifndef CONFIG_MMU | ||
684 | unsigned long caps = 0; | ||
685 | struct address_space *mapping = file->f_mapping; | ||
686 | if (mapping && mapping->backing_dev_info) | ||
687 | caps = mapping->backing_dev_info->capabilities; | ||
688 | if (!(caps & BDI_CAP_EXEC_MAP)) | ||
689 | return prot; | ||
690 | #endif | ||
691 | return prot | PROT_EXEC; | ||
692 | } | ||
693 | /* anything on noexec mount won't get PROT_EXEC */ | ||
694 | return prot; | ||
695 | } | ||
665 | 696 | ||
666 | ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); | 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); | ||
667 | if (ret) | 703 | if (ret) |
668 | return ret; | 704 | return ret; |
669 | return ima_file_mmap(file, prot); | 705 | return ima_file_mmap(file, prot); |
670 | } | 706 | } |
671 | 707 | ||
708 | int security_mmap_addr(unsigned long addr) | ||
709 | { | ||
710 | return security_ops->mmap_addr(addr); | ||
711 | } | ||
712 | |||
672 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, | 713 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, |
673 | unsigned long prot) | 714 | unsigned long prot) |
674 | { | 715 | { |