All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mimi Zohar <zohar@us.ibm.com>
To: linux-security-module@vger.kernel.org
Cc: Mimi Zohar <zohar@linux.vnet.ibm.com>,
	linux-kernel@vger.kernel.org, Al Viro <viro@ZenIV.linux.org.uk>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Mimi Zohar <zohar@us.ibm.com>
Subject: [PATCH] vfs: fix IMA lockdep circular locking dependency
Date: Sun, 13 May 2012 22:47:11 -0400	[thread overview]
Message-ID: <1336963631-3541-1-git-send-email-zohar@us.ibm.com> (raw)

From: Mimi Zohar <zohar@linux.vnet.ibm.com>

This patch has been updated to move the ima_file_mmap() call from
security_file_mmap() to the new vm_mmap() function.

---

The circular lockdep is caused by allocating the 'iint' for mmapped
files.  Originally when an 'iint' was allocated for every inode
in inode_alloc_security(), before the inode was accessible, no
locking was necessary.  Commits bc7d2a3e and 196f518 changed this
behavior and allocated the 'iint' on a per need basis, resulting in
the mmap_sem being taken before the i_mutex for mmapped files.

Possible unsafe locking scenario:
       CPU0                    CPU1
       ----                    ----
lock(&mm->mmap_sem);
                              lock(&sb->s_type->i_mutex_key);
                              lock(&mm->mmap_sem);
lock(&sb->s_type->i_mutex_key);

The existing security_file_mmap() hook is after the mmap_sem is taken.
This patch moves the ima_file_mmap() call from security_file_mmap() to
prior to the mmap_sem being taken.

Changelog v2:
- With commit "6be5ceb VM: add "vm_mmap()" helper function", moving the
ima_file_mmap() call is simplified.  This patch moves the ima_file_mmap()
call to vm_mmap(), and to binfmt_elf.c: elf_map().

Changelog v1:
- Instead of just pre-allocating the iint in a new hook, do ALL of the
work in the new/moved ima_file_mmap() hook. (Based on Eric Paris' suggestion.)
- Removed do_mmap_with_sem() helper function.
- export ima_file_mmap()

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Acked-by: Eric Paris <eparis@redhat.com>
---
 fs/binfmt_elf.c                   |    6 ++++++
 mm/mmap.c                         |   11 +++++++++++
 mm/nommu.c                        |   11 +++++++++++
 security/integrity/ima/ima_main.c |    1 +
 security/security.c               |    7 +------
 5 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 16f7354..0d0514f 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -28,6 +28,7 @@
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/random.h>
 #include <linux/elf.h>
 #include <linux/utsname.h>
@@ -321,6 +322,7 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
 	unsigned long map_addr;
 	unsigned long size = eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr);
 	unsigned long off = eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr);
+	unsigned long ret;
 	addr = ELF_PAGESTART(addr);
 	size = ELF_PAGEALIGN(size);
 
@@ -329,6 +331,10 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
 	if (!size)
 		return addr;
 
