[PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis

Marco Elver posted 35 patches 1 week, 6 days ago
.../dev-tools/capability-analysis.rst         | 148 +++++
Documentation/dev-tools/index.rst             |   1 +
Documentation/dev-tools/sparse.rst            |  19 -
Documentation/mm/process_addrs.rst            |   6 +-
MAINTAINERS                                   |  11 +
Makefile                                      |   1 +
crypto/Makefile                               |   2 +
crypto/acompress.c                            |   6 +-
crypto/algapi.c                               |   2 +
crypto/api.c                                  |   1 +
crypto/crypto_engine.c                        |   2 +-
crypto/drbg.c                                 |   5 +
crypto/internal.h                             |   2 +-
crypto/proc.c                                 |   3 +
crypto/scompress.c                            |  24 +-
.../net/wireless/intel/iwlwifi/iwl-trans.c    |   4 +-
.../net/wireless/intel/iwlwifi/iwl-trans.h    |   6 +-
.../intel/iwlwifi/pcie/gen1_2/internal.h      |   5 +-
.../intel/iwlwifi/pcie/gen1_2/trans.c         |   4 +-
fs/dlm/lock.c                                 |   2 +-
include/crypto/internal/acompress.h           |   7 +-
include/crypto/internal/engine.h              |   2 +-
include/linux/bit_spinlock.h                  |  24 +-
include/linux/cleanup.h                       |  17 +
include/linux/compiler-capability-analysis.h  | 423 +++++++++++++
include/linux/compiler.h                      |   2 +
include/linux/compiler_types.h                |  18 +-
include/linux/console.h                       |   4 +-
include/linux/debugfs.h                       |  12 +-
include/linux/kref.h                          |   2 +
include/linux/list_bl.h                       |   2 +
include/linux/local_lock.h                    |  45 +-
include/linux/local_lock_internal.h           |  73 ++-
include/linux/lockdep.h                       |  12 +-
include/linux/mm.h                            |  33 +-
include/linux/mutex.h                         |  35 +-
include/linux/mutex_types.h                   |   4 +-
include/linux/rcupdate.h                      |  86 +--
include/linux/refcount.h                      |   6 +-
include/linux/rhashtable.h                    |  14 +-
include/linux/rwlock.h                        |  22 +-
include/linux/rwlock_api_smp.h                |  43 +-
include/linux/rwlock_rt.h                     |  44 +-
include/linux/rwlock_types.h                  |  10 +-
include/linux/rwsem.h                         |  66 +-
include/linux/sched.h                         |   6 +-
include/linux/sched/signal.h                  |  16 +-
include/linux/sched/task.h                    |   5 +-
include/linux/sched/wake_q.h                  |   3 +
include/linux/seqlock.h                       |  24 +
include/linux/seqlock_types.h                 |   5 +-
include/linux/spinlock.h                      |  89 ++-
include/linux/spinlock_api_smp.h              |  34 +-
include/linux/spinlock_api_up.h               | 112 +++-
include/linux/spinlock_rt.h                   |  37 +-
include/linux/spinlock_types.h                |  10 +-
include/linux/spinlock_types_raw.h            |   5 +-
include/linux/srcu.h                          |  60 +-
include/linux/srcutiny.h                      |   4 +
include/linux/srcutree.h                      |   6 +-
include/linux/ww_mutex.h                      |  22 +-
kernel/Makefile                               |   2 +
kernel/kcov.c                                 |  36 +-
kernel/kcsan/Makefile                         |   2 +
kernel/kcsan/report.c                         |  11 +-
kernel/printk/printk.c                        |   2 +
kernel/sched/Makefile                         |   3 +
kernel/sched/core.c                           |  89 ++-
kernel/sched/fair.c                           |   9 +-
kernel/sched/sched.h                          | 110 +++-
kernel/signal.c                               |   4 +-
kernel/time/posix-timers.c                    |  13 +-
lib/Kconfig.debug                             |  45 ++
lib/Makefile                                  |   6 +
lib/dec_and_lock.c                            |   8 +-
lib/rhashtable.c                              |   5 +-
lib/stackdepot.c                              |  20 +-
lib/test_capability-analysis.c                | 596 ++++++++++++++++++
mm/kfence/Makefile                            |   2 +
mm/kfence/core.c                              |  20 +-
mm/kfence/kfence.h                            |  14 +-
mm/kfence/report.c                            |   4 +-
mm/memory.c                                   |   4 +-
mm/pgtable-generic.c                          |  19 +-
net/ipv4/tcp_sigpool.c                        |   2 +-
scripts/Makefile.capability-analysis          |  11 +
scripts/Makefile.lib                          |  10 +
scripts/capability-analysis-suppression.txt   |  33 +
scripts/checkpatch.pl                         |   8 +
security/tomoyo/Makefile                      |   2 +
security/tomoyo/common.c                      |  52 +-
security/tomoyo/common.h                      |  77 +--
security/tomoyo/domain.c                      |   1 +
security/tomoyo/environ.c                     |   1 +
security/tomoyo/file.c                        |   5 +
security/tomoyo/gc.c                          |  28 +-
security/tomoyo/mount.c                       |   2 +
security/tomoyo/network.c                     |   3 +
tools/include/linux/compiler_types.h          |   2 -
99 files changed, 2370 insertions(+), 589 deletions(-)
create mode 100644 Documentation/dev-tools/capability-analysis.rst
create mode 100644 include/linux/compiler-capability-analysis.h
create mode 100644 lib/test_capability-analysis.c
create mode 100644 scripts/Makefile.capability-analysis
create mode 100644 scripts/capability-analysis-suppression.txt
[PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Marco Elver 1 week, 6 days ago
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" [2], used to specify the permissibility of
operations to depend on some capability being held (or not held).

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.

Enabling capability analysis can be seen as enabling a dialect of Linux
C with a Capability System.

Additional details can be found in the added kernel-doc documentation.
An LWN article covered v2 of the series: https://lwn.net/Articles/1012990/

 [1] https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
 [2] https://www.cs.cornell.edu/talc/papers/capabilities.pdf

=== Development Approach ===

Prior art exists in the form of Sparse's context tracking. Locking
annotations on functions exist, so the concept of analyzing locking rules
is not foreign to the kernel's codebase.

However, Clang's analysis is more complete vs. Sparse's, with the
typical trade-offs in static analysis: improved completeness is
sacrificed for more possible false positives or additional annotations
required by the programmer. Numerous options exist to disable or opt out
certain code from analysis.

This series initially aimed to retain compatibility with Sparse, which
can provide tree-wide analysis of a subset of the capability analysis
introduced, but it was later decided to drop Sparse compatibility. For
the most part, the new (and old) keywords used for annotations remain
the same, and many of the pre-existing annotations remain valid.

One big question is how to enable this feature, given we end up with a
new dialect of C -- 2 approaches have been considered:

  A. Tree-wide all-or-nothing approach. This approach requires tree-wide
     changes, adding annotations or selective opt-outs. Making additional
     primitives capability-enabled increases churn, esp. where maintainers
     are unaware of the feature's existence and how to use it.

Because we can't change the programming language (even if from one C
dialect to another) of the kernel overnight, a different approach might
cause less friction.

  B. A selective, incremental, and much less intrusive approach.
     Maintainers of subsystems opt in their modules or directories into
     "capability analysis" (via Makefile):
  
       CAPABILITY_ANALYSIS_foo.o := y	# foo.o only
       CAPABILITY_ANALYSIS := y  	# all TUs
  
     Most (eventually all) synchronization primitives and more
     capabilities (including ones that could track "irq disabled",
     "preemption" disabled, etc.) could be supported.

The approach taken by this series is B. This ensures that only
subsystems where maintainers are willing to deal with any warnings are
opted-in. Introducing the feature can be done incrementally, without
large tree-wide changes and adding numerous opt-outs and annotations to
the majority of code.

  Note: Bart Van Assche concurrently worked on enabling -Wthread-safety:
  https://lore.kernel.org/all/20250206175114.1974171-1-bvanassche@acm.org/
  Bart's work has shown what it might take to go with approach A
  (tree-wide, restricted to 'mutex' usage). This has shown that the
  analysis finds real issues when applied to enough subsystems!  We hope
  this serves as motivation to eventually enable the analysis in as many
  subsystems as possible, particularly subsystems that are not as easily
  tested by CI systems and test robots.

=== Initial Uses ===

With this initial series, the following synchronization primitives are
supported: `raw_spinlock_t`, `spinlock_t`, `rwlock_t`, `mutex`,
`seqlock_t`, `bit_spinlock`, RCU, SRCU (`srcu_struct`), `rw_semaphore`,
`local_lock_t`, `ww_mutex`.

To demonstrate use of the feature on real kernel code, the series also
enables capability analysis for the following subsystems:

	* kernel/kcov
	* kernel/kcsan
	* kernel/sched/
	* lib/rhashtable
	* lib/stackdepot
	* mm/kfence
	* security/tomoyo
    	* crypto/

The initial benefits are static detection of violations of locking
rules. As more capabilities are added, we would see more static checking
beyond what regular C can provide, all while remaining easy (read quick)
to use via the Clang compiler.

  Note: The kernel already provides dynamic analysis tools Lockdep and
  KCSAN for lock-safety checking and data-race detection respectively.
  Unlike those, Clang's capability analysis is a compile-time static
  analysis with no runtime impact. The static analysis complements
  existing dynamic analysis tools, as it may catch some issues before
  even getting into a running kernel, but is *not* a replacement for
  whole-kernel testing with the dynamic analysis tools enabled!

=== Appendix ===

A Clang version that supports `-Wthread-safety-pointer` and the new
alias-analysis of capability pointers is required (from this version
onwards):

	https://github.com/llvm/llvm-project/commit/b4c98fcbe1504841203e610c351a3227f36c92a4 [3]

This series is also available at this Git tree:

	https://git.kernel.org/pub/scm/linux/kernel/git/melver/linux.git/log/?h=cap-analysis/dev

=== Changelog ===

v3:

  - Bump min. Clang version to 22+ (unreleased), which now supports:

	* re-entrancy via __attribute__((reentrant_capability));
	* basic form of capability alias analysis [3] - which is the
	  biggest improvement since v2.

    This was the result of conclusions from this discussion:
    https://lore.kernel.org/all/CANpmjNPquO=W1JAh1FNQb8pMQjgeZAKCPQUAd7qUg=5pjJ6x=Q@mail.gmail.com/

  - Rename __asserts_cap/__assert_cap to __assumes_cap/__assume_cap.

  - Switch to DECLARE_LOCK_GUARD_1_ATTRS().

  - 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.

  - Enable for kernel/sched/{core,fair}.c, kernel/kcsan.
  - Drop drivers/tty changes (revisit later).

v2: https://lore.kernel.org/all/20250304092417.2873893-1-elver@google.com/

  - Remove Sparse context tracking support - after the introduction of
    Clang support, so that backports can skip removal of Sparse support.

  - Remove __cond_lock() function-like helper.

  - ww_mutex support.

  - -Wthread-safety-addressof was reworked and committed in upstream
    Clang as -Wthread-safety-pointer.

  - Make __cond_acquires() and __cond_acquires_shared() take abstract
    value, since compiler only cares about zero and non-zero.

  - Rename __var_guarded_by to simply __guarded_by. Initially the idea
    was to be explicit about if the variable itself or the pointed-to
    data is guarded, but in the long-term, making this shorter might be
    better.

  - Likewise rename __ref_guarded_by to __pt_guarded_by.

  - Introduce common header warning suppressions - this is a better
    solution than guarding header inclusions with disable_ +
    enable_capability_analysis(). Header suppressions are disabled when
    selecting CONFIG_WARN_CAPABILITY_ANALYSIS_ALL=y. This bumps the
    minimum Clang version required to 20+.

  - Make the data_race() macro imply disabled capability analysis.
    Writing capability_unsafe(data_race(..)) is unnecessarily verbose
    and data_race() on its own already indicates something subtly unsafe
    is happening.  This change was made after analysis of a finding in
    security/tomoyo.

  - Enable analysis in the following subsystems as additional examples
    of larger subsystem. Where it was obvious, the __guarded_by
    attribute was added to lock-guarded variables to improve coverage.

    	* drivers/tty
	* security/tomoyo
    	* crypto/

RFC v1: https://lore.kernel.org/lkml/20250206181711.1902989-1-elver@google.com

Marco Elver (35):
  compiler_types: Move lock checking attributes to
    compiler-capability-analysis.h
  compiler-capability-analysis: Add infrastructure for Clang's
    capability analysis
  compiler-capability-analysis: Add test stub
  Documentation: Add documentation for Compiler-Based Capability
    Analysis
  checkpatch: Warn about capability_unsafe() without comment
  cleanup: Basic compatibility with capability analysis
  lockdep: Annotate lockdep assertions for capability analysis
  locking/rwlock, spinlock: Support Clang's capability analysis
  compiler-capability-analysis: Change __cond_acquires to take return
    value
  locking/mutex: Support Clang's capability analysis
  locking/seqlock: Support Clang's capability analysis
  bit_spinlock: Include missing <asm/processor.h>
  bit_spinlock: Support Clang's capability analysis
  rcu: Support Clang's capability analysis
  srcu: Support Clang's capability analysis
  kref: Add capability-analysis annotations
  locking/rwsem: Support Clang's capability analysis
  locking/local_lock: Include missing headers
  locking/local_lock: Support Clang's capability analysis
  locking/ww_mutex: Support Clang's capability analysis
  debugfs: Make debugfs_cancellation a capability struct
  compiler-capability-analysis: Remove Sparse support
  compiler-capability-analysis: Remove __cond_lock() function-like
    helper
  compiler-capability-analysis: Introduce header suppressions
  compiler: Let data_race() imply disabled capability analysis
  MAINTAINERS: Add entry for Capability Analysis
  kfence: Enable capability analysis
  kcov: Enable capability analysis
  kcsan: Enable capability analysis
  stackdepot: Enable capability analysis
  rhashtable: Enable capability analysis
  printk: Move locking annotation to printk.c
  security/tomoyo: Enable capability analysis
  crypto: Enable capability analysis
  sched: Enable capability analysis for core.c and fair.c

 .../dev-tools/capability-analysis.rst         | 148 +++++
 Documentation/dev-tools/index.rst             |   1 +
 Documentation/dev-tools/sparse.rst            |  19 -
 Documentation/mm/process_addrs.rst            |   6 +-
 MAINTAINERS                                   |  11 +
 Makefile                                      |   1 +
 crypto/Makefile                               |   2 +
 crypto/acompress.c                            |   6 +-
 crypto/algapi.c                               |   2 +
 crypto/api.c                                  |   1 +
 crypto/crypto_engine.c                        |   2 +-
 crypto/drbg.c                                 |   5 +
 crypto/internal.h                             |   2 +-
 crypto/proc.c                                 |   3 +
 crypto/scompress.c                            |  24 +-
 .../net/wireless/intel/iwlwifi/iwl-trans.c    |   4 +-
 .../net/wireless/intel/iwlwifi/iwl-trans.h    |   6 +-
 .../intel/iwlwifi/pcie/gen1_2/internal.h      |   5 +-
 .../intel/iwlwifi/pcie/gen1_2/trans.c         |   4 +-
 fs/dlm/lock.c                                 |   2 +-
 include/crypto/internal/acompress.h           |   7 +-
 include/crypto/internal/engine.h              |   2 +-
 include/linux/bit_spinlock.h                  |  24 +-
 include/linux/cleanup.h                       |  17 +
 include/linux/compiler-capability-analysis.h  | 423 +++++++++++++
 include/linux/compiler.h                      |   2 +
 include/linux/compiler_types.h                |  18 +-
 include/linux/console.h                       |   4 +-
 include/linux/debugfs.h                       |  12 +-
 include/linux/kref.h                          |   2 +
 include/linux/list_bl.h                       |   2 +
 include/linux/local_lock.h                    |  45 +-
 include/linux/local_lock_internal.h           |  73 ++-
 include/linux/lockdep.h                       |  12 +-
 include/linux/mm.h                            |  33 +-
 include/linux/mutex.h                         |  35 +-
 include/linux/mutex_types.h                   |   4 +-
 include/linux/rcupdate.h                      |  86 +--
 include/linux/refcount.h                      |   6 +-
 include/linux/rhashtable.h                    |  14 +-
 include/linux/rwlock.h                        |  22 +-
 include/linux/rwlock_api_smp.h                |  43 +-
 include/linux/rwlock_rt.h                     |  44 +-
 include/linux/rwlock_types.h                  |  10 +-
 include/linux/rwsem.h                         |  66 +-
 include/linux/sched.h                         |   6 +-
 include/linux/sched/signal.h                  |  16 +-
 include/linux/sched/task.h                    |   5 +-
 include/linux/sched/wake_q.h                  |   3 +
 include/linux/seqlock.h                       |  24 +
 include/linux/seqlock_types.h                 |   5 +-
 include/linux/spinlock.h                      |  89 ++-
 include/linux/spinlock_api_smp.h              |  34 +-
 include/linux/spinlock_api_up.h               | 112 +++-
 include/linux/spinlock_rt.h                   |  37 +-
 include/linux/spinlock_types.h                |  10 +-
 include/linux/spinlock_types_raw.h            |   5 +-
 include/linux/srcu.h                          |  60 +-
 include/linux/srcutiny.h                      |   4 +
 include/linux/srcutree.h                      |   6 +-
 include/linux/ww_mutex.h                      |  22 +-
 kernel/Makefile                               |   2 +
 kernel/kcov.c                                 |  36 +-
 kernel/kcsan/Makefile                         |   2 +
 kernel/kcsan/report.c                         |  11 +-
 kernel/printk/printk.c                        |   2 +
 kernel/sched/Makefile                         |   3 +
 kernel/sched/core.c                           |  89 ++-
 kernel/sched/fair.c                           |   9 +-
 kernel/sched/sched.h                          | 110 +++-
 kernel/signal.c                               |   4 +-
 kernel/time/posix-timers.c                    |  13 +-
 lib/Kconfig.debug                             |  45 ++
 lib/Makefile                                  |   6 +
 lib/dec_and_lock.c                            |   8 +-
 lib/rhashtable.c                              |   5 +-
 lib/stackdepot.c                              |  20 +-
 lib/test_capability-analysis.c                | 596 ++++++++++++++++++
 mm/kfence/Makefile                            |   2 +
 mm/kfence/core.c                              |  20 +-
 mm/kfence/kfence.h                            |  14 +-
 mm/kfence/report.c                            |   4 +-
 mm/memory.c                                   |   4 +-
 mm/pgtable-generic.c                          |  19 +-
 net/ipv4/tcp_sigpool.c                        |   2 +-
 scripts/Makefile.capability-analysis          |  11 +
 scripts/Makefile.lib                          |  10 +
 scripts/capability-analysis-suppression.txt   |  33 +
 scripts/checkpatch.pl                         |   8 +
 security/tomoyo/Makefile                      |   2 +
 security/tomoyo/common.c                      |  52 +-
 security/tomoyo/common.h                      |  77 +--
 security/tomoyo/domain.c                      |   1 +
 security/tomoyo/environ.c                     |   1 +
 security/tomoyo/file.c                        |   5 +
 security/tomoyo/gc.c                          |  28 +-
 security/tomoyo/mount.c                       |   2 +
 security/tomoyo/network.c                     |   3 +
 tools/include/linux/compiler_types.h          |   2 -
 99 files changed, 2370 insertions(+), 589 deletions(-)
 create mode 100644 Documentation/dev-tools/capability-analysis.rst
 create mode 100644 include/linux/compiler-capability-analysis.h
 create mode 100644 lib/test_capability-analysis.c
 create mode 100644 scripts/Makefile.capability-analysis
 create mode 100644 scripts/capability-analysis-suppression.txt

-- 
2.51.0.384.g4c02a37b29-goog
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Ian Rogers 1 week, 6 days ago
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" [2], used to specify the permissibility of
> operations to depend on some capability being held (or not held).
>
> 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.
>
> Enabling capability analysis can be seen as enabling a dialect of Linux
> C with a Capability System.
>
> Additional details can be found in the added kernel-doc documentation.
> An LWN article covered v2 of the series: https://lwn.net/Articles/1012990/
>
>  [1] https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
>  [2] https://www.cs.cornell.edu/talc/papers/capabilities.pdf
>
> === Development Approach ===
>
> Prior art exists in the form of Sparse's context tracking. Locking
> annotations on functions exist, so the concept of analyzing locking rules
> is not foreign to the kernel's codebase.
>
> However, Clang's analysis is more complete vs. Sparse's, with the
> typical trade-offs in static analysis: improved completeness is
> sacrificed for more possible false positives or additional annotations
> required by the programmer. Numerous options exist to disable or opt out
> certain code from analysis.
>
> This series initially aimed to retain compatibility with Sparse, which
> can provide tree-wide analysis of a subset of the capability analysis
> introduced, but it was later decided to drop Sparse compatibility. For
> the most part, the new (and old) keywords used for annotations remain
> the same, and many of the pre-existing annotations remain valid.
>
> One big question is how to enable this feature, given we end up with a
> new dialect of C -- 2 approaches have been considered:
>
>   A. Tree-wide all-or-nothing approach. This approach requires tree-wide
>      changes, adding annotations or selective opt-outs. Making additional
>      primitives capability-enabled increases churn, esp. where maintainers
>      are unaware of the feature's existence and how to use it.
>
> Because we can't change the programming language (even if from one C
> dialect to another) of the kernel overnight, a different approach might
> cause less friction.
>
>   B. A selective, incremental, and much less intrusive approach.
>      Maintainers of subsystems opt in their modules or directories into
>      "capability analysis" (via Makefile):
>
>        CAPABILITY_ANALYSIS_foo.o := y   # foo.o only
>        CAPABILITY_ANALYSIS := y         # all TUs
>
>      Most (eventually all) synchronization primitives and more
>      capabilities (including ones that could track "irq disabled",
>      "preemption" disabled, etc.) could be supported.
>
> The approach taken by this series is B. This ensures that only
> subsystems where maintainers are willing to deal with any warnings are
> opted-in. Introducing the feature can be done incrementally, without
> large tree-wide changes and adding numerous opt-outs and annotations to
> the majority of code.
>
>   Note: Bart Van Assche concurrently worked on enabling -Wthread-safety:
>   https://lore.kernel.org/all/20250206175114.1974171-1-bvanassche@acm.org/
>   Bart's work has shown what it might take to go with approach A
>   (tree-wide, restricted to 'mutex' usage). This has shown that the
>   analysis finds real issues when applied to enough subsystems!  We hope
>   this serves as motivation to eventually enable the analysis in as many
>   subsystems as possible, particularly subsystems that are not as easily
>   tested by CI systems and test robots.
>
> === Initial Uses ===
>
> With this initial series, the following synchronization primitives are
> supported: `raw_spinlock_t`, `spinlock_t`, `rwlock_t`, `mutex`,
> `seqlock_t`, `bit_spinlock`, RCU, SRCU (`srcu_struct`), `rw_semaphore`,
> `local_lock_t`, `ww_mutex`.
>
> To demonstrate use of the feature on real kernel code, the series also
> enables capability analysis for the following subsystems:
>
>         * kernel/kcov
>         * kernel/kcsan
>         * kernel/sched/
>         * lib/rhashtable
>         * lib/stackdepot
>         * mm/kfence
>         * security/tomoyo
>         * crypto/
>
> The initial benefits are static detection of violations of locking
> rules. As more capabilities are added, we would see more static checking
> beyond what regular C can provide, all while remaining easy (read quick)
> to use via the Clang compiler.
>
>   Note: The kernel already provides dynamic analysis tools Lockdep and
>   KCSAN for lock-safety checking and data-race detection respectively.
>   Unlike those, Clang's capability analysis is a compile-time static
>   analysis with no runtime impact. The static analysis complements
>   existing dynamic analysis tools, as it may catch some issues before
>   even getting into a running kernel, but is *not* a replacement for
>   whole-kernel testing with the dynamic analysis tools enabled!
>
> === Appendix ===
>
> A Clang version that supports `-Wthread-safety-pointer` and the new
> alias-analysis of capability pointers is required (from this version
> onwards):
>
>         https://github.com/llvm/llvm-project/commit/b4c98fcbe1504841203e610c351a3227f36c92a4 [3]
>
> This series is also available at this Git tree:
>
>         https://git.kernel.org/pub/scm/linux/kernel/git/melver/linux.git/log/?h=cap-analysis/dev
>
> === Changelog ===
>
> v3:
>
>   - Bump min. Clang version to 22+ (unreleased), which now supports:
>
>         * re-entrancy via __attribute__((reentrant_capability));
>         * basic form of capability alias analysis [3] - which is the
>           biggest improvement since v2.
>
>     This was the result of conclusions from this discussion:
>     https://lore.kernel.org/all/CANpmjNPquO=W1JAh1FNQb8pMQjgeZAKCPQUAd7qUg=5pjJ6x=Q@mail.gmail.com/
>
>   - Rename __asserts_cap/__assert_cap to __assumes_cap/__assume_cap.
>
>   - Switch to DECLARE_LOCK_GUARD_1_ATTRS().
>
>   - 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.
>
>   - Enable for kernel/sched/{core,fair}.c, kernel/kcsan.
>   - Drop drivers/tty changes (revisit later).
>
> v2: https://lore.kernel.org/all/20250304092417.2873893-1-elver@google.com/
>
>   - Remove Sparse context tracking support - after the introduction of
>     Clang support, so that backports can skip removal of Sparse support.
>
>   - Remove __cond_lock() function-like helper.
>
>   - ww_mutex support.
>
>   - -Wthread-safety-addressof was reworked and committed in upstream
>     Clang as -Wthread-safety-pointer.
>
>   - Make __cond_acquires() and __cond_acquires_shared() take abstract
>     value, since compiler only cares about zero and non-zero.
>
>   - Rename __var_guarded_by to simply __guarded_by. Initially the idea
>     was to be explicit about if the variable itself or the pointed-to
>     data is guarded, but in the long-term, making this shorter might be
>     better.
>
>   - Likewise rename __ref_guarded_by to __pt_guarded_by.
>
>   - Introduce common header warning suppressions - this is a better
>     solution than guarding header inclusions with disable_ +
>     enable_capability_analysis(). Header suppressions are disabled when
>     selecting CONFIG_WARN_CAPABILITY_ANALYSIS_ALL=y. This bumps the
>     minimum Clang version required to 20+.
>
>   - Make the data_race() macro imply disabled capability analysis.
>     Writing capability_unsafe(data_race(..)) is unnecessarily verbose
>     and data_race() on its own already indicates something subtly unsafe
>     is happening.  This change was made after analysis of a finding in
>     security/tomoyo.
>
>   - Enable analysis in the following subsystems as additional examples
>     of larger subsystem. Where it was obvious, the __guarded_by
>     attribute was added to lock-guarded variables to improve coverage.
>
>         * drivers/tty
>         * security/tomoyo
>         * crypto/
>
> RFC v1: https://lore.kernel.org/lkml/20250206181711.1902989-1-elver@google.com

