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: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250206175114.1974171-4-bvanassche@acm.org>
Date: Thu,  6 Feb 2025 09:50:44 -0800
From: Bart Van Assche <bvanassche@....org>
To: Peter Zijlstra <peterz@...radead.org>
Cc: Will Deacon <will@...nel.org>,
	Christoph Hellwig <hch@....de>,
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Marco Elver <elver@...gle.com>,
	Nick Desaulniers <ndesaulniers@...gle.com>,
	Nathan Chancellor <nathan@...nel.org>,
	Kees Cook <kees@...nel.org>,
	Jann Horn <jannh@...gle.com>,
	linux-kernel@...r.kernel.org,
	Bart Van Assche <bvanassche@....org>,
	Ingo Molnar <mingo@...hat.com>,
	Boqun Feng <boqun.feng@...il.com>,
	Waiman Long <longman@...hat.com>
Subject: [PATCH RFC 03/33] locking: Introduce <linux/thread_safety.h>

Introduce a new kernel header with the Clang thread-safety attributes.
If:
- a struct that represents a synchronization object is annotated with the
  CAPABILITY() attribute,
- the operations on that synchronization object are annotated with the
  ACQUIRE() and RELEASE() attributes,
- if variables or members that should be guarded by a synchronization
  object are annotated with GUARDED_BY(),

then the Clang compiler verifies the following if -Wthread-safety is
enabled:
- Whether or not locking in a function implementation matches the
  thread-safety attributes in the function declaration. No annotation
  is necessary if a lock call is followed by an unlock call. For other
  patterns, annotation is required.
- Whether or not the requirements of the GUARDED_BY() annotations are
  met.

Some highlights from the Clang thread-safety attribute documentation:
- Alias analysis is not performed on thread-safety attribute arguments.
  Hence the expansion of some local variables in subsequent patches.
- Most thread-safety attributes affect the function interface.
  NO_THREAD_SAFETY_ANALYSIS only affects the function definition.
- If a private struct definition (in a .c file) includes a
  synchronization object, annotations of functions in .h files must
  not refer to the name of the private struct. A possible solution is
  to define a capability with DEFINE_CAPABILITY and to use the name of
  that capability in the thread-safety annotations.

A few notes from me:
- Thread-safety attributes are not included in function pointer types.
  In other words, when passing an annotated function as an argument to
  another function, the thread-safety attributes are discarded.
- Annotating conditional locking functions that return a pointer is not
  yet supported by Clang.

More information is available here:
https://clang.llvm.org/docs/ThreadSafetyAnalysis.html

In case anyone would be interested, the equivalent Qemu header file is
available here:
https://github.com/qemu/qemu/blob/master/include/qemu/clang-tsa.h

Cc: Ingo Molnar <mingo@...hat.com>
Cc: Will Deacon <will@...nel.org>
Cc: Boqun Feng <boqun.feng@...il.com> (LOCKDEP & RUST)
Cc: Waiman Long <longman@...hat.com>
Signed-off-by: Bart Van Assche <bvanassche@....org>
---
 include/linux/thread_safety.h | 141 ++++++++++++++++++++++++++++++++++
 1 file changed, 141 insertions(+)
 create mode 100644 include/linux/thread_safety.h

