diff mbox series

[1/2] security/apparmor: Replace homebrew use of write_can_lock with lockdep

Message ID 1507041166-10618-1-git-send-email-will.deacon@arm.com
State Superseded
Headers show
Series [1/2] security/apparmor: Replace homebrew use of write_can_lock with lockdep | expand

Commit Message

Will Deacon Oct. 3, 2017, 2:32 p.m. UTC
The lockdep subsystem provides a robust way to assert that a lock is
held, so use that instead of write_can_lock, which can give incorrect
results for qrwlocks.

Cc: John Johansen <john.johansen@canonical.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>

---
 security/apparmor/include/lib.h | 11 -----------
 security/apparmor/label.c       |  8 ++++----
 2 files changed, 4 insertions(+), 15 deletions(-)

-- 
2.1.4

Comments

Peter Zijlstra Oct. 3, 2017, 3:07 p.m. UTC | #1
On Tue, Oct 03, 2017 at 03:32:45PM +0100, Will Deacon wrote:
> The lockdep subsystem provides a robust way to assert that a lock is

> held, so use that instead of write_can_lock, which can give incorrect

> results for qrwlocks.

> 

> Cc: John Johansen <john.johansen@canonical.com>

> Cc: Peter Zijlstra <peterz@infradead.org>

> Signed-off-by: Will Deacon <will.deacon@arm.com>


Thanks Will, good to be able to finally remove that API.
John Johansen Oct. 3, 2017, 3:33 p.m. UTC | #2
On 10/03/2017 07:32 AM, Will Deacon wrote:
> The lockdep subsystem provides a robust way to assert that a lock is

> held, so use that instead of write_can_lock, which can give incorrect

> results for qrwlocks.

> 

> Cc: John Johansen <john.johansen@canonical.com>

> Cc: Peter Zijlstra <peterz@infradead.org>

> Signed-off-by: Will Deacon <will.deacon@arm.com>


oh nice,

Acked-by: John Johansen <john.johansen@canonical.com>




> ---

>  security/apparmor/include/lib.h | 11 -----------

>  security/apparmor/label.c       |  8 ++++----

>  2 files changed, 4 insertions(+), 15 deletions(-)

> 

> diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h

> index 436b3a722357..f546707a2bbb 100644

> --- a/security/apparmor/include/lib.h

> +++ b/security/apparmor/include/lib.h

> @@ -19,17 +19,6 @@

>  

>  #include "match.h"

>  

> -/* Provide our own test for whether a write lock is held for asserts

> - * this is because on none SMP systems write_can_lock will always

> - * resolve to true, which is what you want for code making decisions

> - * based on it, but wrong for asserts checking that the lock is held

> - */

> -#ifdef CONFIG_SMP

> -#define write_is_locked(X) !write_can_lock(X)

> -#else

> -#define write_is_locked(X) (1)

> -#endif /* CONFIG_SMP */

> -

>  /*

>   * DEBUG remains global (no per profile flag) since it is mostly used in sysctl

>   * which is not related to profile accesses.

> diff --git a/security/apparmor/label.c b/security/apparmor/label.c

> index c5b99b954580..ad28e03a6f30 100644

> --- a/security/apparmor/label.c

> +++ b/security/apparmor/label.c

> @@ -80,7 +80,7 @@ void __aa_proxy_redirect(struct aa_label *orig, struct aa_label *new)

>  

>  	AA_BUG(!orig);

>  	AA_BUG(!new);

> -	AA_BUG(!write_is_locked(&labels_set(orig)->lock));

> +	lockdep_assert_held_exclusive(&labels_set(orig)->lock);

>  

>  	tmp = rcu_dereference_protected(orig->proxy->label,

>  					&labels_ns(orig)->lock);

> @@ -571,7 +571,7 @@ static bool __label_remove(struct aa_label *label, struct aa_label *new)

>  

>  	AA_BUG(!ls);

>  	AA_BUG(!label);

> -	AA_BUG(!write_is_locked(&ls->lock));

> +	lockdep_assert_held_exclusive(&ls->lock);

>  

>  	if (new)

>  		__aa_proxy_redirect(label, new);

> @@ -608,7 +608,7 @@ static bool __label_replace(struct aa_label *old, struct aa_label *new)

>  	AA_BUG(!ls);

>  	AA_BUG(!old);

>  	AA_BUG(!new);

> -	AA_BUG(!write_is_locked(&ls->lock));

> +	lockdep_assert_held_exclusive(&ls->lock);

>  	AA_BUG(new->flags & FLAG_IN_TREE);

>  

>  	if (!label_is_stale(old))

> @@ -645,7 +645,7 @@ static struct aa_label *__label_insert(struct aa_labelset *ls,

>  	AA_BUG(!ls);

>  	AA_BUG(!label);

>  	AA_BUG(labels_set(label) != ls);

> -	AA_BUG(!write_is_locked(&ls->lock));

> +	lockdep_assert_held_exclusive(&ls->lock);

>  	AA_BUG(label->flags & FLAG_IN_TREE);

>  

>  	/* Figure out where to put new node */

>
Will Deacon Oct. 3, 2017, 4:58 p.m. UTC | #3
On Tue, Oct 03, 2017 at 05:07:09PM +0200, Peter Zijlstra wrote:
> On Tue, Oct 03, 2017 at 03:32:45PM +0100, Will Deacon wrote:

> > The lockdep subsystem provides a robust way to assert that a lock is