Thanks for this and lgtm. Fwiw, there is already thread safety
analysis in tools/perf:
https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/mutex.h?h=perf-tools-next#n43
and we should migrate that code to use this code.

Something that I've wondered about capabilities is to use them for
detecting missing reference count "puts", which feel similar to missed
unlocks. In my experience the sanitizers are weak in this area as in
C++ you can trivially use RAII, however, frustratingly clang's
capability analysis is disabled in C++'s constructors and destructors
(not an issue here :-) and based on my rusty memory). To solve this
for perf (and fix many many bugs) we did a form of runtime RAII:
https://perfwiki.github.io/main/reference-count-checking/
There is likely something better than can be done with the nearly RAII
that is/are cleanups. Trying to make that sane for a data-structure
like an rbtree is hard and maybe rust is just the only solution there.
Anyway, it is great to see thread safety analysis pushed forward.

Thanks,
Ian

> Marco Elver (35):
>   compiler_types: Move lock checking attributes to
>     compiler-capability-analysis.h
>   compiler-capability-analysis: Add infrastructure for Clang's
>     capability analysis
>   compiler-capability-analysis: Add test stub
>   Documentation: Add documentation for Compiler-Based Capability
>     Analysis
>   checkpatch: Warn about capability_unsafe() without comment
>   cleanup: Basic compatibility with capability analysis
>   lockdep: Annotate lockdep assertions for capability analysis
>   locking/rwlock, spinlock: Support Clang's capability analysis
>   compiler-capability-analysis: Change __cond_acquires to take return
>     value
>   locking/mutex: Support Clang's capability analysis
>   locking/seqlock: Support Clang's capability analysis
>   bit_spinlock: Include missing <asm/processor.h>
>   bit_spinlock: Support Clang's capability analysis
>   rcu: Support Clang's capability analysis
>   srcu: Support Clang's capability analysis
>   kref: Add capability-analysis annotations
>   locking/rwsem: Support Clang's capability analysis
>   locking/local_lock: Include missing headers
>   locking/local_lock: Support Clang's capability analysis
>   locking/ww_mutex: Support Clang's capability analysis
>   debugfs: Make debugfs_cancellation a capability struct
>   compiler-capability-analysis: Remove Sparse support
>   compiler-capability-analysis: Remove __cond_lock() function-like
>     helper
>   compiler-capability-analysis: Introduce header suppressions
>   compiler: Let data_race() imply disabled capability analysis
>   MAINTAINERS: Add entry for Capability Analysis
>   kfence: Enable capability analysis
>   kcov: Enable capability analysis
>   kcsan: Enable capability analysis
>   stackdepot: Enable capability analysis
>   rhashtable: Enable capability analysis
>   printk: Move locking annotation to printk.c
>   security/tomoyo: Enable capability analysis
>   crypto: Enable capability analysis
>   sched: Enable capability analysis for core.c and fair.c
>
>  .../dev-tools/capability-analysis.rst         | 148 +++++
>  Documentation/dev-tools/index.rst             |   1 +
>  Documentation/dev-tools/sparse.rst            |  19 -
>  Documentation/mm/process_addrs.rst            |   6 +-
>  MAINTAINERS                                   |  11 +
>  Makefile                                      |   1 +
>  crypto/Makefile                               |   2 +
>  crypto/acompress.c                            |   6 +-
>  crypto/algapi.c                               |   2 +
>  crypto/api.c                                  |   1 +
>  crypto/crypto_engine.c                        |   2 +-
>  crypto/drbg.c                                 |   5 +
>  crypto/internal.h                             |   2 +-
>  crypto/proc.c                                 |   3 +
>  crypto/scompress.c                            |  24 +-
>  .../net/wireless/intel/iwlwifi/iwl-trans.c    |   4 +-
>  .../net/wireless/intel/iwlwifi/iwl-trans.h    |   6 +-
>  .../intel/iwlwifi/pcie/gen1_2/internal.h      |   5 +-
>  .../intel/iwlwifi/pcie/gen1_2/trans.c         |   4 +-
>  fs/dlm/lock.c                                 |   2 +-
>  include/crypto/internal/acompress.h           |   7 +-
>  include/crypto/internal/engine.h              |   2 +-
>  include/linux/bit_spinlock.h                  |  24 +-
>  include/linux/cleanup.h                       |  17 +
>  include/linux/compiler-capability-analysis.h  | 423 +++++++++++++
>  include/linux/compiler.h                      |   2 +
>  include/linux/compiler_types.h                |  18 +-
>  include/linux/console.h                       |   4 +-
>  include/linux/debugfs.h                       |  12 +-
>  include/linux/kref.h                          |   2 +
>  include/linux/list_bl.h                       |   2 +
>  include/linux/local_lock.h                    |  45 +-
>  include/linux/local_lock_internal.h           |  73 ++-
>  include/linux/lockdep.h                       |  12 +-
>  include/linux/mm.h                            |  33 +-
>  include/linux/mutex.h                         |  35 +-
>  include/linux/mutex_types.h                   |   4 +-
>  include/linux/rcupdate.h                      |  86 +--
>  include/linux/refcount.h                      |   6 +-
>  include/linux/rhashtable.h                    |  14 +-
>  include/linux/rwlock.h                        |  22 +-
>  include/linux/rwlock_api_smp.h                |  43 +-
>  include/linux/rwlock_rt.h                     |  44 +-
>  include/linux/rwlock_types.h                  |  10 +-
>  include/linux/rwsem.h                         |  66 +-
>  include/linux/sched.h                         |   6 +-
>  include/linux/sched/signal.h                  |  16 +-
>  include/linux/sched/task.h                    |   5 +-
>  include/linux/sched/wake_q.h                  |   3 +
>  include/linux/seqlock.h                       |  24 +
>  include/linux/seqlock_types.h                 |   5 +-
>  include/linux/spinlock.h                      |  89 ++-
>  include/linux/spinlock_api_smp.h              |  34 +-
>  include/linux/spinlock_api_up.h               | 112 +++-
>  include/linux/spinlock_rt.h                   |  37 +-
>  include/linux/spinlock_types.h                |  10 +-
>  include/linux/spinlock_types_raw.h            |   5 +-
>  include/linux/srcu.h                          |  60 +-
>  include/linux/srcutiny.h                      |   4 +
>  include/linux/srcutree.h                      |   6 +-
>  include/linux/ww_mutex.h                      |  22 +-
>  kernel/Makefile                               |   2 +
>  kernel/kcov.c                                 |  36 +-
>  kernel/kcsan/Makefile                         |   2 +
>  kernel/kcsan/report.c                         |  11 +-
>  kernel/printk/printk.c                        |   2 +
>  kernel/sched/Makefile                         |   3 +
>  kernel/sched/core.c                           |  89 ++-
>  kernel/sched/fair.c                           |   9 +-
>  kernel/sched/sched.h                          | 110 +++-
>  kernel/signal.c                               |   4 +-
>  kernel/time/posix-timers.c                    |  13 +-
>  lib/Kconfig.debug                             |  45 ++
>  lib/Makefile                                  |   6 +
>  lib/dec_and_lock.c                            |   8 +-
>  lib/rhashtable.c                              |   5 +-
>  lib/stackdepot.c                              |  20 +-
>  lib/test_capability-analysis.c                | 596 ++++++++++++++++++
>  mm/kfence/Makefile                            |   2 +
>  mm/kfence/core.c                              |  20 +-
>  mm/kfence/kfence.h                            |  14 +-
>  mm/kfence/report.c                            |   4 +-
>  mm/memory.c                                   |   4 +-
>  mm/pgtable-generic.c                          |  19 +-
>  net/ipv4/tcp_sigpool.c                        |   2 +-
>  scripts/Makefile.capability-analysis          |  11 +
>  scripts/Makefile.lib                          |  10 +
>  scripts/capability-analysis-suppression.txt   |  33 +
>  scripts/checkpatch.pl                         |   8 +
>  security/tomoyo/Makefile                      |   2 +
>  security/tomoyo/common.c                      |  52 +-
>  security/tomoyo/common.h                      |  77 +--
>  security/tomoyo/domain.c                      |   1 +
>  security/tomoyo/environ.c                     |   1 +
>  security/tomoyo/file.c                        |   5 +
>  security/tomoyo/gc.c                          |  28 +-
>  security/tomoyo/mount.c                       |   2 +
>  security/tomoyo/network.c                     |   3 +
>  tools/include/linux/compiler_types.h          |   2 -
>  99 files changed, 2370 insertions(+), 589 deletions(-)
>  create mode 100644 Documentation/dev-tools/capability-analysis.rst
>  create mode 100644 include/linux/compiler-capability-analysis.h
>  create mode 100644 lib/test_capability-analysis.c
>  create mode 100644 scripts/Makefile.capability-analysis
>  create mode 100644 scripts/capability-analysis-suppression.txt
>
> --
> 2.51.0.384.g4c02a37b29-goog
>
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Linus Torvalds 1 week, 6 days ago
On Thu, 18 Sept 2025 at 07:05, 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],

