lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 24 Feb 2010 21:03:57 +0100
From:	Arnd Bergmann <arnd@...db.de>
To:	paulmck@...ux.vnet.ibm.com
Cc:	Mathieu Desnoyers <mathieu.desnoyers@...icios.com>,
	linux-kernel@...r.kernel.org, mingo@...e.hu, laijs@...fujitsu.com,
	dipankar@...ibm.com, akpm@...ux-foundation.org,
	josh@...htriplett.org, dvhltc@...ibm.com, niv@...ibm.com,
	tglx@...utronix.de, peterz@...radead.org, rostedt@...dmis.org,
	Valdis.Kletnieks@...edu, dhowells@...hat.com
Subject: [PATCH 01/10] rcu: define __rcu address space modifier for sparse

This is a first attempt to define an __rcu annotation
that lets sparse check for correct use of rcu_assign_pointer()
and rcu_dereference(). Pointers that are annotated __rcu
must be dereferenced using rcu_dereference or the new
__rcu_dereference and must be assigned using rcu_assign_pointer
or the new __rcu_assign_pointer.

The new macros are used in cases where not using the
regular accessors is proven to be correct.

Signed-off-by: Arnd Bergmann <arnd@...db.de>
---
 include/linux/compiler.h |    2 ++
 include/linux/rcupdate.h |   46 +++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 188fcae..6cc0857 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -10,6 +10,7 @@
 # define __force	__attribute__((force))
 # define __nocast	__attribute__((nocast))
 # define __iomem	__attribute__((noderef, address_space(2)))
+# define __rcu		__attribute__((noderef, address_space(3)))
 # define __acquires(x)	__attribute__((context(x,0,1)))
 # define __releases(x)	__attribute__((context(x,1,0)))
 # define __acquire(x)	__context__(x,1)
@@ -25,6 +26,7 @@ extern void __chk_io_ptr(const volatile void __iomem *);
 # define __force
 # define __nocast
 # define __iomem
+# define __rcu
 # define __chk_user_ptr(x) (void)0
 # define __chk_io_ptr(x) (void)0
 # define __builtin_warning(x, y...) (1)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 24440f4..644e28c 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -40,6 +40,7 @@
 #include <linux/seqlock.h>
 #include <linux/lockdep.h>
 #include <linux/completion.h>
+#include <linux/compiler.h>
 
 /**
  * struct rcu_head - callback structure for use with RCU
@@ -225,13 +226,31 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  *
  * Inserts memory barriers on architectures that require them
  * (currently only the Alpha), and, more importantly, documents
- * exactly which pointers are protected by RCU.
+ * exactly which pointers are protected by RCU and checks that
+ * the pointer is annotated as __rcu.
  */
-
 #define rcu_dereference(p)     ({ \
-				typeof(p) _________p1 = ACCESS_ONCE(p); \
+				typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
+				(void) (((typeof (*p) __rcu *)p) == p); \
 				smp_read_barrier_depends(); \
-				(_________p1); \
+				((typeof(*p) __force __kernel *)(_________p1)); \
+				})
+
+/**
+ * __rcu_dereference - fetch an __rcu pointer outside of a
+ * read-side critical section.
+ *
+ * __rcu_dereference does not contain any barrier but only
+ * converts a __rcu pointer to one that can be dereferenced.
+ * Use this for annotating code that operates on __rcu variables
+ * for checking with sparse in places where you can be sure
+ * that no writers exist, e.g. in a write-side critical section
+ * or in an RCU call.
+ */
+
+#define __rcu_dereference(p)     ({ \
+				(void) (((typeof (*p) __rcu *)p) == p); \
+				((typeof(*p) __force __kernel *)(p)); \
 				})
 
 /**
@@ -252,9 +271,26 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
 		if (!__builtin_constant_p(v) || \
 		    ((v) != NULL)) \
 			smp_wmb(); \
-		(p) = (v); \
+		(p) = (typeof(*v) __force __rcu *)(v); \
 	})
 
+/**
+ * __rcu_assign_pointer - assign a variable to an __rcu pointer
+ * without barriers.
+ * Using this is almost always a bug.
+ */
+#define __rcu_assign_pointer(p, v) \
+	({ \
+		(p) = (typeof(*v) __force __rcu *)(v); \
+	})
+
+/**
+ * RCU_INIT_POINTER - initialize an RCU protected member
+ * in a statically allocated data structure.
+ */
+#define RCU_INIT_POINTER(p, v) \
+		p = (typeof(*v) __force __rcu *)(v)
+
 /* Infrastructure to implement the synchronize_() primitives. */
 
 struct rcu_synchronize {
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