+	ret = ima_file_mmap(filep, prot);
+	if (ret < 0)
+		return ret;
+
 	down_write(&current->mm->mmap_sem);
 	/*
 	* total_size is the size of the ELF (interpreter) image.
diff --git a/mm/mmap.c b/mm/mmap.c
index 848ef52..87e6948 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <linux/personality.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/hugetlb.h>
 #include <linux/profile.h>
 #include <linux/export.h>
@@ -1109,9 +1110,14 @@ unsigned long vm_mmap(struct file *file, unsigned long addr,
 	unsigned long ret;
 	struct mm_struct *mm = current->mm;
 
+	ret = ima_file_mmap(file, prot);
+	if (ret < 0)
+		goto err;
+
 	down_write(&mm->mmap_sem);
 	ret = do_mmap(file, addr, len, prot, flag, offset);
 	up_write(&mm->mmap_sem);
+err:
 	return ret;
 }
 EXPORT_SYMBOL(vm_mmap);
@@ -1147,10 +1153,15 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
 
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 
+	retval = ima_file_mmap(file, prot);
+	if (retval < 0)
+		goto err_out;
+
 	down_write(&current->mm->mmap_sem);
 	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up_write(&current->mm->mmap_sem);
 
+err_out:
 	if (file)
 		fput(file);
 out:
diff --git a/mm/nommu.c b/mm/nommu.c
index bb8f4f0..2b13bd3 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -27,6 +27,7 @@
 #include <linux/mount.h>
 #include <linux/personality.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/syscalls.h>
 #include <linux/audit.h>
 
@@ -1490,9 +1491,14 @@ unsigned long vm_mmap(struct file *file, unsigned long addr,
 	unsigned long ret;
 	struct mm_struct *mm = current->mm;
 
+	ret = ima_file_mmap(file, prot);
+	if (ret < 0)
+		goto err;
+
 	down_write(&mm->mmap_sem);
 	ret = do_mmap(file, addr, len, prot, flag, offset);
 	up_write(&mm->mmap_sem);
+err:
 	return ret;
 }
 EXPORT_SYMBOL(vm_mmap);
@@ -1513,10 +1519,15 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
 
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 
+	retval = ima_file_mmap(file, prot);
+	if (retval < 0)
+		goto err_out;
+
 	down_write(&current->mm->mmap_sem);
 	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up_write(&current->mm->mmap_sem);
 
+err_out:
 	if (file)
 		fput(file);
 out:
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index b17be79..91eda7f 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -176,6 +176,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
 					 MAY_EXEC, FILE_MMAP);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ima_file_mmap);
 
 /**
  * ima_bprm_check - based on policy, collect/store measurement.
diff --git a/security/security.c b/security/security.c
index bf619ff..e50bbf4 100644
--- a/security/security.c
+++ b/security/security.c
@@ -661,12 +661,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
 			unsigned long prot, unsigned long flags,
 			unsigned long addr, unsigned long addr_only)
 {
-	int ret;
-
-	ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only);
-	if (ret)
-		return ret;
-	return ima_file_mmap(file, prot);
+	return security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only);
 }
 
 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
-- 
1.7.7.6


             reply	other threads:[~2012-05-14  2:47 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-14  2:47 Mimi Zohar [this message]
2012-05-15  0:29 ` [PATCH] vfs: fix IMA lockdep circular locking dependency James Morris
2012-05-15  0:51   ` Mimi Zohar
2012-05-15 15:14     ` James Morris
2012-05-15 16:06       ` Mimi Zohar
2012-05-15 17:19 ` Linus Torvalds
2012-05-15 18:36   ` Mimi Zohar
2012-05-15 18:41   ` Linus Torvalds
2012-05-15 19:42     ` Eric Paris
2012-05-15 20:07       ` Mimi Zohar
2012-05-15 21:43         ` Linus Torvalds
2012-05-16  0:37           ` Linus Torvalds
2012-05-16  0:42             ` Al Viro
2012-05-16  0:45               ` Linus Torvalds
2012-05-16  1:53                 ` Linus Torvalds
2012-05-16 11:37                   ` James Morris
2012-05-16 11:38                     ` James Morris
2012-05-16 13:27                       ` Mimi Zohar
2012-05-16 13:42                     ` Eric Paris
2012-05-16 13:52                       ` Mimi Zohar
2012-05-16 14:06                         ` Eric Paris
2012-05-16 15:23                           ` Linus Torvalds
2012-05-16 15:47                           ` Mimi Zohar
2012-05-16 16:09                             ` Linus Torvalds
2012-05-16  2:18                 ` Al Viro
2012-05-23 21:18                   ` Mimi Zohar
2012-05-30  4:34                     ` Al Viro
2012-05-30 16:36                       ` Al Viro
2012-05-30 19:42                         ` Eric Paris
2012-05-30 20:24                           ` Al Viro
2012-05-30 20:28                             ` Linus Torvalds
2012-05-30 20:56                               ` Al Viro
2012-05-30 21:04                                 ` Linus Torvalds
2012-05-30 21:36                                   ` Al Viro
2012-05-30 22:51                                     ` Linus Torvalds
2012-05-31  0:28                                       ` Al Viro
2012-05-31  0:40                                         ` Linus Torvalds
2012-05-31  0:56                                           ` Al Viro
2012-05-31  3:55                                             ` Mimi Zohar
2012-05-31  4:20                                         ` James Morris
2012-05-30 20:33                             ` Mimi Zohar
2012-05-30 20:53                               ` Al Viro
2012-05-16 14:13             ` Eric Paris
2012-05-16 15:13               ` Linus Torvalds

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1336963631-3541-1-git-send-email-zohar@us.ibm.com \
    --to=zohar@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@ZenIV.linux.org.uk \
    --cc=zohar@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.