So this looks really interesting, but I absolutely *hate* the new
"capability" name.

We have existing and traditional - and very very different - meaning
of "capabilities" in the kernel, and having this thing called
"capability" is just wrong. Particularly as it then talks about
"acquiring capabilities" - which is *EXACTLY* what our lon-existing
capabilities are all about, but are something entirely and totally
different.

So please - call it something else. Even if clang then calls it
'capability analysis", within the context of a kernel, please ignore
that, and call it something that makes more sense (I don't think
"capabilities" make sense even in the context of clang, but hey,
that's _their_ choice - but we should not then take that bad choice
and run with it).

Sparse called it "context analysis", and while the "analysis" part is
debatable - sparse never did much anything clever enough to merit
calling it analysis - at least the "context" part of the name is I
think somewhat sane.

Because it's about making decisions based on the context the code runs in.

But I'm certainly not married to the "context" name either. I'd still
claim it makes more sense than "capability", but the real problem with
"capability" isn't that it doesn't make sense, it's that we already
*HAVE* that as a concept, and old and traditional use is important.

But we do use the word "context" in this context quite widely even
outside of the sparse usage, ie that's what we say when we talk about
things like locking and RCU (ie we talk about running in "process
context", or about "interrupt context" etc). That's obviously where
the sparse naming comes from - it's not like sparse made that up.

So I'm really happy to see compilers start exposing these kinds of
interfaces, and the patches look sane apart from the absolutely
horrible and unacceptable name. Really - there is no way in hell we
can call this "capability" in a kernel context.

I'd suggest just doing a search-and-replace of 's/capability/context/'
and it would already make things a ton better. But maybe there are
better names for this still?

I mean, even apart from the fact that we have an existing meaning for
"capability", just look at the documentation patch, and read the first
sentence:

  Capability analysis is a C language extension, which enables statically
  checking that user-definable "capabilities" are acquired and released where
  required.

and just from a plain English language standpoint, the word
"capability" makes zero sense. I think you even realized that, in that
you put that word in quotes, because it's _so_ nonsensical.

And if not "context", maybe some other word? But really, absolutely
*not* "capability". Because that's just crazy talk.

Please? Because other than this naming issue, I think this really is a
good idea.

           Linus
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Marco Elver 1 week, 6 days ago
On Thu, Sep 18, 2025 at 08:49AM -0700, Linus Torvalds wrote:

> I'd suggest just doing a search-and-replace of 's/capability/context/'
> and it would already make things a ton better. But maybe there are
> better names for this still?

Fair points. "Context Analysis" makes sense, but it makes the thing
(e.g. lock) used to establish that context a little awkward to refer to
-- see half-baked attempt at reworking the documentation below.

Maybe this:

  Instance that must be acquired to enter context = "Context Guard"?

We can then still call it "Context Analysis". And I need to be mindful
of calling the objects themselves "Context Guard" throughout that
search-and-replace. E.g. the macro to create a context-guard-enabled
struct would be "context_guard_struct(spinlock) { ..".

I also thought about "Guard Analysis", but that sounds wrong, too.
Because we also have overloaded "guard(..)" (<linux/cleanup.h>).

Preferences?

[...]
> And if not "context", maybe some other word? But really, absolutely
> *not* "capability". Because that's just crazy talk.
> 
> Please? Because other than this naming issue, I think this really is a
> good idea.

Thanks,
-- Marco

------ >8 ------

diff --git a/Documentation/dev-tools/capability-analysis.rst b/Documentation/dev-tools/capability-analysis.rst
index 3456132261c6..b0c0961d6af5 100644
--- a/Documentation/dev-tools/capability-analysis.rst
+++ b/Documentation/dev-tools/capability-analysis.rst
@@ -1,80 +1,79 @@
 .. SPDX-License-Identifier: GPL-2.0
 .. Copyright (C) 2025, Google LLC.
 
-.. _capability-analysis:
+.. _context-analysis:
 
-Compiler-Based Capability Analysis
-==================================
+Compiler-Based Context Analysis
+===============================
 
-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.
+Context analysis is a C language extension, which enables statically checking
+that user-definable contexts 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 context if held), and
+checking that locking rules are not violated.
 
-The Clang compiler currently supports the full set of capability analysis
+The Clang compiler currently supports the full set of context analysis
 features. To enable for Clang, configure the kernel with::
 
-    CONFIG_WARN_CAPABILITY_ANALYSIS=y
+    CONFIG_WARN_CONTEXT_ANALYSIS=y
 
 The feature requires Clang 22 or later.
 
 The analysis is *opt-in by default*, and requires declaring which modules and
 subsystems should be analyzed in the respective `Makefile`::
 
-    CAPABILITY_ANALYSIS_mymodule.o := y
+    CONTEXT_ANALYSIS_mymodule.o := y
 
 Or for all translation units in the directory::
 
-    CAPABILITY_ANALYSIS := y
+    CONTEXT_ANALYSIS := y
 
 It is possible to enable the analysis tree-wide, however, which will result in
 numerous false positive warnings currently and is *not* generally recommended::
 
-    CONFIG_WARN_CAPABILITY_ANALYSIS_ALL=y
+    CONFIG_WARN_CONTEXT_ANALYSIS_ALL=y
 
 Programming Model
 -----------------
 
-The below describes the programming model around using capability-enabled
-types.
+The below describes the programming model around using context-enabled types.
 
 .. note::
-   Enabling capability analysis can be seen as enabling a dialect of Linux C with
-   a Capability System. Some valid patterns involving complex control-flow are
+   Enabling context analysis can be seen as enabling a dialect of Linux C with
+   a Context System. Some valid patterns involving complex control-flow are
    constrained (such as conditional acquisition and later conditional release
-   in the same function, or returning pointers to capabilities from functions.
+   in the same function).
 
-Capability analysis is a way to specify permissibility of operations to depend
-on capabilities being held (or not held). Typically we are interested in
-protecting data and code by requiring some capability to be held, for example a
-specific lock. The analysis ensures that the caller cannot perform the
-operation without holding the appropriate capability.
+Context analysis is a way to specify permissibility of operations to depend on
+contexts being held (or not held). Typically we are interested in protecting
+data and code in a critical section by requiring a specific context to be held,
+for example a specific lock. The analysis ensures that the caller cannot
+perform the operation without holding the appropriate context.
 
-Capabilities are associated with named structs, along with functions that
-operate on capability-enabled struct instances to acquire and release the
-associated capability.
+Contexts are associated with named structs, along with functions that operate
+on context-enabled struct instances to acquire and release the associated
+context.
 
-Capabilities can be held either exclusively or shared. This mechanism allows
-assign more precise privileges when holding a capability, typically to
+Contexts can be held either exclusively or shared. This mechanism allows
+assigning more precise privileges when holding a context, typically to
 distinguish where a thread may only read (shared) or also write (exclusive) to
 guarded data.
 
-The set of capabilities that are actually held by a given thread at a given
-point in program execution is a run-time concept. The static analysis works by
-calculating an approximation of that set, called the capability environment.
-The capability environment is calculated for every program point, and describes
-the set of capabilities that are statically known to be held, or not held, at
-that particular point. This environment is a conservative approximation of the
-full set of capabilities that will actually held by a thread at run-time.
+The set of contexts that are actually held by a given thread at a given point
+in program execution is a run-time concept. The static analysis works by
+calculating an approximation of that set, called the context environment.  The
+context environment is calculated for every program point, and describes the
+set of contexts that are statically known to be held, or not held, at that
+particular point. This environment is a conservative approximation of the full
+set of contexts that will actually held by a thread at run-time.
 
 More details are also documented `here
 <https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>`_.
 
 .. note::
-   Clang's analysis explicitly does not infer capabilities acquired or released
+   Clang's analysis explicitly does not infer contexts acquired or released
    by inline functions. It requires explicit annotations to (a) assert that
-   it's not a bug if a capability is released or acquired, and (b) to retain
+   it's not a bug if a context is released or acquired, and (b) to retain
    consistency between inline and non-inline function declarations.
 
 Supported Kernel Primitives
@@ -85,13 +84,13 @@ Currently the following synchronization primitives are supported:
 `bit_spinlock`, RCU, SRCU (`srcu_struct`), `rw_semaphore`, `local_lock_t`,
 `ww_mutex`.
 
-For capabilities with an initialization function (e.g., `spin_lock_init()`),
-calling this function on the capability instance before initializing any
-guarded members or globals prevents the compiler from issuing warnings about
-unguarded initialization.
+For contexts with an initialization function (e.g., `spin_lock_init()`),
+calling this function on the context instance before initializing any guarded
+members or globals prevents the compiler from issuing warnings about unguarded
+initialization.
 
 Lockdep assertions, such as `lockdep_assert_held()`, inform the compiler's
-capability analysis that the associated synchronization primitive is held after
+context analysis that the associated synchronization primitive is held after
 the assertion. This avoids false positives in complex control-flow scenarios
 and encourages the use of Lockdep where static analysis is limited. For
 example, this is useful when a function doesn't *always* require a lock, making
@@ -100,9 +99,9 @@ example, this is useful when a function doesn't *always* require a lock, making
 Keywords
 ~~~~~~~~
 
