[RFC PATCH] ima: fix ima_file_mmap circular locking dependency

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The LSM security_mmap_file hook is called before the mmap_sem is taken.
This results in IMA taking the i_mutex before the mmap_sem, yet the
normal locking order is mmap_sem, i_mutex.

To resolve this problem, rename and call ima_mmap_file() after taking
the mmap_sem.

Reported-by: syzbot+5ab61747675a87ea359d@xxxxxxxxxxxxxxxxxxxxxxxxx
Signed-off-by: Mimi Zohar <zohar@xxxxxxxxxxxxx>
---
 include/linux/ima.h               | 4 ++--
 ipc/shm.c                         | 5 +++++
 mm/util.c                         | 8 ++++++++
 security/integrity/ima/ima_main.c | 2 +-
 security/security.c               | 8 ++------
 5 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 71796a0959d9..10adb38e0e43 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -17,7 +17,7 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
 extern int ima_file_check(struct file *file, int mask);
 extern void ima_post_create_tmpfile(struct inode *inode);
 extern void ima_file_free(struct file *file);
-extern int ima_file_mmap(struct file *file, unsigned long prot);
+extern int ima_mmap_file(struct file *file, unsigned long prot);
 extern int ima_load_data(enum kernel_load_data_id id);
 extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
 extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
@@ -65,7 +65,7 @@ static inline void ima_file_free(struct file *file)
 	return;
 }
 
-static inline int ima_file_mmap(struct file *file, unsigned long prot)
+static inline int ima_mmap_file(struct file *file, unsigned long prot)
 {
 	return 0;
 }
diff --git a/ipc/shm.c b/ipc/shm.c
index ce1ca9f7c6e9..a712c7d426f0 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -34,6 +34,7 @@
 #include <linux/mman.h>
 #include <linux/shmem_fs.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/syscalls.h>
 #include <linux/audit.h>
 #include <linux/capability.h>
@@ -1549,6 +1550,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
 		goto out_fput;
 	}
 
+	err = ima_mmap_file(file, prot);
+	if (err)
+		goto out_fput;
+
 	if (addr && !(shmflg & SHM_REMAP)) {
 		err = -EINVAL;
 		if (addr + size < addr)
diff --git a/mm/util.c b/mm/util.c
index 9834c4ab7d8e..dbf2c15caacd 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -9,6 +9,7 @@
 #include <linux/sched/mm.h>
 #include <linux/sched/task_stack.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
 #include <linux/mman.h>
@@ -360,6 +361,13 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
 	if (!ret) {
 		if (down_write_killable(&mm->mmap_sem))
 			return -EINTR;
+
+		ret = ima_mmap_file(file, prot);
+		if (ret) {
+			up_write(&mm->mmap_sem);
+			return ret;
+		}
+
 		ret = do_mmap_pgoff(file, addr, len, prot, flag, pgoff,
 				    &populate, &uf);
 		up_write(&mm->mmap_sem);
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 45d9ece88668..14678665cdc8 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -380,7 +380,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
  * On success return 0.  On integrity appraisal error, assuming the file
  * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
  */
-int ima_file_mmap(struct file *file, unsigned long prot)
+int ima_mmap_file(struct file *file, unsigned long prot)
 {
 	u32 secid;
 
diff --git a/security/security.c b/security/security.c
index a749d884faec..e324c425e466 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1410,12 +1410,8 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
 int security_mmap_file(struct file *file, unsigned long prot,
 			unsigned long flags)
 {
-	int ret;
-	ret = call_int_hook(mmap_file, 0, file, prot,
-					mmap_prot(file, prot), flags);
-	if (ret)
-		return ret;
-	return ima_file_mmap(file, prot);
+	return call_int_hook(mmap_file, 0, file, prot,
+			     mmap_prot(file, prot), flags);
 }
 
 int security_mmap_addr(unsigned long addr)
-- 
2.7.5




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux Kernel]     [Linux Kernel Hardening]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux