From: jjohansen@suse.de
To: linux-kernel@vger.kernel.org
Cc: linux-security-module@vger.kernel.org,
linux-fsdevel@vger.kernel.org, John Johansen <jjohansen@suse.de>,
Andreas Gruenbacher <agruen@suse.de>, Ingo Molnar <mingo@elte.hu>
Subject: [AppArmor 42/45] AppArmor: add lock subtyping so lockdep does not report false dependencies
Date: Mon, 14 May 2007 04:06:49 -0700 [thread overview]
Message-ID: <20070514110622.746784766@suse.de> (raw)
In-Reply-To: 20070514110607.549397248@suse.de
[-- Attachment #1: apparmor-lockdep.diff --]
[-- Type: text/plain, Size: 5942 bytes --]
AppArmor uses lock subtyping to avoid false positives from lockdep. The
profile lock is often taken nested, but it is guaranteed to be in a lock
safe order and not the same lock when done, so it is safe.
A third lock type (aa_lock_task_release) is given to the profile lock
when it is taken in soft irq context during task release (aa_release).
This is to avoid a false positive between the task lock and the profile
lock. In task context the profile lock wraps the task lock with irqs
off, but the kernel takes the task lock with irqs enabled. This won't
ever result in a deadlock because aa_release doesn't need to take the
task lock of the dead task that is released.
Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Cc: Ingo Molnar <mingo@elte.hu>
---
security/apparmor/apparmor.h | 7 +++++++
security/apparmor/inline.h | 25 ++++++++++++++++++-------
security/apparmor/locking.txt | 21 +++++++++++++++------
security/apparmor/main.c | 6 +++---
4 files changed, 43 insertions(+), 16 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -185,6 +185,13 @@ struct aa_audit {
#define AA_CHECK_DIR 2 /* file type is directory */
#define AA_CHECK_MANGLE 4 /* leave extra room for name mangling */
+/* lock subtypes so lockdep does not raise false dependencies */
+enum aa_lock_class {
+ aa_lock_normal,
+ aa_lock_nested,
+ aa_lock_task_release
+};
+
/* main.c */
extern int alloc_null_complain_profile(void);
extern void free_null_complain_profile(void);
--- a/security/apparmor/inline.h
+++ b/security/apparmor/inline.h
@@ -99,7 +99,8 @@ static inline void aa_free_task_context(
* While the profile is locked, local interrupts are disabled. This also
* gives us RCU reader safety.
*/
-static inline void lock_profile(struct aa_profile *profile)
+static inline void lock_profile_nested(struct aa_profile *profile,
+ enum aa_lock_class lock_class)
{
/* We always lock top-level profiles instead of children. */
if (profile)
@@ -112,7 +113,13 @@ static inline void lock_profile(struct a
* the task_free_security hook, which may run in RCU context.
*/
if (profile)
- spin_lock_irqsave(&profile->lock, profile->int_flags);
+ spin_lock_irqsave_nested(&profile->lock, profile->int_flags,
+ lock_class);
+}
+
+static inline void lock_profile(struct aa_profile *profile)
+{
+ lock_profile_nested(profile, aa_lock_normal);
}
/**
@@ -161,17 +168,21 @@ static inline void lock_both_profiles(st
*/
if (!profile1 || profile1 == profile2) {
if (profile2)
- spin_lock_irqsave(&profile2->lock, profile2->int_flags);
+ spin_lock_irqsave_nested(&profile2->lock,
+ profile2->int_flags,
+ aa_lock_normal);
} else if (profile1 > profile2) {
/* profile1 cannot be NULL here. */
- spin_lock_irqsave(&profile1->lock, profile1->int_flags);
+ spin_lock_irqsave_nested(&profile1->lock, profile1->int_flags,
+ aa_lock_normal);
if (profile2)
- spin_lock(&profile2->lock);
+ spin_lock_nested(&profile2->lock, aa_lock_nested);
} else {
/* profile2 cannot be NULL here. */
- spin_lock_irqsave(&profile2->lock, profile2->int_flags);
- spin_lock(&profile1->lock);
+ spin_lock_irqsave_nested(&profile2->lock, profile2->int_flags,
+ aa_lock_normal);
+ spin_lock_nested(&profile1->lock, aa_lock_nested);
}
}
--- a/security/apparmor/locking.txt
+++ b/security/apparmor/locking.txt
@@ -51,9 +51,18 @@ list, and can sleep. This ensures that p
won't race with itself. We release the profile_list_lock as soon as
possible to avoid stalling exec during profile loading/replacement/removal.
-lock_dep reports a false 'possible irq lock inversion dependency detected'
-when the profile lock is taken in aa_release. This is due to that the
-task_lock is often taken inside the profile lock but other kernel code
-takes the task_lock with interrupts enabled. A deadlock will not actually
-occur because apparmor does not take the task_lock in hard_irq or soft_irq
-context.
+AppArmor uses lock subtyping to avoid false positives from lockdep. The
+profile lock is often taken nested, but it is guaranteed to be in a lock
+safe order and not the same lock when done, so it is safe.
+
+A third lock type (aa_lock_task_release) is given to the profile lock
+when it is taken in soft irq context during task release (aa_release).
+This is to avoid a false positive between the task lock and the profile
+lock. In task context the profile lock wraps the task lock with irqs
+off, but the kernel takes the task lock with irqs enabled. This won't
+result in a deadlock because for a deadlock to occur the kernel must
+take dead task A's lock (irqs on), the rcu callback hook freeing
+dead task A must be run and AppArmor must be changing the profile on
+dead task A. The kernel should not be taking a dead task's task_lock
+at the same time the task is being freed by task rcu cleanup other wise
+the task would not be out of its quiescent period.
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -1081,8 +1081,8 @@ void aa_release(struct task_struct *task
* sufficient to prevent the replacement race so we do not lock
* the task.
*
- * lock_dep reports a false 'possible irq lock inversion dependency'
- * between the profile lock and the task_lock.
+ * Use lock subtyping to avoid lockdep reporting a false irq
+ * possible inversion between the task_lock and profile_lock
*
* We also avoid taking the task_lock here because lock_dep
* would report another false {softirq-on-W} potential irq_lock
@@ -1095,7 +1095,7 @@ void aa_release(struct task_struct *task
repeat:
profile = aa_get_profile(task);
if (profile) {
- lock_profile(profile);
+ lock_profile_nested(profile, aa_lock_task_release);
cxt = aa_task_context(task);
if (unlikely(!cxt || cxt->profile != profile)) {
unlock_profile(profile);
--
next prev parent reply other threads:[~2007-05-14 11:32 UTC|newest]
Thread overview: 213+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
2007-05-14 11:06 ` [AppArmor 01/45] Pass struct vfsmount to the inode_create LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 02/45] Pass struct path down to remove_suid and children jjohansen
2007-05-14 11:06 ` [AppArmor 03/45] Add a vfsmount parameter to notify_change() jjohansen
2007-05-14 11:06 ` [AppArmor 04/45] Pass struct vfsmount to the inode_setattr LSM hook jjohansen
2007-05-14 11:06 ` jjohansen
2007-05-14 11:06 ` [AppArmor 05/45] Add struct vfsmount parameter to vfs_mkdir() jjohansen
2007-05-14 11:06 ` [AppArmor 06/45] Pass struct vfsmount to the inode_mkdir LSM hook jjohansen
2007-05-14 11:06 ` jjohansen
2007-05-14 11:06 ` [AppArmor 07/45] Add a struct vfsmount parameter to vfs_mknod() jjohansen
2007-05-14 11:06 ` jjohansen
2007-05-14 11:06 ` [AppArmor 08/45] Pass struct vfsmount to the inode_mknod LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 09/45] Add a struct vfsmount parameter to vfs_symlink() jjohansen
2007-05-14 11:06 ` [AppArmor 10/45] Pass struct vfsmount to the inode_symlink LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 11/45] Pass struct vfsmount to the inode_readlink " jjohansen
2007-05-14 11:06 ` [AppArmor 12/45] Add struct vfsmount parameters to vfs_link() jjohansen
2007-05-14 11:06 ` [AppArmor 13/45] Pass the struct vfsmounts to the inode_link LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 14/45] Add a struct vfsmount parameter to vfs_rmdir() jjohansen
2007-05-14 11:06 ` [AppArmor 15/45] Pass struct vfsmount to the inode_rmdir LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 16/45] Call lsm hook before unhashing dentry in vfs_rmdir() jjohansen
2007-05-14 11:06 ` [AppArmor 17/45] Add a struct vfsmount parameter to vfs_unlink() jjohansen
2007-05-14 11:06 ` [AppArmor 18/45] Pass struct vfsmount to the inode_unlink LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 19/45] Add struct vfsmount parameters to vfs_rename() jjohansen
2007-05-14 11:06 ` [AppArmor 20/45] Pass struct vfsmount to the inode_rename LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 21/45] Add a struct vfsmount parameter to vfs_setxattr() jjohansen
2007-05-14 11:06 ` [AppArmor 22/45] Pass struct vfsmount to the inode_setxattr LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 23/45] Add a struct vfsmount parameter to vfs_getxattr() jjohansen
2007-05-14 11:06 ` [AppArmor 24/45] Pass struct vfsmount to the inode_getxattr LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 25/45] Add a struct vfsmount parameter to vfs_listxattr() jjohansen
2007-05-14 11:06 ` jjohansen
2007-05-14 11:06 ` [AppArmor 26/45] Pass struct vfsmount to the inode_listxattr LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 27/45] Add a struct vfsmount parameter to vfs_removexattr() jjohansen
2007-05-14 11:06 ` [AppArmor 28/45] Pass struct vfsmount to the inode_removexattr LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 29/45] Fix __d_path() for lazy unmounts and make it unambiguous jjohansen
2007-05-14 11:06 ` [AppArmor 30/45] Make d_path() consistent across mount operations jjohansen
2007-05-14 11:06 ` [AppArmor 31/45] Add d_namespace_path() to compute namespace relative pathnames jjohansen
2007-05-14 11:06 ` [AppArmor 32/45] Enable LSM hooks to distinguish operations on file descriptors from operations on pathnames jjohansen
2007-05-14 11:06 ` [AppArmor 33/45] Pass struct file down the inode_*xattr security LSM hooks jjohansen
2007-05-14 11:06 ` [AppArmor 34/45] Factor out sysctl pathname code jjohansen
2007-05-14 11:06 ` [AppArmor 35/45] Allow permission functions to tell between parent and leaf checks jjohansen
2007-05-15 9:08 ` Pavel Machek
2007-05-14 11:06 ` [AppArmor 36/45] Export audit subsystem for use by modules jjohansen
2007-05-14 11:06 ` [AppArmor 37/45] AppArmor: Main Part jjohansen
2007-05-15 9:12 ` Pavel Machek
2007-05-14 11:06 ` [AppArmor 38/45] AppArmor: Module and LSM hooks jjohansen
2007-05-15 9:14 ` Pavel Machek
2007-05-23 16:16 ` Andreas Gruenbacher
2007-06-04 10:55 ` Pavel Machek
2007-06-04 11:25 ` Andreas Gruenbacher
2007-06-04 11:35 ` Pavel Machek
2007-06-04 11:42 ` Andreas Gruenbacher
2007-06-04 13:12 ` Pavel Machek
2007-06-04 14:30 ` Andreas Gruenbacher
2007-06-06 13:09 ` Stephen Smalley
2007-06-10 23:10 ` Andreas Gruenbacher
2007-06-11 14:33 ` Stephen Smalley
2007-06-11 15:55 ` Andreas Gruenbacher
2007-06-11 19:02 ` Serge E. Hallyn
2007-06-12 13:00 ` Stephen Smalley
2007-06-12 15:34 ` Serge E. Hallyn
2007-06-12 5:17 ` Karl MacMillan
2007-06-12 19:00 ` Serge E. Hallyn
2007-06-12 13:13 ` Stephen Smalley
2007-06-12 23:50 ` Andreas Gruenbacher
2007-06-09 12:58 ` Pavel Machek
2007-06-09 13:44 ` Andreas Gruenbacher
2007-06-12 13:06 ` Pavel Machek
2007-05-14 11:06 ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching jjohansen
2007-05-15 9:20 ` Pavel Machek
2007-06-04 21:03 ` Andreas Gruenbacher
2007-06-06 13:26 ` Stephen Smalley
2007-06-06 17:32 ` Greg KH
2007-06-09 23:47 ` Pavel Machek
2007-06-08 22:03 ` Andreas Gruenbacher
2007-06-09 0:17 ` Greg KH
2007-06-09 1:06 ` david
2007-06-10 8:34 ` Pavel Machek
2007-06-10 9:04 ` david
2007-06-10 20:04 ` Casey Schaufler
2007-06-10 20:51 ` Crispin Cowan
2007-06-11 6:45 ` david
2007-06-11 8:29 ` Sean
2007-06-11 9:33 ` david
2007-06-11 11:34 ` Sean
2007-06-11 11:00 ` Pavel Machek
2007-06-10 21:05 ` Pavel Machek
2007-06-11 6:27 ` david
2007-06-14 19:16 ` Jack Stone
2007-06-15 0:18 ` david
2007-06-15 17:01 ` Greg KH
2007-06-12 17:03 ` Lars Marowsky-Bree
2007-06-09 5:18 ` david
2007-06-09 5:46 ` Sean
2007-06-09 7:13 ` david
2007-06-09 7:36 ` Sean
2007-06-09 8:06 ` david
2007-06-09 8:10 ` Sean
2007-06-09 15:17 ` Andreas Gruenbacher
2007-06-09 16:36 ` Sean
2007-06-09 15:33 ` Joshua Brindle
2007-06-09 16:18 ` Kyle Moffett
2007-06-09 16:46 ` david
2007-06-09 17:06 ` Kyle Moffett
2007-06-09 17:32 ` david
2007-06-09 19:50 ` Kyle Moffett
2007-06-09 20:43 ` david
2007-06-10 20:54 ` Crispin Cowan
2007-06-10 21:17 ` Joshua Brindle
2007-06-09 15:05 ` Andreas Gruenbacher
2007-06-10 17:09 ` Crispin Cowan
2007-06-15 16:50 ` Greg KH
2007-06-15 18:01 ` Casey Schaufler
2007-06-15 18:15 ` Stephen Smalley
2007-06-15 20:43 ` Casey Schaufler
2007-06-15 21:14 ` Greg KH
2007-06-15 21:28 ` Karl MacMillan
2007-06-15 21:44 ` Greg KH
2007-06-15 22:24 ` Karl MacMillan
2007-06-18 13:33 ` Stephen Smalley
2007-06-21 15:54 ` Andreas Gruenbacher
2007-06-15 22:37 ` Casey Schaufler
2007-06-18 12:47 ` Stephen Smalley
2007-06-15 20:06 ` Pavel Machek
2007-06-15 21:11 ` Greg KH
2007-06-15 21:42 ` James Morris
2007-06-15 23:50 ` Greg KH
2007-06-16 1:21 ` James Morris
2007-06-16 2:57 ` Casey Schaufler
2007-06-16 3:39 ` James Morris
2007-06-18 1:51 ` Casey Schaufler
2007-06-18 11:29 ` Joshua Brindle
2007-06-16 4:23 ` Greg KH
2007-06-15 23:30 ` Crispin Cowan
2007-06-15 23:49 ` Greg KH
2007-06-16 0:01 ` david
2007-06-16 0:20 ` Pavel Machek
2007-06-22 9:59 ` Andreas Gruenbacher
2007-06-16 0:31 ` Greg KH
2007-06-16 8:09 ` david
2007-06-16 16:24 ` Greg KH
2007-06-16 1:41 ` James Morris
2007-06-16 0:18 ` Seth Arnold
2007-06-16 0:29 ` Greg KH
2007-06-16 1:46 ` James Morris
2007-06-16 2:19 ` James Morris
2007-06-18 18:48 ` Crispin Cowan
2007-06-21 16:01 ` Andreas Gruenbacher
2007-06-21 17:59 ` Pavel Machek
2007-06-16 0:02 ` Pavel Machek
2007-06-21 16:08 ` Lars Marowsky-Bree
2007-06-21 18:33 ` Pavel Machek
2007-06-21 19:24 ` Lars Marowsky-Bree
2007-06-21 19:42 ` James Morris
2007-06-21 19:54 ` Lars Marowsky-Bree
2007-06-21 20:59 ` Stephen Smalley
2007-06-21 21:17 ` Lars Marowsky-Bree
2007-06-22 0:16 ` Joshua Brindle
2007-06-22 0:19 ` Lars Marowsky-Bree
2007-06-22 0:28 ` david
2007-06-22 3:45 ` Joshua Brindle
2007-06-22 5:07 ` david
2007-06-22 10:49 ` Lars Marowsky-Bree
2007-06-22 11:19 ` Stephen Smalley
2007-06-22 11:34 ` Neil Brown
2007-06-22 11:48 ` Stephen Smalley
2007-06-22 11:37 ` Lars Marowsky-Bree
2007-06-22 12:41 ` Stephen Smalley
2007-06-22 12:54 ` Lars Marowsky-Bree
2007-06-22 13:22 ` Stephen Smalley
2007-06-22 14:49 ` Stephen Smalley
2007-06-22 16:06 ` Casey Schaufler
2007-06-22 0:34 ` Chris Mason
2007-06-22 1:06 ` James Morris
2007-06-22 4:17 ` Crispin Cowan
2007-06-22 12:20 ` Stephen Smalley
2007-06-22 7:40 ` John Johansen
2007-06-22 12:17 ` Chris Mason
2007-06-22 13:48 ` James Morris
2007-06-22 14:02 ` Chris Mason
2007-06-22 14:23 ` James Morris
2007-06-22 17:30 ` Chris Mason
2007-06-23 0:11 ` Chris Wright
2007-06-24 0:10 ` Toshiharu Harada
2007-06-24 0:40 ` Toshiharu Harada
2007-06-26 21:01 ` Crispin Cowan
2007-06-24 20:43 ` Pavel Machek
2007-06-22 18:12 ` david
2007-06-25 15:14 ` Pavel Machek
2007-06-25 21:02 ` david
2007-06-26 8:50 ` Lars Marowsky-Bree
2007-06-22 8:06 ` John Johansen
2007-06-22 11:53 ` Stephen Smalley
2007-06-22 12:42 ` Lars Marowsky-Bree
2007-06-22 12:46 ` Stephen Smalley
2007-06-22 18:35 ` david
2007-06-21 20:07 ` Pavel Machek
2007-06-21 20:21 ` Lars Marowsky-Bree
2007-06-21 23:25 ` John Johansen
2007-06-21 19:30 ` david
2007-06-21 19:35 ` Lars Marowsky-Bree
2007-06-21 19:52 ` Pavel Machek
2007-06-15 23:33 ` Seth Arnold
2007-06-15 23:39 ` Pavel Machek
2007-06-16 0:07 ` Seth Arnold
2007-06-11 15:16 ` Stephen Smalley
2007-05-14 11:06 ` [AppArmor 40/45] AppArmor: all the rest jjohansen
2007-05-14 11:06 ` [AppArmor 41/45] Add AppArmor LSM to security/Makefile jjohansen
2007-05-14 11:06 ` jjohansen [this message]
2007-05-14 11:06 ` [AppArmor 43/45] Switch to vfs_permission() in do_path_lookup() jjohansen
2007-05-14 11:06 ` [AppArmor 44/45] Switch to vfs_permission() in sys_fchdir() jjohansen
2007-05-14 11:06 ` jjohansen
2007-05-14 11:06 ` [AppArmor 45/45] Fix file_permission() jjohansen
2007-05-14 13:50 ` [AppArmor 00/45] AppArmor security module overview John Johansen
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=20070514110622.746784766@suse.de \
--to=jjohansen@suse.de \
--cc=agruen@suse.de \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=mingo@elte.hu \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).