From: Ian Rogers <irogers@google.com>
To: Marco Elver <elver@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>,
Boqun Feng <boqun.feng@gmail.com>,
Ingo Molnar <mingo@kernel.org>, Will Deacon <will@kernel.org>,
"David S. Miller" <davem@davemloft.net>,
Luc Van Oostenryck <luc.vanoostenryck@gmail.com>,
"Paul E. McKenney" <paulmck@kernel.org>,
Alexander Potapenko <glider@google.com>,
Arnd Bergmann <arnd@arndb.de>,
Bart Van Assche <bvanassche@acm.org>,
Bill Wendling <morbo@google.com>, Christoph Hellwig <hch@lst.de>,
Dmitry Vyukov <dvyukov@google.com>,
Eric Dumazet <edumazet@google.com>,
Frederic Weisbecker <frederic@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Herbert Xu <herbert@gondor.apana.org.au>,
Jann Horn <jannh@google.com>,
Joel Fernandes <joelagnelf@nvidia.com>,
Jonathan Corbet <corbet@lwn.net>,
Josh Triplett <josh@joshtriplett.org>,
Justin Stitt <justinstitt@google.com>,
Kees Cook <kees@kernel.org>,
Kentaro Takeda <takedakn@nttdata.co.jp>,
Lukas Bulwahn <lukas.bulwahn@gmail.com>,
Mark Rutland <mark.rutland@arm.com>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Miguel Ojeda <ojeda@kernel.org>,
Nathan Chancellor <nathan@kernel.org>,
Neeraj Upadhyay <neeraj.upadhyay@kernel.org>,
Nick Desaulniers <nick.desaulniers+lkml@gmail.com>,
Steven Rostedt <rostedt@goodmis.org>,
Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>,
Thomas Gleixner <tglx@linutronix.de>,
Thomas Graf <tgraf@suug.ch>, Uladzislau Rezki <urezki@gmail.com>,
Waiman Long <longman@redhat.com>,
kasan-dev@googlegroups.com, linux-crypto@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kbuild@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
linux-security-module@vger.kernel.org,
linux-sparse@vger.kernel.org, llvm@lists.linux.dev,
rcu@vger.kernel.org
Subject: Re: [PATCH v3 02/35] compiler-capability-analysis: Add infrastructure for Clang's capability analysis
Date: Thu, 18 Sep 2025 08:58:24 -0700 [thread overview]
Message-ID: <CAP-5=fUfbMAKrLC_z04o9r0kGZ02tpHfv8cOecQAQaYPx44awA@mail.gmail.com> (raw)
In-Reply-To: <20250918140451.1289454-3-elver@google.com>
On Thu, Sep 18, 2025 at 7:05 AM Marco Elver <elver@google.com> wrote:
>
> Capability analysis is a C language extension, which enables statically
> checking that user-definable "capabilities" are acquired and released where
> required. An obvious application is lock-safety checking for the kernel's
> various synchronization primitives (each of which represents a "capability"),
> and checking that locking rules are not violated.
>
> Clang originally called the feature "Thread Safety Analysis" [1], with
> some terminology still using the thread-safety-analysis-only names. This
> was later changed and the feature became more flexible, gaining the
> ability to define custom "capabilities". Its foundations can be found in
> "capability systems", used to specify the permissibility of operations
> to depend on some capability being held (or not held).
>
> [1] https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
> [2] https://www.cs.cornell.edu/talc/papers/capabilities.pdf
>
> Because the feature is not just able to express capabilities related to
> synchronization primitives, the naming chosen for the kernel departs
> from Clang's initial "Thread Safety" nomenclature and refers to the
> feature as "Capability Analysis" to avoid confusion. The implementation
> still makes references to the older terminology in some places, such as
> `-Wthread-safety` being the warning enabled option that also still
> appears in diagnostic messages.
>
> See more details in the kernel-doc documentation added in this and the
> subsequent changes.
>
> Clang version 22+ is required.
>
> Signed-off-by: Marco Elver <elver@google.com>
> ---
> v3:
> * Require Clang 22 or later (reentrant capabilities, basic alias analysis).
> * Rename __assert_cap/__asserts_cap -> __assume_cap/__assumes_cap (suggested by Peter).
> * Add __acquire_ret and __acquire_shared_ret helper macros - can be used
> to define function-like macros that return objects which contains a
> held capabilities. Works now because of capability alias analysis.
> * Add capability_unsafe_alias() helper, where the analysis rightfully
> points out we're doing strange things with aliases but we don't care.
> * Support multi-argument attributes.
>
> v2:
> * New -Wthread-safety feature rename to -Wthread-safety-pointer (was
> -Wthread-safety-addressof).
> * Introduce __capability_unsafe() function attribute.
> * Rename __var_guarded_by to simply __guarded_by. The initial idea was
> to be explicit if the variable or pointed-to data is guarded by, but
> having a shorter attribute name is likely better long-term.
> * Rename __ref_guarded_by to __pt_guarded_by (pointed-to guarded by).
> ---
> Makefile | 1 +
> include/linux/compiler-capability-analysis.h | 449 ++++++++++++++++++-
> lib/Kconfig.debug | 31 ++
> scripts/Makefile.capability-analysis | 7 +
> scripts/Makefile.lib | 10 +
> 5 files changed, 491 insertions(+), 7 deletions(-)
> create mode 100644 scripts/Makefile.capability-analysis
>
> diff --git a/Makefile b/Makefile
> index cf37b9407821..2c91730e513b 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1096,6 +1096,7 @@ include-$(CONFIG_RANDSTRUCT) += scripts/Makefile.randstruct
> include-$(CONFIG_KSTACK_ERASE) += scripts/Makefile.kstack_erase
> include-$(CONFIG_AUTOFDO_CLANG) += scripts/Makefile.autofdo
> include-$(CONFIG_PROPELLER_CLANG) += scripts/Makefile.propeller
> +include-$(CONFIG_WARN_CAPABILITY_ANALYSIS) += scripts/Makefile.capability-analysis
> include-$(CONFIG_GCC_PLUGINS) += scripts/Makefile.gcc-plugins
>
> include $(addprefix $(srctree)/, $(include-y))
> diff --git a/include/linux/compiler-capability-analysis.h b/include/linux/compiler-capability-analysis.h
> index 7546ddb83f86..6f3f185478bc 100644
> --- a/include/linux/compiler-capability-analysis.h
> +++ b/include/linux/compiler-capability-analysis.h
> @@ -6,27 +6,462 @@
> #ifndef _LINUX_COMPILER_CAPABILITY_ANALYSIS_H
> #define _LINUX_COMPILER_CAPABILITY_ANALYSIS_H
>
> +#if defined(WARN_CAPABILITY_ANALYSIS)
> +
> +/*
> + * The below attributes are used to define new capability types. Internal only.
> + */
> +# define __cap_type(name) __attribute__((capability(#name)))
> +# define __reentrant_cap __attribute__((reentrant_capability))
> +# define __acquires_cap(...) __attribute__((acquire_capability(__VA_ARGS__)))
> +# define __acquires_shared_cap(...) __attribute__((acquire_shared_capability(__VA_ARGS__)))
> +# define __try_acquires_cap(ret, var) __attribute__((try_acquire_capability(ret, var)))
> +# define __try_acquires_shared_cap(ret, var) __attribute__((try_acquire_shared_capability(ret, var)))
> +# define __releases_cap(...) __attribute__((release_capability(__VA_ARGS__)))
> +# define __releases_shared_cap(...) __attribute__((release_shared_capability(__VA_ARGS__)))
> +# define __assumes_cap(...) __attribute__((assert_capability(__VA_ARGS__)))
> +# define __assumes_shared_cap(...) __attribute__((assert_shared_capability(__VA_ARGS__)))
> +# define __returns_cap(var) __attribute__((lock_returned(var)))
> +
> +/*
> + * The below are used to annotate code being checked. Internal only.
> + */
> +# define __excludes_cap(...) __attribute__((locks_excluded(__VA_ARGS__)))
> +# define __requires_cap(...) __attribute__((requires_capability(__VA_ARGS__)))
> +# define __requires_shared_cap(...) __attribute__((requires_shared_capability(__VA_ARGS__)))
> +
> +/**
> + * __guarded_by - struct member and globals attribute, declares variable
> + * protected by capability
> + *
> + * Declares that the struct member or global variable must be guarded by the
> + * given capabilities. Read operations on the data require shared access,
> + * while write operations require exclusive access.
> + *
> + * .. code-block:: c
> + *
> + * struct some_state {
> + * spinlock_t lock;
> + * long counter __guarded_by(&lock);
> + * };
> + */
> +# define __guarded_by(...) __attribute__((guarded_by(__VA_ARGS__)))
> +
> +/**
> + * __pt_guarded_by - struct member and globals attribute, declares pointed-to
> + * data is protected by capability
> + *
> + * Declares that the data pointed to by the struct member pointer or global
> + * pointer must be guarded by the given capabilities. Read operations on the
> + * data require shared access, while write operations require exclusive access.
> + *
> + * .. code-block:: c
> + *
> + * struct some_state {
> + * spinlock_t lock;
> + * long *counter __pt_guarded_by(&lock);
> + * };
> + */
> +# define __pt_guarded_by(...) __attribute__((pt_guarded_by(__VA_ARGS__)))
> +
> +/**
> + * struct_with_capability() - declare or define a capability struct
> + * @name: struct name
> + *
> + * Helper to declare or define a struct type with capability of the same name.
> + *
> + * .. code-block:: c
> + *
> + * struct_with_capability(my_handle) {
> + * int foo;
> + * long bar;
> + * };
> + *
> + * struct some_state {
> + * ...
> + * };
> + * // ... declared elsewhere ...
> + * struct_with_capability(some_state);
> + *
> + * Note: The implementation defines several helper functions that can acquire,
> + * release, and assert the capability.
> + */
> +# define struct_with_capability(name, ...) \
> + struct __cap_type(name) __VA_ARGS__ name; \
> + static __always_inline void __acquire_cap(const struct name *var) \
> + __attribute__((overloadable)) __no_capability_analysis __acquires_cap(var) { } \
> + static __always_inline void __acquire_shared_cap(const struct name *var) \
> + __attribute__((overloadable)) __no_capability_analysis __acquires_shared_cap(var) { } \
> + static __always_inline bool __try_acquire_cap(const struct name *var, bool ret) \
> + __attribute__((overloadable)) __no_capability_analysis __try_acquires_cap(1, var) \
> + { return ret; } \
> + static __always_inline bool __try_acquire_shared_cap(const struct name *var, bool ret) \
> + __attribute__((overloadable)) __no_capability_analysis __try_acquires_shared_cap(1, var) \
> + { return ret; } \
> + static __always_inline void __release_cap(const struct name *var) \
> + __attribute__((overloadable)) __no_capability_analysis __releases_cap(var) { } \
> + static __always_inline void __release_shared_cap(const struct name *var) \
> + __attribute__((overloadable)) __no_capability_analysis __releases_shared_cap(var) { } \
> + static __always_inline void __assume_cap(const struct name *var) \
> + __attribute__((overloadable)) __assumes_cap(var) { } \
> + static __always_inline void __assume_shared_cap(const struct name *var) \
> + __attribute__((overloadable)) __assumes_shared_cap(var) { } \
> + struct name
> +
> +/**
> + * disable_capability_analysis() - disables capability analysis
> + *
> + * Disables capability analysis. Must be paired with a later
> + * enable_capability_analysis().
> + */
> +# define disable_capability_analysis() \
> + __diag_push(); \
> + __diag_ignore_all("-Wunknown-warning-option", "") \
> + __diag_ignore_all("-Wthread-safety", "") \
> + __diag_ignore_all("-Wthread-safety-pointer", "")
> +
> +/**
> + * enable_capability_analysis() - re-enables capability analysis
> + *
> + * Re-enables capability analysis. Must be paired with a prior
> + * disable_capability_analysis().
> + */
> +# define enable_capability_analysis() __diag_pop()
> +
> +/**
> + * __no_capability_analysis - function attribute, disables capability analysis
> + *
> + * Function attribute denoting that capability analysis is disabled for the
> + * whole function. Prefer use of `capability_unsafe()` where possible.
> + */
> +# define __no_capability_analysis __attribute__((no_thread_safety_analysis))
> +
> +#else /* !WARN_CAPABILITY_ANALYSIS */
> +
> +# define __cap_type(name)
> +# define __reentrant_cap
> +# define __acquires_cap(...)
> +# define __acquires_shared_cap(...)
> +# define __try_acquires_cap(ret, var)
> +# define __try_acquires_shared_cap(ret, var)
> +# define __releases_cap(...)
> +# define __releases_shared_cap(...)
> +# define __assumes_cap(...)
> +# define __assumes_shared_cap(...)
> +# define __returns_cap(var)
> +# define __guarded_by(...)
> +# define __pt_guarded_by(...)
> +# define __excludes_cap(...)
> +# define __requires_cap(...)
> +# define __requires_shared_cap(...)
> +# define __acquire_cap(var) do { } while (0)
> +# define __acquire_shared_cap(var) do { } while (0)
> +# define __try_acquire_cap(var, ret) (ret)
> +# define __try_acquire_shared_cap(var, ret) (ret)
> +# define __release_cap(var) do { } while (0)
> +# define __release_shared_cap(var) do { } while (0)
> +# define __assume_cap(var) do { (void)(var); } while (0)
> +# define __assume_shared_cap(var) do { (void)(var); } while (0)
> +# define struct_with_capability(name, ...) struct __VA_ARGS__ name
> +# define disable_capability_analysis()
> +# define enable_capability_analysis()
> +# define __no_capability_analysis
> +
> +#endif /* WARN_CAPABILITY_ANALYSIS */
> +
> +/**
> + * capability_unsafe() - disable capability checking for contained code
> + *
> + * Disables capability checking for contained statements or expression.
> + *
> + * .. code-block:: c
> + *
> + * struct some_data {
> + * spinlock_t lock;
> + * int counter __guarded_by(&lock);
> + * };
> + *
> + * int foo(struct some_data *d)
> + * {
> + * // ...
> + * // other code that is still checked ...
> + * // ...
> + * return capability_unsafe(d->counter);
> + * }
> + */
> +#define capability_unsafe(...) \
> +({ \
> + disable_capability_analysis(); \
> + __VA_ARGS__; \
> + enable_capability_analysis() \
> +})
> +
> +/**
> + * __capability_unsafe() - function attribute, disable capability checking
> + * @comment: comment explaining why opt-out is safe
> + *
> + * Function attribute denoting that capability analysis is disabled for the
> + * whole function. Forces adding an inline comment as argument.
> + */
> +#define __capability_unsafe(comment) __no_capability_analysis
> +
> +/**
> + * capability_unsafe_alias() - helper to insert a capability "alias barrier"
> + * @p: pointer aliasing a capability or object containing capabilities
> + *
> + * No-op function that acts as a "capability alias barrier", where the analysis
> + * rightfully detects that we're switching aliases, but the switch is considered
> + * safe but beyond the analysis reasoning abilities.
> + *
> + * This should be inserted before the first use of such an alias.
> + *
> + * Implementation Note: The compiler ignores aliases that may be reassigned but
> + * their value cannot be determined (e.g. when passing a non-const pointer to an
> + * alias as a function argument).
> + */
> +#define capability_unsafe_alias(p) _capability_unsafe_alias((void **)&(p))
> +static inline void _capability_unsafe_alias(void **p) { }
> +
> +/**
> + * token_capability() - declare an abstract global capability instance
> + * @name: token capability name
> + *
> + * Helper that declares an abstract global capability instance @name that can be
> + * used as a token capability, but not backed by a real data structure (linker
> + * error if accidentally referenced). The type name is `__capability_@name`.
> + */
> +#define token_capability(name, ...) \
> + struct_with_capability(__capability_##name, ##__VA_ARGS__) {}; \
> + extern const struct __capability_##name *name
> +
> +/**
> + * token_capability_instance() - declare another instance of a global capability
> + * @cap: token capability previously declared with token_capability()
> + * @name: name of additional global capability instance
> + *
> + * Helper that declares an additional instance @name of the same token
> + * capability class @name. This is helpful where multiple related token
> + * capabilities are declared, as it also allows using the same underlying type
> + * (`__capability_@cap`) as function arguments.
> + */
> +#define token_capability_instance(cap, name) \
> + extern const struct __capability_##cap *name
> +
> +/*
> + * Common keywords for static capability analysis. Both Clang's capability
> + * analysis and Sparse's context tracking are currently supported.
> + */
> #ifdef __CHECKER__
>
> /* Sparse context/lock checking support. */
> # define __must_hold(x) __attribute__((context(x,1,1)))
> +# define __must_not_hold(x)
> # define __acquires(x) __attribute__((context(x,0,1)))
> # define __cond_acquires(x) __attribute__((context(x,0,-1)))
> # define __releases(x) __attribute__((context(x,1,0)))
> # define __acquire(x) __context__(x,1)
> # define __release(x) __context__(x,-1)
> # define __cond_lock(x, c) ((c) ? ({ __acquire(x); 1; }) : 0)
> +/* For Sparse, there's no distinction between exclusive and shared locks. */
> +# define __must_hold_shared __must_hold
> +# define __acquires_shared __acquires
> +# define __cond_acquires_shared __cond_acquires
> +# define __releases_shared __releases
> +# define __acquire_shared __acquire
> +# define __release_shared __release
> +# define __cond_lock_shared __cond_acquire
>
> #else /* !__CHECKER__ */
>
> -# define __must_hold(x)
> -# define __acquires(x)
> -# define __cond_acquires(x)
> -# define __releases(x)
> -# define __acquire(x) (void)0
> -# define __release(x) (void)0
> -# define __cond_lock(x, c) (c)
> +/**
> + * __must_hold() - function attribute, caller must hold exclusive capability
> + * @x: capability instance pointer
> + *
> + * Function attribute declaring that the caller must hold the given capability
> + * instance @x exclusively.
> + */
> +# define __must_hold(x) __requires_cap(x)
> +
> +/**
> + * __must_not_hold() - function attribute, caller must not hold capability
> + * @x: capability instance pointer
> + *
> + * Function attribute declaring that the caller must not hold the given
> + * capability instance @x.
> + */
> +# define __must_not_hold(x) __excludes_cap(x)
> +
> +/**
> + * __acquires() - function attribute, function acquires capability exclusively
> + * @x: capability instance pointer
> + *
> + * Function attribute declaring that the function acquires the given
> + * capability instance @x exclusively, but does not release it.
> + */
> +# define __acquires(x) __acquires_cap(x)
> +
> +/**
> + * __cond_acquires() - function attribute, function conditionally
> + * acquires a capability exclusively
> + * @x: capability instance pointer
> + *
> + * Function attribute declaring that the function conditionally acquires the
> + * given capability instance @x exclusively, but does not release it.
> + */
> +# define __cond_acquires(x) __try_acquires_cap(1, x)
> +
> +/**
> + * __releases() - function attribute, function releases a capability exclusively
> + * @x: capability instance pointer
> + *
> + * Function attribute declaring that the function releases the given capability
> + * instance @x exclusively. The capability must be held on entry.
> + */
> +# define __releases(x) __releases_cap(x)
> +
> +/**
> + * __acquire() - function to acquire capability exclusively
> + * @x: capability instance pointer
> + *
> + * No-op function that acquires the given capability instance @x exclusively.
> + */
> +# define __acquire(x) __acquire_cap(x)
> +
> +/**
> + * __release() - function to release capability exclusively
> + * @x: capability instance pointer
> + *
> + * No-op function that releases the given capability instance @x.
> + */
> +# define __release(x) __release_cap(x)
> +
> +/**
> + * __cond_lock() - function that conditionally acquires a capability
> + * exclusively
> + * @x: capability instance pinter
> + * @c: boolean expression
> + *
> + * Return: result of @c
> + *
> + * No-op function that conditionally acquires capability instance @x
> + * exclusively, if the boolean expression @c is true. The result of @c is the
> + * return value, to be able to create a capability-enabled interface; for
> + * example:
> + *
> + * .. code-block:: c
> + *
> + * #define spin_trylock(l) __cond_lock(&lock, _spin_trylock(&lock))
> + */
> +# define __cond_lock(x, c) __try_acquire_cap(x, c)
> +
> +/**
> + * __must_hold_shared() - function attribute, caller must hold shared capability
> + * @x: capability instance pointer
> + *
> + * Function attribute declaring that the caller must hold the given capability
> + * instance @x with shared access.
> + */
> +# define __must_hold_shared(x) __requires_shared_cap(x)
> +
> +/**
> + * __acquires_shared() - function attribute, function acquires capability shared
> + * @x: capability instance pointer
> + *
> + * Function attribute declaring that the function acquires the given
> + * capability instance @x with shared access, but does not release it.
> + */
> +# define __acquires_shared(x) __acquires_shared_cap(x)
> +
> +/**
> + * __cond_acquires_shared() - function attribute, function conditionally
> + * acquires a capability shared
> + * @x: capability instance pointer
> + *
> + * Function attribute declaring that the function conditionally acquires the
> + * given capability instance @x with shared access, but does not release it.
> + */
> +# define __cond_acquires_shared(x) __try_acquires_shared_cap(1, x)
> +
> +/**
> + * __releases_shared() - function attribute, function releases a
> + * capability shared
> + * @x: capability instance pointer
> + *
> + * Function attribute declaring that the function releases the given capability
> + * instance @x with shared access. The capability must be held on entry.
> + */
> +# define __releases_shared(x) __releases_shared_cap(x)
> +
> +/**
> + * __acquire_shared() - function to acquire capability shared
> + * @x: capability instance pointer
> + *
> + * No-op function that acquires the given capability instance @x with shared
> + * access.
> + */
> +# define __acquire_shared(x) __acquire_shared_cap(x)
> +
> +/**
> + * __release_shared() - function to release capability shared
> + * @x: capability instance pointer
> + *
> + * No-op function that releases the given capability instance @x with shared
> + * access.
> + */
> +# define __release_shared(x) __release_shared_cap(x)
> +
> +/**
> + * __cond_lock_shared() - function that conditionally acquires a capability
> + * shared
> + * @x: capability instance pinter
> + * @c: boolean expression
> + *
> + * Return: result of @c
> + *
> + * No-op function that conditionally acquires capability instance @x with shared
> + * access, if the boolean expression @c is true. The result of @c is the return
> + * value, to be able to create a capability-enabled interface.
> + */
> +# define __cond_lock_shared(x, c) __try_acquire_shared_cap(x, c)
>
> #endif /* __CHECKER__ */
>
> +/**
> + * __acquire_ret() - helper to acquire capability of return value
> + * @call: call expression
> + * @ret_expr: acquire expression that uses __ret
> + */
> +#define __acquire_ret(call, ret_expr) \
> + ({ \
> + __auto_type __ret = call; \
> + __acquire(ret_expr); \
> + __ret; \
> + })
> +
> +/**
> + * __acquire_shared_ret() - helper to acquire capability shared of return value
> + * @call: call expression
> + * @ret_expr: acquire shared expression that uses __ret
> + */
> +#define __acquire_shared_ret(call, ret_expr) \
> + ({ \
> + __auto_type __ret = call; \
> + __acquire_shared(ret_expr); \
> + __ret; \
> + })
> +
> +/*
> + * Attributes to mark functions returning acquired capabilities. This is purely
> + * cosmetic to help readability, and should be used with the above macros as
> + * follows:
> + *
> + * struct foo { spinlock_t lock; ... };
> + * ...
> + * #define myfunc(...) __acquire_ret(_myfunc(__VA_ARGS__), &__ret->lock)
> + * struct foo *_myfunc(int bar) __acquires_ret;
> + * ...
> + */
> +#define __acquires_ret __no_capability_analysis
> +#define __acquires_shared_ret __no_capability_analysis
> +
> #endif /* _LINUX_COMPILER_CAPABILITY_ANALYSIS_H */
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index dc0e0c6ed075..57e09615f88d 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -613,6 +613,37 @@ config DEBUG_FORCE_WEAK_PER_CPU
> To ensure that generic code follows the above rules, this
> option forces all percpu variables to be defined as weak.
>
> +config WARN_CAPABILITY_ANALYSIS
> + bool "Compiler capability-analysis warnings"
> + depends on CC_IS_CLANG && CLANG_VERSION >= 220000
> + # Branch profiling re-defines "if", which messes with the compiler's
> + # ability to analyze __cond_acquires(..), resulting in false positives.
> + depends on !TRACE_BRANCH_PROFILING
Err, wow! What and huh, and why? Crikes. I'm amazed you found such an
option exists. I must be very naive to have never heard of it and now
I wonder if it is needed and load bearing?
Ian
> + default y
> + help
> + Capability analysis is a C language extension, which enables
> + statically checking that user-definable "capabilities" are acquired
> + and released where required.
> +
> + Clang's name of the feature ("Thread Safety Analysis") refers to
> + the original name of the feature; it was later expanded to be a
> + generic "Capability Analysis" framework.
> +
> + Requires Clang 22 or later.
> +
> + Produces warnings by default. Select CONFIG_WERROR if you wish to
> + turn these warnings into errors.
> +
> +config WARN_CAPABILITY_ANALYSIS_ALL
> + bool "Enable capability analysis for all source files"
> + depends on WARN_CAPABILITY_ANALYSIS
> + depends on EXPERT && !COMPILE_TEST
> + help
> + Enable tree-wide capability analysis. This is likely to produce a
> + large number of false positives - enable at your own risk.
> +
> + If unsure, say N.
> +
> endmenu # "Compiler options"
>
> menu "Generic Kernel Debugging Instruments"
> diff --git a/scripts/Makefile.capability-analysis b/scripts/Makefile.capability-analysis
> new file mode 100644
> index 000000000000..e137751a4c9a
> --- /dev/null
> +++ b/scripts/Makefile.capability-analysis
> @@ -0,0 +1,7 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +capability-analysis-cflags := -DWARN_CAPABILITY_ANALYSIS \
> + -fexperimental-late-parse-attributes -Wthread-safety \
> + -Wthread-safety-pointer -Wthread-safety-beta
> +
> +export CFLAGS_CAPABILITY_ANALYSIS := $(capability-analysis-cflags)
> diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
> index 1d581ba5df66..e0ac273bf9eb 100644
> --- a/scripts/Makefile.lib
> +++ b/scripts/Makefile.lib
> @@ -105,6 +105,16 @@ _c_flags += $(if $(patsubst n%,, \
> -D__KCSAN_INSTRUMENT_BARRIERS__)
> endif
>
> +#
> +# Enable capability analysis flags only where explicitly opted in.
> +# (depends on variables CAPABILITY_ANALYSIS_obj.o, CAPABILITY_ANALYSIS)
> +#
> +ifeq ($(CONFIG_WARN_CAPABILITY_ANALYSIS),y)
> +_c_flags += $(if $(patsubst n%,, \
> + $(CAPABILITY_ANALYSIS_$(target-stem).o)$(CAPABILITY_ANALYSIS)$(if $(is-kernel-object),$(CONFIG_WARN_CAPABILITY_ANALYSIS_ALL))), \
> + $(CFLAGS_CAPABILITY_ANALYSIS))
> +endif
> +
> #
> # Enable AutoFDO build flags except some files or directories we don't want to
> # enable (depends on variables AUTOFDO_PROFILE_obj.o and AUTOFDO_PROFILE).
> --
> 2.51.0.384.g4c02a37b29-goog
>
next prev parent reply other threads:[~2025-09-18 15:58 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-18 13:59 [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 01/35] compiler_types: Move lock checking attributes to compiler-capability-analysis.h Marco Elver
2025-09-18 13:59 ` [PATCH v3 02/35] compiler-capability-analysis: Add infrastructure for Clang's capability analysis Marco Elver
2025-09-18 15:58 ` Ian Rogers [this message]
2025-09-18 16:03 ` Bart Van Assche
2025-09-18 16:14 ` Steven Rostedt
2025-09-18 13:59 ` [PATCH v3 03/35] compiler-capability-analysis: Add test stub Marco Elver
2025-09-18 13:59 ` [PATCH v3 04/35] Documentation: Add documentation for Compiler-Based Capability Analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 05/35] checkpatch: Warn about capability_unsafe() without comment Marco Elver
2025-09-18 20:36 ` Joe Perches
2025-09-18 13:59 ` [PATCH v3 06/35] cleanup: Basic compatibility with capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 07/35] lockdep: Annotate lockdep assertions for " Marco Elver
2025-09-18 13:59 ` [PATCH v3 08/35] locking/rwlock, spinlock: Support Clang's " Marco Elver
2025-09-18 13:59 ` [PATCH v3 09/35] compiler-capability-analysis: Change __cond_acquires to take return value Marco Elver
2025-09-18 13:59 ` [PATCH v3 10/35] locking/mutex: Support Clang's capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 11/35] locking/seqlock: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 12/35] bit_spinlock: Include missing <asm/processor.h> Marco Elver
2025-09-18 13:59 ` [PATCH v3 13/35] bit_spinlock: Support Clang's capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 14/35] rcu: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 15/35] srcu: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 16/35] kref: Add capability-analysis annotations Marco Elver
2025-09-18 13:59 ` [PATCH v3 17/35] locking/rwsem: Support Clang's capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 18/35] locking/local_lock: Include missing headers Marco Elver
2025-09-18 13:59 ` [PATCH v3 19/35] locking/local_lock: Support Clang's capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 20/35] locking/ww_mutex: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 21/35] debugfs: Make debugfs_cancellation a capability struct Marco Elver
2025-09-18 13:59 ` [PATCH v3 22/35] compiler-capability-analysis: Remove Sparse support Marco Elver
2025-09-18 13:59 ` [PATCH v3 23/35] compiler-capability-analysis: Remove __cond_lock() function-like helper Marco Elver
2025-09-18 13:59 ` [PATCH v3 24/35] compiler-capability-analysis: Introduce header suppressions Marco Elver
2025-09-18 13:59 ` [PATCH v3 25/35] compiler: Let data_race() imply disabled capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 26/35] MAINTAINERS: Add entry for Capability Analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 27/35] kfence: Enable capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 28/35] kcov: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 29/35] kcsan: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 30/35] stackdepot: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 31/35] rhashtable: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 32/35] printk: Move locking annotation to printk.c Marco Elver
2025-09-18 13:59 ` [PATCH v3 33/35] security/tomoyo: Enable capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 34/35] crypto: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 35/35] sched: Enable capability analysis for core.c and fair.c Marco Elver
2025-09-18 14:15 ` [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis Christoph Hellwig
2025-09-18 14:30 ` Marco Elver
2025-09-18 14:38 ` Christoph Hellwig
2025-09-18 17:45 ` Nathan Chancellor
2025-09-18 19:40 ` Nathan Chancellor
2025-09-19 14:08 ` Christoph Hellwig
2025-09-19 14:09 ` Christoph Hellwig
2025-09-22 9:33 ` Marco Elver
2025-09-22 17:11 ` Christoph Hellwig
2025-09-23 19:49 ` Nathan Chancellor
2025-09-19 17:20 ` Bart Van Assche
2025-09-22 17:12 ` Christoph Hellwig
2025-09-20 10:23 ` Marco Elver
2025-09-20 12:44 ` Marco Elver
2025-09-18 15:49 ` Linus Torvalds
2025-09-18 21:26 ` Marco Elver
2025-09-18 21:47 ` Linus Torvalds
2025-09-19 9:10 ` Marco Elver
2025-11-13 14:30 ` Marco Elver
2025-11-14 4:38 ` Nathan Chancellor
2025-11-14 13:22 ` Marco Elver
2025-09-18 16:21 ` Ian Rogers
2025-09-18 19:41 ` [syzbot ci] " syzbot ci
2025-09-19 7:05 ` Marco Elver
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='CAP-5=fUfbMAKrLC_z04o9r0kGZ02tpHfv8cOecQAQaYPx44awA@mail.gmail.com' \
--to=irogers@google.com \
--cc=arnd@arndb.de \
--cc=boqun.feng@gmail.com \
--cc=bvanassche@acm.org \
--cc=corbet@lwn.net \
--cc=davem@davemloft.net \
--cc=dvyukov@google.com \
--cc=edumazet@google.com \
--cc=elver@google.com \
--cc=frederic@kernel.org \
--cc=glider@google.com \
--cc=gregkh@linuxfoundation.org \
--cc=hch@lst.de \
--cc=herbert@gondor.apana.org.au \
--cc=jannh@google.com \
--cc=joelagnelf@nvidia.com \
--cc=josh@joshtriplett.org \
--cc=justinstitt@google.com \
--cc=kasan-dev@googlegroups.com \
--cc=kees@kernel.org \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-security-module@vger.kernel.org \
--cc=linux-sparse@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=longman@redhat.com \
--cc=luc.vanoostenryck@gmail.com \
--cc=lukas.bulwahn@gmail.com \
--cc=mark.rutland@arm.com \
--cc=mathieu.desnoyers@efficios.com \
--cc=mingo@kernel.org \
--cc=morbo@google.com \
--cc=nathan@kernel.org \
--cc=neeraj.upadhyay@kernel.org \
--cc=nick.desaulniers+lkml@gmail.com \
--cc=ojeda@kernel.org \
--cc=paulmck@kernel.org \
--cc=penguin-kernel@i-love.sakura.ne.jp \
--cc=peterz@infradead.org \
--cc=rcu@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=takedakn@nttdata.co.jp \
--cc=tglx@linutronix.de \
--cc=tgraf@suug.ch \
--cc=urezki@gmail.com \
--cc=will@kernel.org \
/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