-.. kernel-doc:: include/linux/compiler-capability-analysis.h
-   :identifiers: struct_with_capability
-                 token_capability token_capability_instance
+.. kernel-doc:: include/linux/compiler-context-analysis.h
+   :identifiers: struct_with_context
+                 token_context token_context_instance
                  __guarded_by __pt_guarded_by
                  __must_hold
                  __must_not_hold
@@ -117,13 +116,13 @@ Keywords
                  __release
                  __acquire_shared
                  __release_shared
-                 capability_unsafe
-                 __capability_unsafe
-                 disable_capability_analysis enable_capability_analysis
+                 context_unsafe
+                 __context_unsafe
+                 disable_context_analysis enable_context_analysis
 
 .. note::
-   The function attribute `__no_capability_analysis` is reserved for internal
-   implementation of capability-enabled primitives, and should be avoided in
+   The function attribute `__no_context_analysis` is reserved for internal
+   implementation of context-enabled primitives, and should be avoided in
    normal code.
 
 Background
@@ -140,9 +139,10 @@ Indeed, its foundations can be found in `capability systems
 the permissibility of operations to depend on some capability being held (or
 not held).
 
-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 option that also still appears in diagnostic messages.
+Because the feature is not just able to express contexts related to
+synchronization primitives, and "capability" is already overloaded in the
+kernel, the naming chosen for the kernel departs from Clang's initial "Thread
+Safety" and "Capability" nomenclature and refers to the feature as "Context
+Analysis" to avoid confusion. The internal implementation still makes
+references to Clang's terminology, such as `-Wthread-safety` being the warning
+option that also still appears in diagnostic messages.
diff --git a/include/linux/compiler-capability-analysis.h b/include/linux/compiler-capability-analysis.h
index f8a1da67589c..7882684a8308 100644
--- a/include/linux/compiler-capability-analysis.h
+++ b/include/linux/compiler-capability-analysis.h
@@ -1,42 +1,43 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Macros and attributes for compiler-based static capability analysis.
+ * Macros and attributes for compiler-based static context analysis.
  */
 
-#ifndef _LINUX_COMPILER_CAPABILITY_ANALYSIS_H
-#define _LINUX_COMPILER_CAPABILITY_ANALYSIS_H
+#ifndef _LINUX_COMPILER_CONTEXT_ANALYSIS_H
+#define _LINUX_COMPILER_CONTEXT_ANALYSIS_H
 
-#if defined(WARN_CAPABILITY_ANALYSIS)
+#if defined(WARN_CONTEXT_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 attributes are used to define new context (Clang: capability) types.
+ * Internal only.
+ */
+# define __ctx_type(name)			__attribute__((capability(#name)))
+# define __reentrant_ctx			__attribute__((reentrant_capability))
+# define __acquires_ctx(...)			__attribute__((acquire_capability(__VA_ARGS__)))
+# define __acquires_shared_ctx(...)		__attribute__((acquire_shared_capability(__VA_ARGS__)))
+# define __try_acquires_ctx(ret, var)		__attribute__((try_acquire_capability(ret, var)))
+# define __try_acquires_shared_ctx(ret, var)	__attribute__((try_acquire_shared_capability(ret, var)))
+# define __releases_ctx(...)			__attribute__((release_capability(__VA_ARGS__)))
+# define __releases_shared_ctx(...)		__attribute__((release_shared_capability(__VA_ARGS__)))
+# define __assumes_ctx(...)			__attribute__((assert_capability(__VA_ARGS__)))
+# define __assumes_shared_ctx(...)		__attribute__((assert_shared_capability(__VA_ARGS__)))
+# define __returns_ctx(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__)))
+# define __excludes_ctx(...)		__attribute__((locks_excluded(__VA_ARGS__)))
+# define __requires_ctx(...)		__attribute__((requires_capability(__VA_ARGS__)))
+# define __requires_shared_ctx(...)	__attribute__((requires_shared_capability(__VA_ARGS__)))
 
 /**
  * __guarded_by - struct member and globals attribute, declares variable
- *                protected by capability
+ *                protected by context
  *
  * 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.
+ * given context. Read operations on the data require shared access, while write
+ * operations require exclusive access.
  *
  * .. code-block:: c
  *
@@ -49,11 +50,11 @@
 
 /**
  * __pt_guarded_by - struct member and globals attribute, declares pointed-to
- *                   data is protected by capability
+ *                   data is protected by context
  *
  * 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.
+ * pointer must be guarded by the given contexts. Read operations on the data
+ * require shared access, while write operations require exclusive access.
  *
  * .. code-block:: c
  *
@@ -65,14 +66,14 @@
 # define __pt_guarded_by(...)		__attribute__((pt_guarded_by(__VA_ARGS__)))
 
 /**
- * struct_with_capability() - declare or define a capability struct
+ * struct_with_context() - declare or define a context struct
  * @name: struct name
  *
- * Helper to declare or define a struct type with capability of the same name.
+ * Helper to declare or define a struct type with context of the same name.
  *
  * .. code-block:: c
  *
- *	struct_with_capability(my_handle) {
+ *	struct_with_context(my_handle) {
  *		int foo;
  *		long bar;
  *	};
@@ -81,98 +82,98 @@
  *		...
  *	};
  *	// ... declared elsewhere ...
- *	struct_with_capability(some_state);
+ *	struct_with_context(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)	\
+ * release, and assert the context is held.
+ */
+# define struct_with_context(name, ...)								\
+	struct __ctx_type(name) __VA_ARGS__ name;							\
+	static __always_inline void __acquire_ctx(const struct name *var)				\
+		__attribute__((overloadable)) __no_context_analysis __acquires_ctx(var) { }		\
+	static __always_inline void __acquire_shared_ctx(const struct name *var)			\
+		__attribute__((overloadable)) __no_context_analysis __acquires_shared_ctx(var) { }	\
+	static __always_inline bool __try_acquire_ctx(const struct name *var, bool ret)			\
+		__attribute__((overloadable)) __no_context_analysis __try_acquires_ctx(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) \
+	static __always_inline bool __try_acquire_shared_ctx(const struct name *var, bool ret)		\
+		__attribute__((overloadable)) __no_context_analysis __try_acquires_shared_ctx(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) { }				\
+	static __always_inline void __release_ctx(const struct name *var)				\
+		__attribute__((overloadable)) __no_context_analysis __releases_ctx(var) { }		\
+	static __always_inline void __release_shared_ctx(const struct name *var)			\
+		__attribute__((overloadable)) __no_context_analysis __releases_shared_ctx(var) { }	\
+	static __always_inline void __assume_ctx(const struct name *var)				\
+		__attribute__((overloadable)) __assumes_ctx(var) { }					\
+	static __always_inline void __assume_shared_ctx(const struct name *var)				\
+		__attribute__((overloadable)) __assumes_shared_ctx(var) { }				\
 	struct name
 
 /**
- * disable_capability_analysis() - disables capability analysis
+ * disable_context_analysis() - disables context analysis
  *
- * Disables capability analysis. Must be paired with a later
- * enable_capability_analysis().
+ * Disables context analysis. Must be paired with a later
+ * enable_context_analysis().
  */
-# define disable_capability_analysis()				\
+# define disable_context_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
+ * enable_context_analysis() - re-enables context analysis
  *
- * Re-enables capability analysis. Must be paired with a prior
- * disable_capability_analysis().
+ * Re-enables context analysis. Must be paired with a prior
+ * disable_context_analysis().
  */
-# define enable_capability_analysis() __diag_pop()
+# define enable_context_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)
+ * __no_context_analysis - function attribute, disables context analysis
+ *
+ * Function attribute denoting that context analysis is disabled for the
+ * whole function. Prefer use of `context_unsafe()` where possible.
+ */
+# define __no_context_analysis	__attribute__((no_thread_safety_analysis))
+
+#else /* !WARN_CONTEXT_ANALYSIS */
+
+# define __ctx_type(name)
+# define __reentrant_ctx
+# define __acquires_ctx(...)
+# define __acquires_shared_ctx(...)
+# define __try_acquires_ctx(ret, var)
+# define __try_acquires_shared_ctx(ret, var)
+# define __releases_ctx(...)
+# define __releases_shared_ctx(...)
+# define __assumes_ctx(...)
+# define __assumes_shared_ctx(...)
+# define __returns_ctx(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 */
+# define __excludes_ctx(...)
+# define __requires_ctx(...)
+# define __requires_shared_ctx(...)
+# define __acquire_ctx(var)			do { } while (0)
+# define __acquire_shared_ctx(var)		do { } while (0)
+# define __try_acquire_ctx(var, ret)		(ret)
+# define __try_acquire_shared_ctx(var, ret)	(ret)
+# define __release_ctx(var)			do { } while (0)
+# define __release_shared_ctx(var)		do { } while (0)
+# define __assume_ctx(var)			do { (void)(var); } while (0)
+# define __assume_shared_ctx(var)		do { (void)(var); } while (0)
+# define struct_with_context(name, ...)	struct __VA_ARGS__ name
+# define disable_context_analysis()
+# define enable_context_analysis()
+# define __no_context_analysis
+
+#endif /* WARN_CONTEXT_ANALYSIS */
 
 /**
- * capability_unsafe() - disable capability checking for contained code
+ * context_unsafe() - disable context checking for contained code
  *
- * Disables capability checking for contained statements or expression.
+ * Disables context checking for contained statements or expression.
  *
  * .. code-block:: c
  *
@@ -186,30 +187,30 @@
  *		// ...
  *		// other code that is still checked ...
  *		// ...
- *		return capability_unsafe(d->counter);
+ *		return context_unsafe(d->counter);
  *	}
  */
-#define capability_unsafe(...)		\
+#define context_unsafe(...)		\
 ({					\
-	disable_capability_analysis();	\
+	disable_context_analysis();	\
 	__VA_ARGS__;			\
-	enable_capability_analysis()	\
+	enable_context_analysis()	\
 })
 
 /**
- * __capability_unsafe() - function attribute, disable capability checking
+ * __context_unsafe() - function attribute, disable context checking
  * @comment: comment explaining why opt-out is safe
  *
- * Function attribute denoting that capability analysis is disabled for the
+ * Function attribute denoting that context analysis is disabled for the
  * whole function. Forces adding an inline comment as argument.
  */
-#define __capability_unsafe(comment) __no_capability_analysis
+#define __context_unsafe(comment) __no_context_analysis
 
 /**
- * capability_unsafe_alias() - helper to insert a capability "alias barrier"
- * @p: pointer aliasing a capability or object containing capabilities
+ * context_unsafe_alias() - helper to insert a context "alias barrier"
+ * @p: pointer aliasing a context or object containing context pointers
  *
- * No-op function that acts as a "capability alias barrier", where the analysis
+ * No-op function that acts as a "context alias barrier", where the analysis
  * rightfully detects that we're switching aliases, but the switch is considered
  * safe but beyond the analysis reasoning abilities.
  *
@@ -219,61 +220,61 @@
  * 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) { }
+#define context_unsafe_alias(p) _context_unsafe_alias((void **)&(p))
+static inline void _context_unsafe_alias(void **p) { }
 
 /**
- * token_capability() - declare an abstract global capability instance
- * @name: token capability name
+ * token_context() - declare an abstract global context instance
+ * @name: token context 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`.
+ * Helper that declares an abstract global context instance @name that can be
+ * used as a token context, but not backed by a real data structure (linker
+ * error if accidentally referenced). The type name is `__context_@name`.
  */