> > held, so use that instead of write_can_lock, which can give incorrect

> > results for qrwlocks.

> > 

> > Cc: John Johansen <john.johansen@canonical.com>

> > Cc: Peter Zijlstra <peterz@infradead.org>

> > Signed-off-by: Will Deacon <will.deacon@arm.com>

> 

> Thanks Will, good to be able to finally remove that API.


Yup, but my grep-fu missed these guys in kernel/locking/spinlock.c:

	while (!raw_##op##_can_lock(lock) && (lock)->break_lock

so diff below to catch those and remove spin_can_lock too.

Let me spin a v2...

Will

--->8

diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 69e079c5ff98..1e3e48041800 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -278,12 +278,6 @@ static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
 	1 : ({ local_irq_restore(flags); 0; }); \
 })
 
-/**
- * raw_spin_can_lock - would raw_spin_trylock() succeed?
- * @lock: the spinlock in question.
- */
-#define raw_spin_can_lock(lock)	(!raw_spin_is_locked(lock))
-
 /* Include rwlock functions */
 #include <linux/rwlock.h>
 
@@ -396,11 +390,6 @@ static __always_inline int spin_is_contended(spinlock_t *lock)
 	return raw_spin_is_contended(&lock->rlock);
 }
 
-static __always_inline int spin_can_lock(spinlock_t *lock)
-{
-	return raw_spin_can_lock(&lock->rlock);
-}
-
 #define assert_spin_locked(lock)	assert_raw_spin_locked(&(lock)->rlock)
 
 /*
diff --git a/kernel/locking/spinlock.c b/kernel/locking/spinlock.c
index 42ee9d0a1ea4..8fd48b5552a7 100644
--- a/kernel/locking/spinlock.c
+++ b/kernel/locking/spinlock.c
@@ -66,7 +66,7 @@ void __lockfunc __raw_##op##_lock(locktype##_t *lock)			\
 									\
 		if (!(lock)->break_lock)				\
 			(lock)->break_lock = 1;				\
-		while (!raw_##op##_can_lock(lock) && (lock)->break_lock)\
+		while ((lock)->break_lock)				\
 			arch_##op##_relax(&lock->raw_lock);		\
 	}								\
 	(lock)->break_lock = 0;						\
@@ -86,7 +86,7 @@ unsigned long __lockfunc __raw_##op##_lock_irqsave(locktype##_t *lock)	\
 									\
 		if (!(lock)->break_lock)				\
 			(lock)->break_lock = 1;				\
-		while (!raw_##op##_can_lock(lock) && (lock)->break_lock)\
+		while ((lock)->break_lock)				\
 			arch_##op##_relax(&lock->raw_lock);		\
 	}								\
 	(lock)->break_lock = 0;						\
diff mbox series

Patch

diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h
index 436b3a722357..f546707a2bbb 100644
--- a/security/apparmor/include/lib.h
+++ b/security/apparmor/include/lib.h
@@ -19,17 +19,6 @@ 
 
 #include "match.h"
 
-/* Provide our own test for whether a write lock is held for asserts
- * this is because on none SMP systems write_can_lock will always
- * resolve to true, which is what you want for code making decisions
- * based on it, but wrong for asserts checking that the lock is held
- */
-#ifdef CONFIG_SMP
-#define write_is_locked(X) !write_can_lock(X)
-#else
-#define write_is_locked(X) (1)
-#endif /* CONFIG_SMP */
-
 /*
  * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
  * which is not related to profile accesses.
diff --git a/security/apparmor/label.c b/security/apparmor/label.c
index c5b99b954580..ad28e03a6f30 100644
--- a/security/apparmor/label.c
+++ b/security/apparmor/label.c
@@ -80,7 +80,7 @@  void __aa_proxy_redirect(struct aa_label *orig, struct aa_label *new)
 
 	AA_BUG(!orig);
 	AA_BUG(!new);
-	AA_BUG(!write_is_locked(&labels_set(orig)->lock));
+	lockdep_assert_held_exclusive(&labels_set(orig)->lock);
 
 	tmp = rcu_dereference_protected(orig->proxy->label,
 					&labels_ns(orig)->lock);
@@ -571,7 +571,7 @@  static bool __label_remove(struct aa_label *label, struct aa_label *new)
 
 	AA_BUG(!ls);
 	AA_BUG(!label);
-	AA_BUG(!write_is_locked(&ls->lock));
+	lockdep_assert_held_exclusive(&ls->lock);
 
 	if (new)
 		__aa_proxy_redirect(label, new);
@@ -608,7 +608,7 @@  static bool __label_replace(struct aa_label *old, struct aa_label *new)
 	AA_BUG(!ls);
 	AA_BUG(!old);
 	AA_BUG(!new);
-	AA_BUG(!write_is_locked(&ls->lock));
+	lockdep_assert_held_exclusive(&ls->lock);
 	AA_BUG(new->flags & FLAG_IN_TREE);
 
 	if (!label_is_stale(old))
@@ -645,7 +645,7 @@  static struct aa_label *__label_insert(struct aa_labelset *ls,
 	AA_BUG(!ls);
 	AA_BUG(!label);
 	AA_BUG(labels_set(label) != ls);
-	AA_BUG(!write_is_locked(&ls->lock));
+	lockdep_assert_held_exclusive(&ls->lock);
 	AA_BUG(label->flags & FLAG_IN_TREE);
 
 	/* Figure out where to put new node */