take security_mmap_file() outside of ->mmap_sem
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / security / security.c
index d91c66d3956bc6106fe33e52fceeac81013cd5e3..3b11b3b72fe2f0af5f561fbbff4dcadb60a4a59a 100644 (file)
@@ -20,6 +20,9 @@
 #include <linux/ima.h>
 #include <linux/evm.h>
 #include <linux/fsnotify.h>
+#include <linux/mman.h>
+#include <linux/mount.h>
+#include <linux/personality.h>
 #include <net/flow.h>
 
 #define MAX_LSM_EVM_XATTR      2
@@ -657,11 +660,35 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        return security_ops->file_ioctl(file, cmd, arg);
 }
 
-int security_mmap_file(struct file *file, unsigned long reqprot,
-                       unsigned long prot, unsigned long flags)
+int security_mmap_file(struct file *file, unsigned long prot,
+                       unsigned long flags)
 {
+       unsigned long reqprot = prot;
        int ret;
-
+       /*
+        * Does the application expect PROT_READ to imply PROT_EXEC?
+        *
+        * (the exception is when the underlying filesystem is noexec
+        *  mounted, in which case we dont add PROT_EXEC.)
+        */
+       if (!(reqprot & PROT_READ))
+               goto out;
+       if (!(current->personality & READ_IMPLIES_EXEC))
+               goto out;
+       if (!file) {
+               prot |= PROT_EXEC;
+       } else if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) {
+#ifndef CONFIG_MMU
+               unsigned long caps = 0;
+               struct address_space *mapping = file->f_mapping;
+               if (mapping && mapping->backing_dev_info)
+                       caps = mapping->backing_dev_info->capabilities;
+               if (!(caps & BDI_CAP_EXEC_MAP))
+                       goto out;
+#endif
+               prot |= PROT_EXEC;
+       }
+out:
        ret = security_ops->mmap_file(file, reqprot, prot, flags);
        if (ret)
                return ret;