-#define token_capability(name, ...)					\
-	struct_with_capability(__capability_##name, ##__VA_ARGS__) {};	\
-	extern const struct __capability_##name *name
+#define token_context(name, ...)					\
+	struct_with_context(__context_##name, ##__VA_ARGS__) {};	\
+	extern const struct __context_##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
+ * token_context_instance() - declare another instance of a global context
+ * @ctx: token context previously declared with token_context()
+ * @name: name of additional global context 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.
+ * context class @name. This is helpful where multiple related token
+ * contexts are declared, as it also allows using the same underlying type
+ * (`__context_@ctx`) as function arguments.
  */
-#define token_capability_instance(cap, name)		\
-	extern const struct __capability_##cap *name
+#define token_context_instance(ctx, name)		\
+	extern const struct __context_##ctx *name
 
 /*
- * Common keywords for static capability analysis.
+ * Common keywords for static context analysis.
  */
 
 /**
- * __must_hold() - function attribute, caller must hold exclusive capability
+ * __must_hold() - function attribute, caller must hold exclusive context
  *
- * Function attribute declaring that the caller must hold the given capability
+ * Function attribute declaring that the caller must hold the given context
  * instance(s) exclusively.
  */
-#define __must_hold(...)	__requires_cap(__VA_ARGS__)
+#define __must_hold(...)	__requires_ctx(__VA_ARGS__)
 
 /**
- * __must_not_hold() - function attribute, caller must not hold capability
+ * __must_not_hold() - function attribute, caller must not hold context
  *
  * Function attribute declaring that the caller must not hold the given
- * capability instance(s).
+ * context instance(s).
  */
-#define __must_not_hold(...)	__excludes_cap(__VA_ARGS__)
+#define __must_not_hold(...)	__excludes_ctx(__VA_ARGS__)
 
 /**
- * __acquires() - function attribute, function acquires capability exclusively
+ * __acquires() - function attribute, function acquires context exclusively
  *
  * Function attribute declaring that the function acquires the given
- * capability instance(s) exclusively, but does not release them.
+ * context instance(s) exclusively, but does not release them.
  */
-#define __acquires(...)		__acquires_cap(__VA_ARGS__)
+#define __acquires(...)		__acquires_ctx(__VA_ARGS__)
 
 /*
  * Clang's analysis does not care precisely about the value, only that it is
@@ -281,75 +282,75 @@ static inline void _capability_unsafe_alias(void **p) { }
  * misleading if we say that @ret is the value returned if acquired. Instead,
  * provide symbolic variants which we translate.
  */
-#define __cond_acquires_impl_true(x, ...)     __try_acquires##__VA_ARGS__##_cap(1, x)
-#define __cond_acquires_impl_false(x, ...)    __try_acquires##__VA_ARGS__##_cap(0, x)
-#define __cond_acquires_impl_nonzero(x, ...)  __try_acquires##__VA_ARGS__##_cap(1, x)
-#define __cond_acquires_impl_0(x, ...)        __try_acquires##__VA_ARGS__##_cap(0, x)
-#define __cond_acquires_impl_nonnull(x, ...)  __try_acquires##__VA_ARGS__##_cap(1, x)
-#define __cond_acquires_impl_NULL(x, ...)     __try_acquires##__VA_ARGS__##_cap(0, x)
+#define __cond_acquires_impl_true(x, ...)     __try_acquires##__VA_ARGS__##_ctx(1, x)
+#define __cond_acquires_impl_false(x, ...)    __try_acquires##__VA_ARGS__##_ctx(0, x)
+#define __cond_acquires_impl_nonzero(x, ...)  __try_acquires##__VA_ARGS__##_ctx(1, x)
+#define __cond_acquires_impl_0(x, ...)        __try_acquires##__VA_ARGS__##_ctx(0, x)
+#define __cond_acquires_impl_nonnull(x, ...)  __try_acquires##__VA_ARGS__##_ctx(1, x)
+#define __cond_acquires_impl_NULL(x, ...)     __try_acquires##__VA_ARGS__##_ctx(0, x)
 
 /**
  * __cond_acquires() - function attribute, function conditionally
- *                     acquires a capability exclusively
- * @ret: abstract value returned by function if capability acquired
- * @x: capability instance pointer
+ *                     acquires a context exclusively
+ * @ret: abstract value returned by function if context acquired
+ * @x: context instance pointer
  *
  * Function attribute declaring that the function conditionally acquires the
- * given capability instance @x exclusively, but does not release it. The
- * function return value @ret denotes when the capability is acquired.
+ * given context instance @x exclusively, but does not release it. The
+ * function return value @ret denotes when the context is acquired.
  *
  * @ret may be one of: true, false, nonzero, 0, nonnull, NULL.
  */
 #define __cond_acquires(ret, x) __cond_acquires_impl_##ret(x)
 
 /**
- * __releases() - function attribute, function releases a capability exclusively
+ * __releases() - function attribute, function releases a context exclusively
  *
- * Function attribute declaring that the function releases the given capability
- * instance(s) exclusively. The capability must be held on entry.
+ * Function attribute declaring that the function releases the given context
+ * instance(s) exclusively. The context must be held on entry.
  */
-#define __releases(...)		__releases_cap(__VA_ARGS__)
+#define __releases(...)		__releases_ctx(__VA_ARGS__)
 
 /**
- * __acquire() - function to acquire capability exclusively
- * @x: capability instance pointer
+ * __acquire() - function to acquire context exclusively
+ * @x: context instance pointer
  *
- * No-op function that acquires the given capability instance @x exclusively.
+ * No-op function that acquires the given context instance @x exclusively.
  */
-#define __acquire(x)		__acquire_cap(x)
+#define __acquire(x)		__acquire_ctx(x)
 
 /**
- * __release() - function to release capability exclusively
- * @x: capability instance pointer
+ * __release() - function to release context exclusively
+ * @x: context instance pointer
  *
- * No-op function that releases the given capability instance @x.
+ * No-op function that releases the given context instance @x.
  */
-#define __release(x)		__release_cap(x)
+#define __release(x)		__release_ctx(x)
 
 /**
- * __must_hold_shared() - function attribute, caller must hold shared capability
+ * __must_hold_shared() - function attribute, caller must hold shared context
  *
- * Function attribute declaring that the caller must hold the given capability
+ * Function attribute declaring that the caller must hold the given context
  * instance(s) with shared access.
  */
-#define __must_hold_shared(...)	__requires_shared_cap(__VA_ARGS__)
+#define __must_hold_shared(...)	__requires_shared_ctx(__VA_ARGS__)
 
 /**
- * __acquires_shared() - function attribute, function acquires capability shared
+ * __acquires_shared() - function attribute, function acquires context shared
  *
  * Function attribute declaring that the function acquires the given
- * capability instance(s) with shared access, but does not release them.
+ * context instance(s) with shared access, but does not release them.
  */
-#define __acquires_shared(...)	__acquires_shared_cap(__VA_ARGS__)
+#define __acquires_shared(...)	__acquires_shared_ctx(__VA_ARGS__)
 
 /**
  * __cond_acquires_shared() - function attribute, function conditionally
- *                            acquires a capability shared
- * @ret: abstract value returned by function if capability acquired
+ *                            acquires a context shared
+ * @ret: abstract value returned by function if context acquired
  *
  * Function attribute declaring that the function conditionally acquires the
- * given capability instance @x with shared access, but does not release it. The
- * function return value @ret denotes when the capability is acquired.
+ * given context instance @x with shared access, but does not release it. The
+ * function return value @ret denotes when the context is acquired.
  *
  * @ret may be one of: true, false, nonzero, 0, nonnull, NULL.
  */
@@ -357,33 +358,33 @@ static inline void _capability_unsafe_alias(void **p) { }
 
 /**
  * __releases_shared() - function attribute, function releases a
- *                       capability shared
+ *                       context shared
  *
- * Function attribute declaring that the function releases the given capability
- * instance(s) with shared access. The capability must be held on entry.
+ * Function attribute declaring that the function releases the given context
+ * instance(s) with shared access. The context must be held on entry.
  */
-#define __releases_shared(...)	__releases_shared_cap(__VA_ARGS__)
+#define __releases_shared(...)	__releases_shared_ctx(__VA_ARGS__)
 
 /**
- * __acquire_shared() - function to acquire capability shared
- * @x: capability instance pointer
+ * __acquire_shared() - function to acquire context shared
+ * @x: context instance pointer
  *
- * No-op function that acquires the given capability instance @x with shared
+ * No-op function that acquires the given context instance @x with shared
  * access.
  */
-#define __acquire_shared(x)	__acquire_shared_cap(x)
+#define __acquire_shared(x)	__acquire_shared_ctx(x)
 
 /**
- * __release_shared() - function to release capability shared
- * @x: capability instance pointer
+ * __release_shared() - function to release context shared
+ * @x: context instance pointer
  *
- * No-op function that releases the given capability instance @x with shared
+ * No-op function that releases the given context instance @x with shared
  * access.
  */
-#define __release_shared(x)	__release_shared_cap(x)
+#define __release_shared(x)	__release_shared_ctx(x)
 
 /**
- * __acquire_ret() - helper to acquire capability of return value
+ * __acquire_ret() - helper to acquire context of return value
  * @call: call expression
  * @ret_expr: acquire expression that uses __ret
  */
@@ -395,7 +396,7 @@ static inline void _capability_unsafe_alias(void **p) { }
 	})
 
 /**
- * __acquire_shared_ret() - helper to acquire capability shared of return value
+ * __acquire_shared_ret() - helper to acquire context shared of return value
  * @call: call expression
  * @ret_expr: acquire shared expression that uses __ret
  */
@@ -407,7 +408,7 @@ static inline void _capability_unsafe_alias(void **p) { }
 	})
 
 /*
- * Attributes to mark functions returning acquired capabilities. This is purely
+ * Attributes to mark functions returning acquired contexts. This is purely
  * cosmetic to help readability, and should be used with the above macros as
  * follows:
  *
@@ -417,7 +418,7 @@ static inline void _capability_unsafe_alias(void **p) { }
  *   struct foo *_myfunc(int bar) __acquires_ret;
  *   ...
  */
-#define __acquires_ret		__no_capability_analysis
-#define __acquires_shared_ret	__no_capability_analysis
+#define __acquires_ret		__no_context_analysis
+#define __acquires_shared_ret	__no_context_analysis
 
-#endif /* _LINUX_COMPILER_CAPABILITY_ANALYSIS_H */
+#endif /* _LINUX_COMPILER_CONTEXT_ANALYSIS_H */
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Linus Torvalds 1 week, 6 days ago
On Thu, 18 Sept 2025 at 14:26, Marco Elver <elver@google.com> wrote:
>
> Fair points. "Context Analysis" makes sense, but it makes the thing
> (e.g. lock) used to establish that context a little awkward to refer to
> -- see half-baked attempt at reworking the documentation below.

Yeah, I agree that some of that reads more than a bit oddly.

I wonder if we could talk about "context analysis", but then when
discussing what is *held* for a particular context, call that a
"context token" or something like that?

But I don't mind your "Context guard" notion either. I'm not loving
it, but it's not offensive to me either.

Then the language would be feel fairly straightforward,

Eg:

> +Context analysis is a way to specify permissibility of operations to depend on
> +contexts being held (or not held).

That "contexts being held" sounds odd, but talking about "context
markers", or "context tokens" would seem natural.

An alternative would be to not talk about markers / tokens / guards at
all, but simply about a context being *active*.

IOW, instead of wording it like this:

> +The set of contexts that are actually held by a given thread at a given point
> +in program execution is a run-time concept.

that talks about "being held", you could just state it in the sense of
the "set of contexts being active", and that immediately reads fairly
naturally, doesn't it?

Because a context is a *state* you are in, it's not something you hold on to.

The tokens - or whatever - would be only some internal implementation
detail of how the compiler keeps track of which state is active, not
the conceptual idea itself.

So you name states, and you have functions to mark those context
states as being entered or exited, but you don't really even have to
talk about "holding" anything.

No?

               Linus
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Marco Elver 1 week, 5 days ago
On Thu, Sep 18, 2025 at 02:47PM -0700, Linus Torvalds wrote:
[...] 
> But I don't mind your "Context guard" notion either. I'm not loving
> it, but it's not offensive to me either.
> 
> Then the language would be feel fairly straightforward,
> 
> Eg:
> 
> > +Context analysis is a way to specify permissibility of operations to depend on
> > +contexts being held (or not held).
> 
> That "contexts being held" sounds odd, but talking about "context
> markers", or "context tokens" would seem natural.
> 
> An alternative would be to not talk about markers / tokens / guards at
> all, but simply about a context being *active*.

That works for high-level descriptions, but we need something for the
API, too, which specifically operates and refers to the objects which
are acquired/released to enter/exit a context.

> IOW, instead of wording it like this:
> 
> > +The set of contexts that are actually held by a given thread at a given point
> > +in program execution is a run-time concept.
> 
> that talks about "being held", you could just state it in the sense of
> the "set of contexts being active", and that immediately reads fairly
> naturally, doesn't it?
> 
> Because a context is a *state* you are in, it's not something you hold on to.
> 
> The tokens - or whatever - would be only some internal implementation
> detail of how the compiler keeps track of which state is active, not
> the conceptual idea itself.
> 
> So you name states, and you have functions to mark those context
> states as being entered or exited, but you don't really even have to
> talk about "holding" anything.

It's a tough one -- because fundamentally we operate on objects, which
when acquired/released we enter/exit some context. I tried to balance
not venturing off too far from common terminology, while keeping it
general enough to allow eventual uses for "IRQ enable/disable", "preempt
enable/disable", or anything else where we might need to enter/exit some
context to access a resource (incl. perhaps Ian's suggestion of figuring
out if we can design a refcount_t API that uses context tracking).

I went with "context guard" to refer to the objects themselves, as that
doesn't look too odd. It does match the concept of "guard" in
<linux/cleanup.h>.

See second attempt below.

Preferences?

Thanks,
-- Marco

------ >8 ------

diff --git a/Documentation/dev-tools/capability-analysis.rst b/Documentation/dev-tools/capability-analysis.rst
index 3456132261c6..87125ec2db11 100644
--- a/Documentation/dev-tools/capability-analysis.rst
+++ b/Documentation/dev-tools/capability-analysis.rst
@@ -1,81 +1,80 @@
 .. SPDX-License-Identifier: GPL-2.0
 .. Copyright (C) 2025, Google LLC.
 
-.. _capability-analysis:
+.. _context-analysis:
 
-Compiler-Based Capability Analysis
-==================================
+Compiler-Based Context Analysis
+===============================
 
-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.
+Context analysis is a C language extension, which enables statically checking
+that user-definable context guards 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 context guard), and
+checking that locking rules are not violated.
 
-The Clang compiler currently supports the full set of capability analysis
+The Clang compiler currently supports the full set of context analysis
 features. To enable for Clang, configure the kernel with::
 
-    CONFIG_WARN_CAPABILITY_ANALYSIS=y
+    CONFIG_WARN_CONTEXT_ANALYSIS=y
 
 The feature requires Clang 22 or later.
 
 The analysis is *opt-in by default*, and requires declaring which modules and
 subsystems should be analyzed in the respective `Makefile`::
 
-    CAPABILITY_ANALYSIS_mymodule.o := y
+    CONTEXT_ANALYSIS_mymodule.o := y
 
 Or for all translation units in the directory::
 
-    CAPABILITY_ANALYSIS := y
+    CONTEXT_ANALYSIS := y
 
 It is possible to enable the analysis tree-wide, however, which will result in
 numerous false positive warnings currently and is *not* generally recommended::
 
-    CONFIG_WARN_CAPABILITY_ANALYSIS_ALL=y
+    CONFIG_WARN_CONTEXT_ANALYSIS_ALL=y
 
 Programming Model
 -----------------
 
-The below describes the programming model around using capability-enabled
-types.
+The below describes the programming model around using context guard types.
 
 .. note::
-   Enabling capability analysis can be seen as enabling a dialect of Linux C with
-   a Capability System. Some valid patterns involving complex control-flow are
+   Enabling context analysis can be seen as enabling a dialect of Linux C with
+   a Context System. Some valid patterns involving complex control-flow are
    constrained (such as conditional acquisition and later conditional release
-   in the same function, or returning pointers to capabilities from functions.
+   in the same function).
 
-Capability analysis is a way to specify permissibility of operations to depend
-on capabilities being held (or not held). Typically we are interested in
-protecting data and code by requiring some capability to be held, for example a
-specific lock. The analysis ensures that the caller cannot perform the
-operation without holding the appropriate capability.
+Context analysis is a way to specify permissibility of operations to depend on
+context guards being held (or not held). Typically we are interested in
+protecting data and code in a critical section by requiring a specific context
+to be active, for example by holding a specific lock. The analysis ensures that
+callers cannot perform an operation without the required context being active.
 
-Capabilities are associated with named structs, along with functions that
-operate on capability-enabled struct instances to acquire and release the
-associated capability.
+Context guards are associated with named structs, along with functions that
+operate on struct instances to acquire and release the associated context
+guard.
 
-Capabilities can be held either exclusively or shared. This mechanism allows
-assign more precise privileges when holding a capability, typically to
+Context guards can be held either exclusively or shared. This mechanism allows
+assigning more precise privileges when a context is active, typically to
 distinguish where a thread may only read (shared) or also write (exclusive) to
-guarded data.
+data guarded within a context.
 
-The set of capabilities that are actually held by a given thread at a given
-point in program execution is a run-time concept. The static analysis works by
-calculating an approximation of that set, called the capability environment.
-The capability environment is calculated for every program point, and describes
-the set of capabilities that are statically known to be held, or not held, at
-that particular point. This environment is a conservative approximation of the
-full set of capabilities that will actually held by a thread at run-time.
+The set of contexts that are actually active in a given thread at a given point
+in program execution is a run-time concept. The static analysis works by
+calculating an approximation of that set, called the context environment. The
+context environment is calculated for every program point, and describes the
+set of contexts that are statically known to be active, or inactive, at that
+particular point. This environment is a conservative approximation of the full
+set of contexts that will actually be active in a thread at run-time.
 
 More details are also documented `here
 <https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>`_.
 
 .. note::
-   Clang's analysis explicitly does not infer capabilities acquired or released
-   by inline functions. It requires explicit annotations to (a) assert that
-   it's not a bug if a capability is released or acquired, and (b) to retain
-   consistency between inline and non-inline function declarations.
+   Clang's analysis explicitly does not infer context guards acquired or
+   released by inline functions. It requires explicit annotations to (a) assert
+   that it's not a bug if a context guard is released or acquired, and (b) to
+   retain consistency between inline and non-inline function declarations.
 
 Supported Kernel Primitives
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -85,13 +84,12 @@ Currently the following synchronization primitives are supported:
 `bit_spinlock`, RCU, SRCU (`srcu_struct`), `rw_semaphore`, `local_lock_t`,
 `ww_mutex`.
 