diff --git a/include/linux/thread_safety.h b/include/linux/thread_safety.h
new file mode 100644
index 000000000000..e23175223a18
--- /dev/null
+++ b/include/linux/thread_safety.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _THREAD_SAFETY_H_
+#define _THREAD_SAFETY_H_
+
+/* See also https://clang.llvm.org/docs/ThreadSafetyAnalysis.html */
+
+/*
+ * Enable thread safety attributes only for clang. The attributes can be safely
+ * ignored when compiling with other compilers.
+ */
+#if defined(__clang__)
+#define THREAD_ANNOTATION_ATTRIBUTE_(...) __attribute__((__VA_ARGS__))
+#else
+#define THREAD_ANNOTATION_ATTRIBUTE_(...)
+#endif
+
+/*
+ * Macro for applying a capability as an attribute to a type definition.
+ * This macro can be used in struct definitions and also in typedefs.
+ * @x must be a string.
+ */
+#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(capability(x))
+
+/*
+ * Macro for defining a capability name that is not tied to an existing type.
+ * @capability_name is declared as an external variable. Any attempt to
+ * read or modify that external variable will result in a linker error.
+ */
+#define DEFINE_CAPABILITY(capability_name)	      \
+	extern const struct {} CAPABILITY(#capability_name) capability_name
+
+/*
+ * Attribute for structure members that declares that the structure members are
+ * protected by the given capability.
+ */
+#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE_(guarded_by(x))
+
+/*
+ * Attribute for pointer structure members that declares that the contents
+ * of these pointers are protected by the given capability.
+ */
+#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE_(pt_guarded_by(x))
+
+/*
+ * Attribute for instances of data structures that declares that the given
+ * capabilities must be acquired before the annotated data structure.
+ */
+#define ACQUIRED_BEFORE(...)					\
+	THREAD_ANNOTATION_ATTRIBUTE_(acquired_before(__VA_ARGS__))
+
+/*
+ * Attribute for instances of data structures that declares that the given
+ * capabilities must be acquired after the annotated data structure.
+ */
+#define ACQUIRED_AFTER(...)					\
+	THREAD_ANNOTATION_ATTRIBUTE_(acquired_after(__VA_ARGS__))
+
+/*
+ * Function attribute that declares that the caller must have exclusive access
+ * to the given capabilities.
+ */
+#define REQUIRES(...)							\
+	THREAD_ANNOTATION_ATTRIBUTE_(requires_capability(__VA_ARGS__))
+
+/*
+ * Function attribute that declares that the caller must have shared access
+ * to the given capabilities.
+ */
+#define REQUIRES_SHARED(...)						\
+	THREAD_ANNOTATION_ATTRIBUTE_(requires_shared_capability(__VA_ARGS__))
+
+/*
+ * Function attribute that declares that the function acquires the given
+ * capability.
+ */
+#define ACQUIRE(...)						\
+	THREAD_ANNOTATION_ATTRIBUTE_(acquire_capability(__VA_ARGS__))
+
+/*
+ * Function attribute that declares that the function acquires the given
+ * shared capability.
+ */
+#define ACQUIRE_SHARED(...)						\
+	THREAD_ANNOTATION_ATTRIBUTE_(acquire_shared_capability(__VA_ARGS__))
+
+/*
+ * Function attribute that declares that the function releases the given
+ * capability.
+ */
+#define RELEASE(...)						\
+	THREAD_ANNOTATION_ATTRIBUTE_(release_capability(__VA_ARGS__))
+
+/*
+ * Function attribute that declares that the function releases the given
+ * shared capability.
+ */
+#define RELEASE_SHARED(...)						\
+	THREAD_ANNOTATION_ATTRIBUTE_(release_shared_capability(__VA_ARGS__))
+
+/*
+ * Function attribute that declares that a function only acquires the given
+ * capability (2nd argument) for a given return value (first argument).
+ */
+#define TRY_ACQUIRE(...)						\
+	THREAD_ANNOTATION_ATTRIBUTE_(try_acquire_capability(__VA_ARGS__))
+
+/*
+ * Function attribute that declares that a function only acquires the given
+ * shared capability (2nd argument) for a given return value (first argument).
+ */
+#define TRY_ACQUIRE_SHARED(...)						\
+	THREAD_ANNOTATION_ATTRIBUTE_(try_acquire_shared_capability(__VA_ARGS__))
+
+/*
+ * Function attribute that declares that the caller must not hold the given
+ * capabilities.
+ */
+#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE_(locks_excluded(__VA_ARGS__))
+
+/*
+ * Tell the compiler that the given capability is held.
+ */
+#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(assert_capability(x))
+
+/*
+ * Tell the compiler that the given shared capability is held.
+ */
+#define ASSERT_SHARED_CAPABILITY(x)				\
+	THREAD_ANNOTATION_ATTRIBUTE_(assert_shared_capability(x))
+
+/*
+ * Function attribute that declares that a function returns a pointer to a
+ * capability.
+ */
+#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(lock_returned(x))
+
+/* Function attribute that disables thread-safety analysis. */
+#define NO_THREAD_SAFETY_ANALYSIS				\
+	THREAD_ANNOTATION_ATTRIBUTE_(no_thread_safety_analysis)
+
+#endif /* _THREAD_SAFETY_H_ */

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