-For capabilities with an initialization function (e.g., `spin_lock_init()`),
-calling this function on the capability instance before initializing any
-guarded members or globals prevents the compiler from issuing warnings about
-unguarded initialization.
+For context guards with an initialization function (e.g., `spin_lock_init()`),
+calling this function before initializing any guarded members or globals
+prevents the compiler from issuing warnings about unguarded initialization.
 
 Lockdep assertions, such as `lockdep_assert_held()`, inform the compiler's
-capability analysis that the associated synchronization primitive is held after
+context analysis that the associated synchronization primitive is held after
 the assertion. This avoids false positives in complex control-flow scenarios
 and encourages the use of Lockdep where static analysis is limited. For
 example, this is useful when a function doesn't *always* require a lock, making
@@ -100,9 +98,9 @@ example, this is useful when a function doesn't *always* require a lock, making
 Keywords
 ~~~~~~~~
 
-.. kernel-doc:: include/linux/compiler-capability-analysis.h
-   :identifiers: struct_with_capability
-                 token_capability token_capability_instance
+.. kernel-doc:: include/linux/compiler-context-analysis.h
+   :identifiers: context_guard_struct
+                 token_context_guard token_context_guard_instance
                  __guarded_by __pt_guarded_by
                  __must_hold
                  __must_not_hold
@@ -117,32 +115,32 @@ Keywords
                  __release
                  __acquire_shared
                  __release_shared
-                 capability_unsafe
-                 __capability_unsafe
-                 disable_capability_analysis enable_capability_analysis
+                 __acquire_ret
+                 __acquire_shared_ret
+                 context_unsafe
+                 __context_unsafe
+                 disable_context_analysis enable_context_analysis
 
 .. note::
-   The function attribute `__no_capability_analysis` is reserved for internal
-   implementation of capability-enabled primitives, and should be avoided in
-   normal code.
+   The function attribute `__no_context_analysis` is reserved for internal
+   implementation of context guard types, and should be avoided in normal code.
 
 Background
 ----------
 
 Clang originally called the feature `Thread Safety Analysis
-<https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>`_, 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".
-
-Indeed, its foundations can be found in `capability systems
-<https://www.cs.cornell.edu/talc/papers/capabilities.pdf>`_, used to specify
-the permissibility of operations to depend on some capability being held (or
-not held).
+<https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>`_, with some keywords
+and documentation still using the thread-safety-analysis-only terminology. 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 <https://www.cs.cornell.edu/talc/papers/capabilities.pdf>`_, used to
+specify the permissibility of operations to depend on some "capability" being
+held (or not held).
 
 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`
+synchronization primitives, and "capability" is already overloaded in the
+kernel, the naming chosen for the kernel departs from Clang's initial "Thread
+Safety" and "capability" nomenclature; we refer to the feature as "Context
+Analysis" to avoid confusion. The internal implementation still makes
+references to Clang's terminology in a few places, such as `-Wthread-safety`
 being the warning option that also still appears in diagnostic messages.
diff --git a/include/linux/compiler-capability-analysis.h b/include/linux/compiler-capability-analysis.h
index f8a1da67589c..b3804c5ac40d 100644
--- a/include/linux/compiler-capability-analysis.h
+++ b/include/linux/compiler-capability-analysis.h
@@ -1,42 +1,43 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Macros and attributes for compiler-based static capability analysis.
+ * Macros and attributes for compiler-based static context analysis.
  */
 
-#ifndef _LINUX_COMPILER_CAPABILITY_ANALYSIS_H
-#define _LINUX_COMPILER_CAPABILITY_ANALYSIS_H
+#ifndef _LINUX_COMPILER_CONTEXT_ANALYSIS_H
+#define _LINUX_COMPILER_CONTEXT_ANALYSIS_H
 
-#if defined(WARN_CAPABILITY_ANALYSIS)
+#if defined(WARN_CONTEXT_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)))
+ * These attributes define new context guard (Clang: capability) types.
+ * Internal only.
+ */
+# define __ctx_guard_type(name)			__attribute__((capability(#name)))
+# define __reentrant_ctx_guard			__attribute__((reentrant_capability))
+# define __acquires_ctx_guard(...)		__attribute__((acquire_capability(__VA_ARGS__)))
+# define __acquires_shared_ctx_guard(...)	__attribute__((acquire_shared_capability(__VA_ARGS__)))
+# define __try_acquires_ctx_guard(ret, var)	__attribute__((try_acquire_capability(ret, var)))
+# define __try_acquires_shared_ctx_guard(ret, var) __attribute__((try_acquire_shared_capability(ret, var)))
+# define __releases_ctx_guard(...)		__attribute__((release_capability(__VA_ARGS__)))
+# define __releases_shared_ctx_guard(...)	__attribute__((release_shared_capability(__VA_ARGS__)))
+# define __assumes_ctx_guard(...)		__attribute__((assert_capability(__VA_ARGS__)))
+# define __assumes_shared_ctx_guard(...)	__attribute__((assert_shared_capability(__VA_ARGS__)))
+# define __returns_ctx_guard(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__)))
+# define __excludes_ctx_guard(...)		__attribute__((locks_excluded(__VA_ARGS__)))
+# define __requires_ctx_guard(...)		__attribute__((requires_capability(__VA_ARGS__)))
+# define __requires_shared_ctx_guard(...)	__attribute__((requires_shared_capability(__VA_ARGS__)))
 
 /**
  * __guarded_by - struct member and globals attribute, declares variable
- *                protected by capability
+ *                only accessible within active context
  *
- * 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.
+ * Declares that the struct member or global variable is only accessible within
+ * the context entered by the given context guard. Read operations on the data
+ * require shared access, while write operations require exclusive access.
  *
  * .. code-block:: c
  *
@@ -49,11 +50,12 @@
 
 /**
  * __pt_guarded_by - struct member and globals attribute, declares pointed-to
- *                   data is protected by capability
+ *                   data only accessible within active context
  *
  * 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.
+ * pointer is only accessible within the context entered by the given context
+ * guard. Read operations on the data require shared access, while write
+ * operations require exclusive access.
  *
  * .. code-block:: c
  *
@@ -65,14 +67,14 @@
 # define __pt_guarded_by(...)		__attribute__((pt_guarded_by(__VA_ARGS__)))
 
 /**
- * struct_with_capability() - declare or define a capability struct
+ * context_guard_struct() - declare or define a context guard struct
  * @name: struct name
  *
- * Helper to declare or define a struct type with capability of the same name.
+ * Helper to declare or define a struct type that is also a context guard.
  *
  * .. code-block:: c
  *
- *	struct_with_capability(my_handle) {
+ *	context_guard_struct(my_handle) {
  *		int foo;
  *		long bar;
  *	};
@@ -81,98 +83,98 @@
  *		...
  *	};
  *	// ... 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)	\
+ *	context_guard_struct(some_state);
+ *
+ * Note: The implementation defines several helper functions that can acquire
+ * and release the context guard.
+ */
+# define context_guard_struct(name, ...)								\
+	struct __ctx_guard_type(name) __VA_ARGS__ name;							\
+	static __always_inline void __acquire_ctx_guard(const struct name *var)				\
+		__attribute__((overloadable)) __no_context_analysis __acquires_ctx_guard(var) { }	\
+	static __always_inline void __acquire_shared_ctx_guard(const struct name *var)			\
+		__attribute__((overloadable)) __no_context_analysis __acquires_shared_ctx_guard(var) { } \
+	static __always_inline bool __try_acquire_ctx_guard(const struct name *var, bool ret)		\
+		__attribute__((overloadable)) __no_context_analysis __try_acquires_ctx_guard(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) \
+	static __always_inline bool __try_acquire_shared_ctx_guard(const struct name *var, bool ret)	\
+		__attribute__((overloadable)) __no_context_analysis __try_acquires_shared_ctx_guard(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) { }				\
+	static __always_inline void __release_ctx_guard(const struct name *var)				\
+		__attribute__((overloadable)) __no_context_analysis __releases_ctx_guard(var) { }	\
+	static __always_inline void __release_shared_ctx_guard(const struct name *var)			\
+		__attribute__((overloadable)) __no_context_analysis __releases_shared_ctx_guard(var) { } \
+	static __always_inline void __assume_ctx_guard(const struct name *var)				\
+		__attribute__((overloadable)) __assumes_ctx_guard(var) { }				\
+	static __always_inline void __assume_shared_ctx_guard(const struct name *var)			\
+		__attribute__((overloadable)) __assumes_shared_ctx_guard(var) { }			\
 	struct name
 
 /**
- * disable_capability_analysis() - disables capability analysis
+ * disable_context_analysis() - disables context analysis
  *
- * Disables capability analysis. Must be paired with a later
- * enable_capability_analysis().
+ * Disables context analysis. Must be paired with a later
+ * enable_context_analysis().
  */
-# define disable_capability_analysis()				\
+# define disable_context_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
+ * enable_context_analysis() - re-enables context analysis
  *
- * Re-enables capability analysis. Must be paired with a prior
- * disable_capability_analysis().
+ * Re-enables context analysis. Must be paired with a prior
+ * disable_context_analysis().
  */
-# define enable_capability_analysis() __diag_pop()
+# define enable_context_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)
+ * __no_context_analysis - function attribute, disables context analysis
+ *
+ * Function attribute denoting that context analysis is disabled for the
+ * whole function. Prefer use of `context_unsafe()` where possible.
+ */
+# define __no_context_analysis	__attribute__((no_thread_safety_analysis))
+
+#else /* !WARN_CONTEXT_ANALYSIS */
+
+# define __ctx_guard_type(name)
+# define __reentrant_ctx_guard
+# define __acquires_ctx_guard(...)
+# define __acquires_shared_ctx_guard(...)
+# define __try_acquires_ctx_guard(ret, var)
+# define __try_acquires_shared_ctx_guard(ret, var)
+# define __releases_ctx_guard(...)
+# define __releases_shared_ctx_guard(...)
+# define __assumes_ctx_guard(...)
+# define __assumes_shared_ctx_guard(...)
+# define __returns_ctx_guard(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 */
+# define __excludes_ctx_guard(...)
+# define __requires_ctx_guard(...)
+# define __requires_shared_ctx_guard(...)
+# define __acquire_ctx_guard(var)			do { } while (0)
+# define __acquire_shared_ctx_guard(var)		do { } while (0)
+# define __try_acquire_ctx_guard(var, ret)		(ret)
+# define __try_acquire_shared_ctx_guard(var, ret)	(ret)
+# define __release_ctx_guard(var)			do { } while (0)
+# define __release_shared_ctx_guard(var)		do { } while (0)
+# define __assume_ctx_guard(var)			do { (void)(var); } while (0)
+# define __assume_shared_ctx_guard(var)			do { (void)(var); } while (0)
+# define context_guard_struct(name, ...)		struct __VA_ARGS__ name
+# define disable_context_analysis()
+# define enable_context_analysis()
+# define __no_context_analysis
+
+#endif /* WARN_CONTEXT_ANALYSIS */
 
 /**
- * capability_unsafe() - disable capability checking for contained code
+ * context_unsafe() - disable context checking for contained code
  *
- * Disables capability checking for contained statements or expression.
+ * Disables context checking for contained statements or expression.
  *
  * .. code-block:: c
  *
@@ -186,32 +188,32 @@
  *		// ...
  *		// other code that is still checked ...
  *		// ...
- *		return capability_unsafe(d->counter);
+ *		return context_unsafe(d->counter);
  *	}
  */
-#define capability_unsafe(...)		\
+#define context_unsafe(...)		\
 ({					\
-	disable_capability_analysis();	\
+	disable_context_analysis();	\
 	__VA_ARGS__;			\
-	enable_capability_analysis()	\
+	enable_context_analysis()	\
 })
 
 /**
- * __capability_unsafe() - function attribute, disable capability checking
+ * __context_unsafe() - function attribute, disable context checking
  * @comment: comment explaining why opt-out is safe
  *
- * Function attribute denoting that capability analysis is disabled for the
+ * Function attribute denoting that context analysis is disabled for the
  * whole function. Forces adding an inline comment as argument.
  */
-#define __capability_unsafe(comment) __no_capability_analysis
+#define __context_unsafe(comment) __no_context_analysis
 
 /**
- * capability_unsafe_alias() - helper to insert a capability "alias barrier"
- * @p: pointer aliasing a capability or object containing capabilities
+ * context_unsafe_alias() - helper to insert a context guard "alias barrier"
+ * @p: pointer aliasing a context guard or object containing context guards
  *
- * 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.
+ * No-op function that acts as a "context guard 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.
  *
@@ -219,61 +221,61 @@
  * 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) { }
+#define context_unsafe_alias(p) _context_unsafe_alias((void **)&(p))
+static inline void _context_unsafe_alias(void **p) { }
 
 /**
- * token_capability() - declare an abstract global capability instance
- * @name: token capability name
+ * token_context_guard() - declare an abstract global context guard instance
+ * @name: token context guard 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`.
+ * Helper that declares an abstract global context guard instance @name, but not
+ * backed by a real data structure (linker error if accidentally referenced).
+ * The type name is `__context_@name`.
  */
-#define token_capability(name, ...)					\
-	struct_with_capability(__capability_##name, ##__VA_ARGS__) {};	\
-	extern const struct __capability_##name *name
+#define token_context_guard(name, ...)					\
+	context_guard_struct(__context_##name, ##__VA_ARGS__) {};	\
+	extern const struct __context_##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
+ * token_context_guard_instance() - declare another instance of a global context guard
+ * @ctx: token context guard previously declared with token_context_guard()
+ * @name: name of additional global context guard 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.
+ * Helper that declares an additional instance @name of the same token context
+ * guard class @ctx. This is helpful where multiple related token contexts are
+ * declared, as it also allows using the same underlying type (`__context_@ctx`)
+ * as function arguments.
  */
-#define token_capability_instance(cap, name)		\
-	extern const struct __capability_##cap *name
+#define token_context_guard_instance(ctx, name)		\
+	extern const struct __context_##ctx *name
 
 /*
- * Common keywords for static capability analysis.
+ * Common keywords for static context analysis.
  */
 
 /**
- * __must_hold() - function attribute, caller must hold exclusive capability
+ * __must_hold() - function attribute, caller must hold exclusive context guard
  *
- * Function attribute declaring that the caller must hold the given capability
- * instance(s) exclusively.
+ * Function attribute declaring that the caller must hold the given context
+ * guard instance(s) exclusively.
  */
-#define __must_hold(...)	__requires_cap(__VA_ARGS__)
+#define __must_hold(...)	__requires_ctx_guard(__VA_ARGS__)
 
 /**
- * __must_not_hold() - function attribute, caller must not hold capability
+ * __must_not_hold() - function attribute, caller must not hold context guard
  *
  * Function attribute declaring that the caller must not hold the given
- * capability instance(s).
+ * context guard instance(s).
  */
-#define __must_not_hold(...)	__excludes_cap(__VA_ARGS__)
+#define __must_not_hold(...)	__excludes_ctx_guard(__VA_ARGS__)
 
 /**
- * __acquires() - function attribute, function acquires capability exclusively
+ * __acquires() - function attribute, function acquires context guard exclusively
  *
  * Function attribute declaring that the function acquires the given
- * capability instance(s) exclusively, but does not release them.
+ * context guard instance(s) exclusively, but does not release them.
  */
-#define __acquires(...)		__acquires_cap(__VA_ARGS__)
+#define __acquires(...)		__acquires_ctx_guard(__VA_ARGS__)
 
 /*
  * Clang's analysis does not care precisely about the value, only that it is
@@ -281,75 +283,76 @@ static inline void _capability_unsafe_alias(void **p) { }
  * misleading if we say that @ret is the value returned if acquired. Instead,
  * provide symbolic variants which we translate.
  */
-#define __cond_acquires_impl_true(x, ...)     __try_acquires##__VA_ARGS__##_cap(1, x)
-#define __cond_acquires_impl_false(x, ...)    __try_acquires##__VA_ARGS__##_cap(0, x)
-#define __cond_acquires_impl_nonzero(x, ...)  __try_acquires##__VA_ARGS__##_cap(1, x)
-#define __cond_acquires_impl_0(x, ...)        __try_acquires##__VA_ARGS__##_cap(0, x)
-#define __cond_acquires_impl_nonnull(x, ...)  __try_acquires##__VA_ARGS__##_cap(1, x)
-#define __cond_acquires_impl_NULL(x, ...)     __try_acquires##__VA_ARGS__##_cap(0, x)
+#define __cond_acquires_impl_true(x, ...)     __try_acquires##__VA_ARGS__##_ctx_guard(1, x)
+#define __cond_acquires_impl_false(x, ...)    __try_acquires##__VA_ARGS__##_ctx_guard(0, x)
+#define __cond_acquires_impl_nonzero(x, ...)  __try_acquires##__VA_ARGS__##_ctx_guard(1, x)
+#define __cond_acquires_impl_0(x, ...)        __try_acquires##__VA_ARGS__##_ctx_guard(0, x)
+#define __cond_acquires_impl_nonnull(x, ...)  __try_acquires##__VA_ARGS__##_ctx_guard(1, x)
+#define __cond_acquires_impl_NULL(x, ...)     __try_acquires##__VA_ARGS__##_ctx_guard(0, x)
 
 /**
  * __cond_acquires() - function attribute, function conditionally
- *                     acquires a capability exclusively
- * @ret: abstract value returned by function if capability acquired
- * @x: capability instance pointer
+ *                     acquires a context guard exclusively
+ * @ret: abstract value returned by function if context guard acquired
+ * @x: context guard instance pointer
  *
  * Function attribute declaring that the function conditionally acquires the
- * given capability instance @x exclusively, but does not release it. The
- * function return value @ret denotes when the capability is acquired.
+ * given context guard instance @x exclusively, but does not release it. The
+ * function return value @ret denotes when the context guard is acquired.
  *
  * @ret may be one of: true, false, nonzero, 0, nonnull, NULL.
  */
 #define __cond_acquires(ret, x) __cond_acquires_impl_##ret(x)
 
 /**
- * __releases() - function attribute, function releases a capability exclusively
+ * __releases() - function attribute, function releases a context guard exclusively
  *
- * Function attribute declaring that the function releases the given capability
- * instance(s) exclusively. The capability must be held on entry.
+ * Function attribute declaring that the function releases the given context
+ * guard instance(s) exclusively. The associated context must be active on
+ * entry.
  */
-#define __releases(...)		__releases_cap(__VA_ARGS__)
+#define __releases(...)		__releases_ctx_guard(__VA_ARGS__)
 
 /**
- * __acquire() - function to acquire capability exclusively
- * @x: capability instance pointer
+ * __acquire() - function to acquire context guard exclusively
+ * @x: context guard instance pointer
  *
- * No-op function that acquires the given capability instance @x exclusively.
+ * No-op function that acquires the given context guard instance @x exclusively.
  */
-#define __acquire(x)		__acquire_cap(x)
+#define __acquire(x)		__acquire_ctx_guard(x)
 
 /**
- * __release() - function to release capability exclusively
- * @x: capability instance pointer
+ * __release() - function to release context guard exclusively
+ * @x: context guard instance pointer
  *
- * No-op function that releases the given capability instance @x.
+ * No-op function that releases the given context guard instance @x.
  */
-#define __release(x)		__release_cap(x)
+#define __release(x)		__release_ctx_guard(x)
 
 /**
- * __must_hold_shared() - function attribute, caller must hold shared capability
+ * __must_hold_shared() - function attribute, caller must hold shared context guard
  *
- * Function attribute declaring that the caller must hold the given capability
- * instance(s) with shared access.
+ * Function attribute declaring that the caller must hold the given context
+ * guard instance(s) with shared access.
  */
-#define __must_hold_shared(...)	__requires_shared_cap(__VA_ARGS__)
+#define __must_hold_shared(...)	__requires_shared_ctx_guard(__VA_ARGS__)
 
 /**
- * __acquires_shared() - function attribute, function acquires capability shared
+ * __acquires_shared() - function attribute, function acquires context guard shared
  *
  * Function attribute declaring that the function acquires the given
- * capability instance(s) with shared access, but does not release them.
+ * context guard instance(s) with shared access, but does not release them.
  */
-#define __acquires_shared(...)	__acquires_shared_cap(__VA_ARGS__)
+#define __acquires_shared(...)	__acquires_shared_ctx_guard(__VA_ARGS__)
 
 /**
  * __cond_acquires_shared() - function attribute, function conditionally
- *                            acquires a capability shared
- * @ret: abstract value returned by function if capability acquired
+ *                            acquires a context guard shared
+ * @ret: abstract value returned by function if context guard acquired
  *
  * Function attribute declaring that the function conditionally acquires the
- * given capability instance @x with shared access, but does not release it. The
- * function return value @ret denotes when the capability is acquired.
+ * given context guard instance @x with shared access, but does not release it.
+ * The function return value @ret denotes when the context guard is acquired.
  *
  * @ret may be one of: true, false, nonzero, 0, nonnull, NULL.
  */
@@ -357,33 +360,34 @@ static inline void _capability_unsafe_alias(void **p) { }
 
 /**
  * __releases_shared() - function attribute, function releases a
- *                       capability shared
+ *                       context guard shared
  *
- * Function attribute declaring that the function releases the given capability
- * instance(s) with shared access. The capability must be held on entry.
+ * Function attribute declaring that the function releases the given context
+ * guard instance(s) with shared access. The associated context must be active
+ * on entry.
  */
-#define __releases_shared(...)	__releases_shared_cap(__VA_ARGS__)
+#define __releases_shared(...)	__releases_shared_ctx_guard(__VA_ARGS__)
 
 /**
- * __acquire_shared() - function to acquire capability shared
- * @x: capability instance pointer
+ * __acquire_shared() - function to acquire context guard shared
+ * @x: context guard instance pointer
  *
- * No-op function that acquires the given capability instance @x with shared
+ * No-op function that acquires the given context guard instance @x with shared
  * access.
  */
-#define __acquire_shared(x)	__acquire_shared_cap(x)
+#define __acquire_shared(x)	__acquire_shared_ctx_guard(x)
 
 /**
- * __release_shared() - function to release capability shared
- * @x: capability instance pointer
+ * __release_shared() - function to release context guard shared
+ * @x: context guard instance pointer
  *
- * No-op function that releases the given capability instance @x with shared
+ * No-op function that releases the given context guard instance @x with shared
  * access.
  */
-#define __release_shared(x)	__release_shared_cap(x)
+#define __release_shared(x)	__release_shared_ctx_guard(x)
 
 /**
- * __acquire_ret() - helper to acquire capability of return value
+ * __acquire_ret() - helper to acquire context guard of return value
  * @call: call expression
  * @ret_expr: acquire expression that uses __ret
  */
@@ -395,7 +399,7 @@ static inline void _capability_unsafe_alias(void **p) { }
 	})
 
 /**
- * __acquire_shared_ret() - helper to acquire capability shared of return value
+ * __acquire_shared_ret() - helper to acquire context guard shared of return value
  * @call: call expression
  * @ret_expr: acquire shared expression that uses __ret
  */
@@ -407,9 +411,9 @@ static inline void _capability_unsafe_alias(void **p) { }
 	})
 
 /*
- * Attributes to mark functions returning acquired capabilities. This is purely
- * cosmetic to help readability, and should be used with the above macros as
- * follows:
+ * Attributes to mark functions returning acquired context guards. This is
+ * purely cosmetic to help readability, and should be used with the above macros
+ * as follows:
  *
  *   struct foo { spinlock_t lock; ... };
  *   ...
@@ -417,7 +421,7 @@ static inline void _capability_unsafe_alias(void **p) { }
  *   struct foo *_myfunc(int bar) __acquires_ret;
  *   ...
  */
-#define __acquires_ret		__no_capability_analysis
-#define __acquires_shared_ret	__no_capability_analysis
+#define __acquires_ret		__no_context_analysis
+#define __acquires_shared_ret	__no_context_analysis
 
-#endif /* _LINUX_COMPILER_CAPABILITY_ANALYSIS_H */
+#endif /* _LINUX_COMPILER_CONTEXT_ANALYSIS_H */
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Christoph Hellwig 1 week, 6 days ago
On Thu, Sep 18, 2025 at 03:59:11PM +0200, Marco Elver wrote:
> A Clang version that supports `-Wthread-safety-pointer` and the new
> alias-analysis of capability pointers is required (from this version
> onwards):
> 
> 	https://github.com/llvm/llvm-project/commit/b4c98fcbe1504841203e610c351a3227f36c92a4 [3]

There's no chance to make say x86 pre-built binaries for that available?
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Nathan Chancellor 1 week, 6 days ago
On Thu, Sep 18, 2025 at 04:15:11PM +0200, Christoph Hellwig wrote:
> On Thu, Sep 18, 2025 at 03:59:11PM +0200, Marco Elver wrote:
> > A Clang version that supports `-Wthread-safety-pointer` and the new
> > alias-analysis of capability pointers is required (from this version
> > onwards):
> > 
> > 	https://github.com/llvm/llvm-project/commit/b4c98fcbe1504841203e610c351a3227f36c92a4 [3]
> 
> There's no chance to make say x86 pre-built binaries for that available?

I can use my existing kernel.org LLVM [1] build infrastructure to
generate prebuilt x86 binaries. Just give me a bit to build and upload
them. You may not be the only developer or maintainer who may want to
play with this.

[1]: https://kernel.org/pub/tools/llvm/

Cheers,
Nathan
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Christoph Hellwig 1 week, 5 days ago
On Thu, Sep 18, 2025 at 10:45:55AM -0700, Nathan Chancellor wrote:
> On Thu, Sep 18, 2025 at 04:15:11PM +0200, Christoph Hellwig wrote:
> > On Thu, Sep 18, 2025 at 03:59:11PM +0200, Marco Elver wrote:
> > > A Clang version that supports `-Wthread-safety-pointer` and the new
> > > alias-analysis of capability pointers is required (from this version
> > > onwards):
> > > 
> > > 	https://github.com/llvm/llvm-project/commit/b4c98fcbe1504841203e610c351a3227f36c92a4 [3]
> > 
> > There's no chance to make say x86 pre-built binaries for that available?
> 
> I can use my existing kernel.org LLVM [1] build infrastructure to
> generate prebuilt x86 binaries. Just give me a bit to build and upload
> them. You may not be the only developer or maintainer who may want to
> play with this.

That did work, thanks.

I started to play around with that.  For the nvme code adding the
annotations was very simply, and I also started adding trivial
__guarded_by which instantly found issues.

For XFS it was a lot more work and I still see tons of compiler
warnings, which I'm not entirely sure how to address.  Right now I
see three major classes:

1) locks held over loop iterations like:

fs/xfs/xfs_extent_busy.c:573:26: warning: expecting spinlock 'xfs_group_hold(busyp->group)..xg_busy_extents->eb_lock' to be held at start of each loop [-Wthread-safety-analysis]
  573 |                 struct xfs_group        *xg = xfs_group_hold(busyp->group);
      |                                               ^
fs/xfs/xfs_extent_busy.c:577:3: note: spinlock acquired here
  577 |                 spin_lock(&eb->eb_lock);
      |                 ^

This is perfectly find code and needs some annotations, but I can't find
any good example.

2) Locks on returned objects, which can be NULL.  I.e., something
like crossover of __acquire_ret and __cond_acquires

3) Wrappers that take multiple locks conditionally

We have helpers that take different locks in the same object based on the
arguments like xfs_ilock() or those that take the same lock and a variable
number of objects like xfs_dqlockn based on input and sorting.  The
first are just historic and we might want to kill them, but the
sorting of objects to acquire locks in order thing is a pattern in
various places including the VFS, so we'll need some way to annotate it.
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Bart Van Assche 1 week, 5 days ago
On 9/19/25 7:08 AM, Christoph Hellwig wrote:
> 3) Wrappers that take multiple locks conditionally
> 
> We have helpers that take different locks in the same object based on the
> arguments like xfs_ilock() or those that take the same lock and a variable
> number of objects like xfs_dqlockn based on input and sorting.  The
> first are just historic and we might want to kill them, but the
> sorting of objects to acquire locks in order thing is a pattern in
> various places including the VFS, so we'll need some way to annotate it.

Hi Christoph,

As you probably remember some time ago I took a look myself at adding
locking annotations to kernel code. I ended up annotating multiple XFS
functions with NO_THREAD_SAFETY_ANALYSIS. Maybe the locking patterns in
XFS are too complex for compile-time analysis? See also the XFS changes
in 
https://lore.kernel.org/lkml/20250206175114.1974171-33-bvanassche@acm.org/.

Thanks,

Bart.
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Christoph Hellwig 1 week, 2 days ago
On Fri, Sep 19, 2025 at 10:20:37AM -0700, Bart Van Assche wrote:
> locking annotations to kernel code. I ended up annotating multiple XFS
> functions with NO_THREAD_SAFETY_ANALYSIS. Maybe the locking patterns in
> XFS are too complex for compile-time analysis?

If our locking patterns are too complex for analysis, either the code or
the analysis has problems that need addressing.  Potentially both.
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Christoph Hellwig 1 week, 5 days ago
On Fri, Sep 19, 2025 at 04:08:03PM +0200, Christoph Hellwig wrote:
> I started to play around with that.  For the nvme code adding the
> annotations was very simply, and I also started adding trivial
> __guarded_by which instantly found issues.
> 
> For XFS it was a lot more work and I still see tons of compiler
> warnings, which I'm not entirely sure how to address.  Right now I
> see three major classes:

And in case anyone cares, here are my patches for that:

https://git.infradead.org/?p=users/hch/misc.git;a=shortlog;h=refs/heads/cap-analysis

git://git.infradead.org/users/hch/misc.git cap-analysis
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Marco Elver 1 week, 2 days ago
On Fri, Sep 19, 2025 at 04:09PM +0200, Christoph Hellwig wrote:
> On Fri, Sep 19, 2025 at 04:08:03PM +0200, Christoph Hellwig wrote:
> > I started to play around with that.  For the nvme code adding the
> > annotations was very simply, and I also started adding trivial
> > __guarded_by which instantly found issues.
> > 
> > For XFS it was a lot more work and I still see tons of compiler
> > warnings, which I'm not entirely sure how to address.  Right now I
> > see three major classes:
> 
> And in case anyone cares, here are my patches for that:
> 
> https://git.infradead.org/?p=users/hch/misc.git;a=shortlog;h=refs/heads/cap-analysis
> 
> git://git.infradead.org/users/hch/misc.git cap-analysis

I gave this a try, and with the below patch and the Clang fix [1],
fs/xfs compiles cleanly. I think the fundamental limitation are the
conditional locking wrappers. I suspect it's possible to do better than
disabling the analysis here, by overapproximating the lock set taken
(like you did elsewhere), so that at least the callers are checked, but
when I tried it showed lots of callers need annotating as well, so I
gave up at that point. Still, it might be better than no checking at
all.

[1] https://github.com/llvm/llvm-project/pull/159921

Thanks,
 -- Marco


diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 9c39251961a3..f371a08e5d44 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -140,6 +140,7 @@ void
 xfs_ilock(
 	xfs_inode_t		*ip,
 	uint			lock_flags)
+	__capability_unsafe(/* conditional locking */)
 {
 	trace_xfs_ilock(ip, lock_flags, _RET_IP_);
 
@@ -183,6 +184,7 @@ int
 xfs_ilock_nowait(
 	xfs_inode_t		*ip,
 	uint			lock_flags)
+	__capability_unsafe(/* conditional locking */)
 {
 	trace_xfs_ilock_nowait(ip, lock_flags, _RET_IP_);
 
@@ -243,6 +245,7 @@ void
 xfs_iunlock(
 	xfs_inode_t		*ip,
 	uint			lock_flags)
+	__capability_unsafe(/* conditional locking */)
 {
 	xfs_lock_flags_assert(lock_flags);
 
@@ -272,6 +275,7 @@ void
 xfs_ilock_demote(
 	xfs_inode_t		*ip,
 	uint			lock_flags)
+	__capability_unsafe(/* conditional locking */)
 {
 	ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_MMAPLOCK_EXCL|XFS_ILOCK_EXCL));
 	ASSERT((lock_flags &
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index d9ac9521c203..9c4ec3aa8bf9 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -472,6 +472,7 @@ xfs_log_reserve(
 static void
 xlog_state_shutdown_callbacks(
 	struct xlog		*log)
+	__must_hold(&log->l_icloglock)
 {
 	struct xlog_in_core	*iclog;
 	LIST_HEAD(cb_list);
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Nathan Chancellor 1 week, 1 day ago
On Mon, Sep 22, 2025 at 11:33:23AM +0200, Marco Elver wrote:
> [1] https://github.com/llvm/llvm-project/pull/159921

Now that this is merged, I have pushed an updated snapshot for x86_64:

https://mirrors.edge.kernel.org/pub/tools/llvm/files/prerelease/llvm-22.0.0-ca2e8fc928ad103f46ca9f827e147c43db3a5c47-20250923-185804-x86_64.tar.xz

Cheers,
Nathan
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Christoph Hellwig 1 week, 2 days ago
On Mon, Sep 22, 2025 at 11:33:23AM +0200, Marco Elver wrote:
> I gave this a try, and with the below patch and the Clang fix [1],
> fs/xfs compiles cleanly. I think the fundamental limitation are the
> conditional locking wrappers. I suspect it's possible to do better than
> disabling the analysis here, by overapproximating the lock set taken
> (like you did elsewhere), so that at least the callers are checked, but
> when I tried it showed lots of callers need annotating as well, so I
> gave up at that point. Still, it might be better than no checking at
> all.

I guess this at least allows us to work with the analysis, even if it 
drops coverage for one of the most important locks.  I guess you also
have CONFIG_XFS_QUOTA disabled as that would lead to similar warnings,
and also currently has the lock the object on return if it's not a
NULL return case?  I now have a local series to remove that instance,
but I've seen that pattern elsewhere in the kernel code.

Besides the conditional locking these two also do another thing that
is nasty to the analysis, the locked state can be attached to a
transaction and unlocked at transaction commit.  Not sure how to best
model that.

> [1] https://github.com/llvm/llvm-project/pull/159921

Thanks for all the work!
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Nathan Chancellor 1 week, 6 days ago
On Thu, Sep 18, 2025 at 10:45:55AM -0700, Nathan Chancellor wrote:
> On Thu, Sep 18, 2025 at 04:15:11PM +0200, Christoph Hellwig wrote:
> > On Thu, Sep 18, 2025 at 03:59:11PM +0200, Marco Elver wrote:
> > > A Clang version that supports `-Wthread-safety-pointer` and the new
> > > alias-analysis of capability pointers is required (from this version
> > > onwards):
> > > 
> > > 	https://github.com/llvm/llvm-project/commit/b4c98fcbe1504841203e610c351a3227f36c92a4 [3]
> > 
> > There's no chance to make say x86 pre-built binaries for that available?
> 
> I can use my existing kernel.org LLVM [1] build infrastructure to
> generate prebuilt x86 binaries. Just give me a bit to build and upload
> them. You may not be the only developer or maintainer who may want to
> play with this.

This should include Marco's change, let me know if there are any issues.

https://kernel.org/pub/tools/llvm/files/prerelease/llvm-22.0.0-e19fa930ca838715028c00c234874d1db4f93154-20250918-184558-x86_64.tar.xz

Cheers,
Nathan
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Marco Elver 1 week, 6 days ago
On Thu, 18 Sept 2025 at 16:15, Christoph Hellwig <hch@lst.de> wrote:
>
> On Thu, Sep 18, 2025 at 03:59:11PM +0200, Marco Elver wrote:
> > A Clang version that supports `-Wthread-safety-pointer` and the new
> > alias-analysis of capability pointers is required (from this version
> > onwards):
> >
> >       https://github.com/llvm/llvm-project/commit/b4c98fcbe1504841203e610c351a3227f36c92a4 [3]
>
> There's no chance to make say x86 pre-built binaries for that available?

Not officially, but I can try to build something to share if you prefer.
Or a script that automatically pulls and builds clang for you - I have
this old script I just updated to the above commit:
https://gist.github.com/melver/fe8a5fd9e43e21fab569ee24fc9c6072
Does that help?
Re: [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis
Posted by Christoph Hellwig 1 week, 6 days ago
On Thu, Sep 18, 2025 at 04:30:55PM +0200, Marco Elver wrote:
> Not officially, but I can try to build something to share if you prefer.
> Or a script that automatically pulls and builds clang for you - I have
> this old script I just updated to the above commit:
> https://gist.github.com/melver/fe8a5fd9e43e21fab569ee24fc9c6072
> Does that help?

Just kicked it off, I'll see how long this will take on my laptop.
At least the error checking that tells me about dependencies and work
that needs to be done before starting the build is nice so that I
hopefully don't have to restart the build too often.
[syzbot ci] Re: Compiler-Based Capability- and Locking-Analysis
Posted by syzbot ci 1 week, 6 days ago
syzbot ci has tested the following series

[v3] Compiler-Based Capability- and Locking-Analysis
https://lore.kernel.org/all/20250918140451.1289454-1-elver@google.com
* [PATCH v3 01/35] compiler_types: Move lock checking attributes to compiler-capability-analysis.h
* [PATCH v3 02/35] compiler-capability-analysis: Add infrastructure for Clang's capability analysis
* [PATCH v3 03/35] compiler-capability-analysis: Add test stub
* [PATCH v3 04/35] Documentation: Add documentation for Compiler-Based Capability Analysis
* [PATCH v3 05/35] checkpatch: Warn about capability_unsafe() without comment
* [PATCH v3 06/35] cleanup: Basic compatibility with capability analysis
* [PATCH v3 07/35] lockdep: Annotate lockdep assertions for capability analysis
* [PATCH v3 08/35] locking/rwlock, spinlock: Support Clang's capability analysis
* [PATCH v3 09/35] compiler-capability-analysis: Change __cond_acquires to take return value
* [PATCH v3 10/35] locking/mutex: Support Clang's capability analysis
* [PATCH v3 11/35] locking/seqlock: Support Clang's capability analysis
* [PATCH v3 12/35] bit_spinlock: Include missing <asm/processor.h>
* [PATCH v3 13/35] bit_spinlock: Support Clang's capability analysis
* [PATCH v3 14/35] rcu: Support Clang's capability analysis
* [PATCH v3 15/35] srcu: Support Clang's capability analysis
* [PATCH v3 16/35] kref: Add capability-analysis annotations
* [PATCH v3 17/35] locking/rwsem: Support Clang's capability analysis
* [PATCH v3 18/35] locking/local_lock: Include missing headers
* [PATCH v3 19/35] locking/local_lock: Support Clang's capability analysis
* [PATCH v3 20/35] locking/ww_mutex: Support Clang's capability analysis
* [PATCH v3 21/35] debugfs: Make debugfs_cancellation a capability struct
* [PATCH v3 22/35] compiler-capability-analysis: Remove Sparse support
* [PATCH v3 23/35] compiler-capability-analysis: Remove __cond_lock() function-like helper
* [PATCH v3 24/35] compiler-capability-analysis: Introduce header suppressions
* [PATCH v3 25/35] compiler: Let data_race() imply disabled capability analysis
* [PATCH v3 26/35] MAINTAINERS: Add entry for Capability Analysis
* [PATCH v3 27/35] kfence: Enable capability analysis
* [PATCH v3 28/35] kcov: Enable capability analysis
* [PATCH v3 29/35] kcsan: Enable capability analysis
* [PATCH v3 30/35] stackdepot: Enable capability analysis
* [PATCH v3 31/35] rhashtable: Enable capability analysis
* [PATCH v3 32/35] printk: Move locking annotation to printk.c
* [PATCH v3 33/35] security/tomoyo: Enable capability analysis
* [PATCH v3 34/35] crypto: Enable capability analysis
* [PATCH v3 35/35] sched: Enable capability analysis for core.c and fair.c

and found the following issue:
general protection fault in validate_page_before_insert

Full report is available here:
https://ci.syzbot.org/series/81182522-74c0-4494-bcf8-976133df7dc7

***

general protection fault in validate_page_before_insert

tree:      torvalds
URL:       https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux
base:      f83ec76bf285bea5727f478a68b894f5543ca76e
arch:      amd64
compiler:  Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
config:    https://ci.syzbot.org/builds/8f7ff868-4cf7-40da-b62b-45ebfec4e994/config

cgroup: Unknown subsys name 'net'
cgroup: Unknown subsys name 'cpuset'
cgroup: Unknown subsys name 'rlimit'
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN PTI
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
CPU: 0 UID: 0 PID: 5775 Comm: syz-executor Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
RIP: 0010:validate_page_before_insert+0x2a/0x300
Code: 55 41 57 41 56 41 55 41 54 53 48 89 f3 49 89 fe 49 bd 00 00 00 00 00 fc ff df e8 f1 3f b3 ff 4c 8d 7b 08 4c 89 f8 48 c1 e8 03 <42> 80 3c 28 00 74 08 4c 89 ff e8 17 b3 16 00 4d 8b 3f 4c 89 fe 48
RSP: 0018:ffffc90002a5f608 EFLAGS: 00010202
RAX: 0000000000000001 RBX: 0000000000000000 RCX: ffff888022891cc0
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff888028c71200
RBP: ffffc90002a5f720 R08: 0000000000000000 R09: 1ffff11021cf81e0
R10: dffffc0000000000 R11: ffffed1021cf81e1 R12: dffffc0000000000
R13: dffffc0000000000 R14: ffff888028c71200 R15: 0000000000000008
FS:  00005555815ad500(0000) GS:ffff8880b8615000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f1788fd20b8 CR3: 000000010d8a4000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 insert_page+0x90/0x2c0
 kcov_mmap+0xc3/0x130
 mmap_region+0x18ae/0x20c0
 do_mmap+0xc45/0x10d0
 vm_mmap_pgoff+0x2a6/0x4d0
 ksys_mmap_pgoff+0x51f/0x760
 do_syscall_64+0xfa/0x3b0
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f1788d8ebe3
Code: f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 41 89 ca 41 f7 c1 ff 0f 00 00 75 14 b8 09 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 25 c3 0f 1f 40 00 48 c7 c0 a8 ff ff ff 64 c7
RSP: 002b:00007ffc8a37e638 EFLAGS: 00000246 ORIG_RAX: 0000000000000009
RAX: ffffffffffffffda RBX: 00007ffc8a37e670 RCX: 00007f1788d8ebe3
RDX: 0000000000000003 RSI: 0000000000400000 RDI: 00007f17867ff000
RBP: 00007ffc8a37e940 R08: 00000000000000d8 R09: 0000000000000000
R10: 0000000000000011 R11: 0000000000000246 R12: 0000000000000003
R13: 0000000000000000 R14: 00007f1788fa11c0 R15: 00007f1788e2e478
 </TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:validate_page_before_insert+0x2a/0x300
Code: 55 41 57 41 56 41 55 41 54 53 48 89 f3 49 89 fe 49 bd 00 00 00 00 00 fc ff df e8 f1 3f b3 ff 4c 8d 7b 08 4c 89 f8 48 c1 e8 03 <42> 80 3c 28 00 74 08 4c 89 ff e8 17 b3 16 00 4d 8b 3f 4c 89 fe 48
RSP: 0018:ffffc90002a5f608 EFLAGS: 00010202
RAX: 0000000000000001 RBX: 0000000000000000 RCX: ffff888022891cc0
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff888028c71200
RBP: ffffc90002a5f720 R08: 0000000000000000 R09: 1ffff11021cf81e0
R10: dffffc0000000000 R11: ffffed1021cf81e1 R12: dffffc0000000000
R13: dffffc0000000000 R14: ffff888028c71200 R15: 0000000000000008
FS:  00005555815ad500(0000) GS:ffff8880b8615000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f1788fd20b8 CR3: 000000010d8a4000 CR4: 00000000000006f0


***

If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
  Tested-by: syzbot@syzkaller.appspotmail.com

---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.
Re: [syzbot ci] Re: Compiler-Based Capability- and Locking-Analysis
Posted by Marco Elver 1 week, 6 days ago
On Thu, Sep 18, 2025 at 12:41PM -0700, syzbot ci wrote:
> syzbot ci has tested the following series
> 
> [v3] Compiler-Based Capability- and Locking-Analysis
[...]
> and found the following issue:
> general protection fault in validate_page_before_insert
> 
> Full report is available here:
> https://ci.syzbot.org/series/81182522-74c0-4494-bcf8-976133df7dc7
> 
> ***
> 
> general protection fault in validate_page_before_insert

Thanks, syzbot ci!

I messed up the type when moving kcov->area access inside the critical
section. This is the fix:


    fixup! kcov: Enable capability analysis

diff --git a/kernel/kcov.c b/kernel/kcov.c
index 1897c8ca6209..e81e3c0d01c6 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -497,7 +497,7 @@ static int kcov_mmap(struct file *filep, struct vm_area_struct *vma)
 	unsigned long size, off;
 	struct page *page;
 	unsigned long flags;
-	unsigned long *area;
+	void *area;
 
 	spin_lock_irqsave(&kcov->lock, flags);
 	size = kcov->size * sizeof(unsigned long);