* Re: [PATCH v3 1/9] kernel/api: introduce kernel API specification framework
From: Nicolas Schier @ 2026-04-29 16:32 UTC (permalink / raw)
To: Nathan Chancellor
Cc: Sasha Levin, linux-api, linux-kernel, linux-doc, linux-fsdevel,
linux-kbuild, linux-kselftest, workflows, tools, x86,
Thomas Gleixner, Paul E . McKenney, Greg Kroah-Hartman,
Jonathan Corbet, Dmitry Vyukov, Randy Dunlap, Cyril Hrubis,
Kees Cook, Jake Edge, David Laight, Askar Safin, Gabriele Paoloni,
Mauro Carvalho Chehab, Christian Brauner, Alexander Viro,
Andrew Morton, Masahiro Yamada, Shuah Khan, Ingo Molnar,
Arnd Bergmann
In-Reply-To: <177726106581.2478607.12645653803520391071.b4-review@b4>
On Sun, Apr 26, 2026 at 11:37:45PM -0400, Nathan Chancellor wrote:
> On Fri, 24 Apr 2026 12:51:21 -0400, Sasha Levin <sashal@kernel.org> wrote:
> > diff --git a/kernel/Makefile b/kernel/Makefile
> > index 6785982013dc..564315153643 100644
> > --- a/kernel/Makefile
> > +++ b/kernel/Makefile
> > @@ -59,6 +59,9 @@ obj-y += dma/
> > obj-y += entry/
> > obj-y += unwind/
> > obj-$(CONFIG_MODULES) += module/
> > +obj-$(CONFIG_KAPI_SPEC) += api/
> > +# Ensure api/ is always cleaned even when CONFIG_KAPI_SPEC is not set
> > +obj- += api/
>
> If $(CONFIG_KAPI_SPEC) is not set, shouldn't
>
> obj-$(CONFIG_KAPI_SPEC) += api/
>
> evaluate to
>
> obj- += api/
>
> anyways? Why the duplication? This is the only place in the kernel where
> this would be needed?
yes, this is definitely not needed, as obj- is always evaluated during
'make clean', cp. scripts/Makefile.clean [1].
Kind regards
Nicolas
[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/scripts/Makefile.clean?h=v7.1-rc1#n30
^ permalink raw reply
* Re: [PATCH v3 1/9] kernel/api: introduce kernel API specification framework
From: Nicolas Schier @ 2026-04-29 16:43 UTC (permalink / raw)
To: Sasha Levin
Cc: linux-api, linux-kernel, linux-doc, linux-fsdevel, linux-kbuild,
linux-kselftest, workflows, tools, x86, Thomas Gleixner,
Paul E . McKenney, Greg Kroah-Hartman, Jonathan Corbet,
Dmitry Vyukov, Randy Dunlap, Cyril Hrubis, Kees Cook, Jake Edge,
David Laight, Askar Safin, Gabriele Paoloni,
Mauro Carvalho Chehab, Christian Brauner, Alexander Viro,
Andrew Morton, Masahiro Yamada, Shuah Khan, Ingo Molnar,
Arnd Bergmann
In-Reply-To: <20260424165130.2306833-2-sashal@kernel.org>
On Fri, Apr 24, 2026 at 12:51:21PM -0400, Sasha Levin wrote:
...
> diff --git a/kernel/Makefile b/kernel/Makefile
> index 6785982013dce..5643151536439 100644
> --- a/kernel/Makefile
> +++ b/kernel/Makefile
> @@ -59,6 +59,9 @@ obj-y += dma/
> obj-y += entry/
> obj-y += unwind/
> obj-$(CONFIG_MODULES) += module/
> +obj-$(CONFIG_KAPI_SPEC) += api/
> +# Ensure api/ is always cleaned even when CONFIG_KAPI_SPEC is not set
> +obj- += api/
>
> obj-$(CONFIG_KCMP) += kcmp.o
...
> diff --git a/kernel/api/Makefile b/kernel/api/Makefile
> new file mode 100644
> index 0000000000000..c0a13fc590e4a
> --- /dev/null
> +++ b/kernel/api/Makefile
> @@ -0,0 +1,14 @@
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Makefile for the Kernel API Specification Framework
> +#
> +
> +# Core API specification framework
> +obj-$(CONFIG_KAPI_SPEC) += kernel_api_spec.o
Bike-shedding: I'd use 'obj-y' here, to state clearly that
kernel_api_spec.c is the core part in the kernel/api/ subdir. If
CONFIG_KAPI_SPEC is unset, the subfir will not be entered at all.
--
Nicolas
^ permalink raw reply
* Re: [PATCH v3 2/9] kernel/api: enable kerneldoc-based API specifications
From: Nicolas Schier @ 2026-04-30 14:47 UTC (permalink / raw)
To: Sasha Levin
Cc: linux-api, linux-kernel, linux-doc, linux-fsdevel, linux-kbuild,
linux-kselftest, workflows, tools, x86, Thomas Gleixner,
Paul E . McKenney, Greg Kroah-Hartman, Jonathan Corbet,
Dmitry Vyukov, Randy Dunlap, Cyril Hrubis, Kees Cook, Jake Edge,
David Laight, Askar Safin, Gabriele Paoloni,
Mauro Carvalho Chehab, Christian Brauner, Alexander Viro,
Andrew Morton, Masahiro Yamada, Shuah Khan, Ingo Molnar,
Arnd Bergmann
In-Reply-To: <20260424165130.2306833-3-sashal@kernel.org>
On Fri, Apr 24, 2026 at 12:51:22PM -0400, Sasha Levin wrote:
> This patch adds support for extracting API specifications from
> kernel-doc comments and generating C macro invocations for the
> kernel API specification framework.
>
> Changes include:
> - New kdoc_apispec.py module for generating API spec macros
> - Updates to kernel-doc.py to support -apispec output format
> - Build system integration in Makefile.build
> - Generator script for collecting all API specifications
> - Support for API-specific sections in kernel-doc comments
>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
> Documentation/dev-tools/kernel-api-spec.rst | 11 +
> scripts/Makefile.build | 31 +
> scripts/Makefile.clean | 3 +
> tools/docs/kernel-doc | 5 +
> tools/lib/python/kdoc/kdoc_apispec.py | 1249 +++++++++++++++++++
> tools/lib/python/kdoc/kdoc_output.py | 9 +-
> tools/lib/python/kdoc/kdoc_parser.py | 86 +-
> 7 files changed, 1389 insertions(+), 5 deletions(-)
> create mode 100644 tools/lib/python/kdoc/kdoc_apispec.py
>
> diff --git a/Documentation/dev-tools/kernel-api-spec.rst b/Documentation/dev-tools/kernel-api-spec.rst
> index 395c2294d5209..479bc78797ba8 100644
> --- a/Documentation/dev-tools/kernel-api-spec.rst
> +++ b/Documentation/dev-tools/kernel-api-spec.rst
> @@ -239,6 +239,17 @@ execution context, and return values. Parameter violations are reported via
> ``pr_warn_ratelimited`` and return value violations via ``WARN_ONCE`` to avoid
> flooding the kernel log.
>
> +.. warning::
> +
> + Userspace errno is affected when this option is on. For syscalls that
> + violate their parameter specification, KAPI short-circuits the call and
> + returns ``-EINVAL`` from the validator **before** the real handler runs.
> + That errno can differ from what the real handler would have produced for
> + the same condition (for example, ``-ENOMEM`` from an allocation path or
> + ``-EFAULT`` from a deeper copy-in). ``CONFIG_KAPI_RUNTIME_CHECKS`` is a
> + debug-only option; do not enable it on production kernels or in
> + userspace-visible test environments where error-code fidelity matters.
> +
> Custom Validators
> -----------------
>
> diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> index 3652b85be5459..ef203e490c797 100644
> --- a/scripts/Makefile.build
> +++ b/scripts/Makefile.build
> @@ -174,6 +174,37 @@ ifneq ($(KBUILD_EXTRA_WARN),)
> endif
> endif
>
> +# Generate API spec headers from kernel-doc comments
> +ifeq ($(CONFIG_KAPI_SPEC),y)
> +# Function to check if a file has API specifications
> +has-apispec = $(shell grep -qE '^\s*\*\s*context-flags:' $(src)/$(1) 2>/dev/null && echo $(1))
> +
> +# Get base names without directory prefix
> +c-objs-base := $(notdir $(real-obj-y) $(real-obj-m))
> +# Filter to only .o files with corresponding .c source files
> +c-files := $(foreach o,$(c-objs-base),$(if $(wildcard $(src)/$(o:.o=.c)),$(o:.o=.c)))
Looks to me as if the two lines above are redundant, since 'find'
(below) will find all files gathered in $(c-files).
> +# Also check for any additional .c files that contain API specs but are included
> +extra-c-files := $(shell find $(src) -maxdepth 1 -name "*.c" -exec grep -l '^\s*\*\s*\(long-desc\|context-flags\|state-trans\):' {} \; 2>/dev/null | xargs -r basename -a)
> +# Combine both lists and remove duplicates
> +all-c-files := $(sort $(c-files) $(extra-c-files))
> +# Only include files that actually have API specifications
> +apispec-files := $(foreach f,$(all-c-files),$(call has-apispec,$(f)))
> +# Generate apispec targets with proper directory prefix
> +apispec-y := $(addprefix $(obj)/,$(apispec-files:.c=.apispec.h))
To goal is to find any relevant C file in $(src)/ (but not deeper below)
that holds KAPI documentation, right?
I do not like the find call, as it picks up anything. Might it make
sense to evaluate $(obj-) along with $(obj-y) and $(obj-m) to pick up
all C files that are references in kbuild?
# in top definition block -- before 'include $(kbuild-file)' et al.
obj- :=
# below the definitions of real-obj-{y,m}
real-obj-any := $(call real-search, $(obj-y) $(obj-m) $(obj-), .o, -objs -y -m -)
has-apispec = $(shell grep -lE '^\s*\*\s*context-flags:' $(1) 2>/dev/null)
apispec-y := $(patsubst $(src)/%.c, $(obj)/%.apispec.h, $(call has-apispec,
$(patsubst $(obj)/%.o, $(src)/%.c, $(real-obj-any))))
#...
# Source files that include their own apispec.h need to depend on it
$(apispec-y:.apispec.h=.o): $(obj)/%.o: $(obj)/%.apispec.h
(untested)
> +always-y += $(apispec-y)
> +targets += $(apispec-y)
> +
> +quiet_cmd_apispec = APISPEC $@
> + cmd_apispec = PYTHONDONTWRITEBYTECODE=1 $(KERNELDOC) -apispec \
> + $(KDOCFLAGS) $< > $@ || rm -f $@
> +
> +$(obj)/%.apispec.h: $(src)/%.c $(KERNELDOC) FORCE
> + $(call if_changed,apispec)
> +
> +# Source files that include their own apispec.h need to depend on it
> +$(foreach f,$(apispec-files),$(eval $(obj)/$(f:.c=.o): $(obj)/$(f:.c=.apispec.h)))
> +endif
> +
> # Compile C sources (.c)
> # ---------------------------------------------------------------------------
>
> diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
> index 6ead00ec7313b..f78dbbe637f27 100644
> --- a/scripts/Makefile.clean
> +++ b/scripts/Makefile.clean
> @@ -35,6 +35,9 @@ __clean-files := $(filter-out $(no-clean-files), $(__clean-files))
>
> __clean-files := $(wildcard $(addprefix $(obj)/, $(__clean-files)))
>
> +# Also clean generated apispec headers (computed dynamically in Makefile.build)
> +__clean-files += $(wildcard $(obj)/*.apispec.h)
We have a list of wildcard clean patterns in top-level Makefile
(line 2114 ff.); please add '*.apispec.h' there instead.
When I apply the series on top of v7.1, compilation fails with
../fs/open.c:2148:10: fatal error: open.apispec.h: No such file or directory
../fs/read_write.c:2519:10: fatal error: read_write.apispec.h: No such file or directory
Kind regards,
Nicolas
^ permalink raw reply
* Re: [PATCH v4 1/3] Documentation: adopt new coding style of type-aware kmalloc-family
From: Manuel Ebner @ 2026-05-01 9:12 UTC (permalink / raw)
To: SeongJae Park
Cc: Jonathan Corbet, Shuah Khan, linux-doc, Kees Cook, linux-kernel,
workflows, linux-sound, linux-media, linux-mm
In-Reply-To: <20260430010013.113971-1-sj@kernel.org>
On Wed, 2026-04-29 at 18:00 -0700, SeongJae Park wrote:
> On Wed, 29 Apr 2026 17:53:36 -0700 SeongJae Park <sj@kernel.org> wrote:
>
> > On Wed, 29 Apr 2026 09:14:44 +0200 Manuel Ebner <manuelebner@mailbox.org>
> > wrote:
> >
> > > Update the documentation to reflect new type-aware kmalloc-family as
> > > suggested in commit 2932ba8d9c99 ("slab: Introduce kmalloc_obj()
> > > and family")
> > >
> > > ptr = kmalloc(sizeof(*ptr), gfp);
> > > -> ptr = kmalloc_obj(*ptr);
> > > ptr = kmalloc(sizeof(struct some_obj_name), gfp);
> > > -> ptr = kmalloc_obj(*ptr);
> > > ptr = kzalloc(sizeof(*ptr), gfp);
> > > -> ptr = kzalloc_obj(*ptr);
> > > ptr = kmalloc_array(count, sizeof(*ptr), gfp);
> > > -> ptr = kmalloc_objs(*ptr, count);
> > > ptr = kcalloc(count, sizeof(*ptr), gfp);
> > > -> ptr = kzalloc_objs(*ptr, count);
>
> Forgot asking this, sorry. Shouldn't 'gfp' parameters be kept?
Yes, i should have kept it, like so:
eg. ptr = kmalloc_obj(*ptr, gfp);
-> ptr = kmalloc_obj(*ptr [, gfp] );
same in [Patch 2/3]
> >
> > > Signed-off-by: Manuel Ebner <manuelebner@mailbox.org>
> >
> > Acked-by: SeongJae Park <sj@kernel.org>
>
> My Acked-by: is still valid regardless of your answer to my trivial question.
Thanks
Manuel
>
> Thanks,
> SJ
>
> [...]
^ permalink raw reply
* Re: [PATCH v4 3/3] Documentation: deprecated.rst: kmalloc-family: mark argument as optional
From: Manuel Ebner @ 2026-05-01 9:19 UTC (permalink / raw)
To: SeongJae Park
Cc: Jonathan Corbet, Shuah Khan, linux-doc, Kees Cook, linux-kernel,
workflows, linux-mm, Geert Uytterhoeven
In-Reply-To: <20260430010332.114100-1-sj@kernel.org>
On Wed, 2026-04-29 at 18:03 -0700, SeongJae Park wrote:
> On Wed, 29 Apr 2026 09:27:04 +0200 Manuel Ebner <manuelebner@mailbox.org>
> wrote:
>
> > put the optional argument (gfp) in square brackets
> > add default value = GFP_KERNEL
> >
> > eg. ptr = kmalloc_obj(*ptr, gfp);
> > -> ptr = kmalloc_obj(*ptr [, gfp] );
> >
> > Signed-off-by: Manuel Ebner <manuelebner@mailbox.org>
>
> I have a trivial question below, but because it is trivial,
>
> Acked-by: SeongJae Park <sj@kernel.org>
>
> > ---
> > Documentation/process/deprecated.rst | 15 ++++++++-------
> > 1 file changed, 8 insertions(+), 7 deletions(-)
> >
> > diff --git a/Documentation/process/deprecated.rst
> > b/Documentation/process/deprecated.rst
> > index fed56864d036..ac75b7ecac47 100644
> > --- a/Documentation/process/deprecated.rst
> > +++ b/Documentation/process/deprecated.rst
> > @@ -392,13 +392,14 @@ allocations. For example, these open coded
> > assignments::
> >
> > become, respectively::
> >
> > - ptr = kmalloc_obj(*ptr, gfp);
> > - ptr = kzalloc_obj(*ptr, gfp);
> > - ptr = kmalloc_objs(*ptr, count, gfp);
> > - ptr = kzalloc_objs(*ptr, count, gfp);
> > - ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
> > - __auto_type ptr = kmalloc_obj(struct foo, gfp);
> > -
> > + ptr = kmalloc_obj(*ptr [, gfp] );
> > + ptr = kzalloc_obj(*ptr [, gfp] );
> > + ptr = kmalloc_objs(*ptr, count [, gfp] );
> > + ptr = kzalloc_objs(*ptr, count [, gfp] );
> > + ptr = kmalloc_flex(*ptr, flex_member, count [, gfp] );
> > + __auto_type ptr = kmalloc_obj(struct foo [, gfp] );
> > +
> > +The argument gfp is optional, the default value is GFP_KERNEL.
> > If `ptr->flex_member` is annotated with __counted_by(), the allocation
> > will automatically fail if `count` is larger than the maximum
> > representable value that can be stored in the counter member associated
>
> Like 'ptr->flex_member' and 'count', why don't you enclose 'gfp' and
> 'GFP_KERNEL' with backticks ('`')?
I didn't know what ` is doing, so didn't consider it. It makes sense to
enclose these two.
should __counted_by() be enclosed aswell?
> Thanks,
> SJ
Thanks
Manuel
---
The possibility of getting blamed has to be earned.
^ permalink raw reply
* Re: [PATCH 2/3] Documentation: security-bugs: explain what is and is not a security bug
From: Willy Tarreau @ 2026-05-01 13:57 UTC (permalink / raw)
To: Greg KH
Cc: leon, security, Jonathan Corbet, skhan, workflows, linux-doc,
linux-kernel
In-Reply-To: <2026042945-duress-extenuate-939f@gregkh>
Hi Greg,
On Wed, Apr 29, 2026 at 12:10:51AM -0600, Greg KH wrote:
> On Wed, Apr 29, 2026 at 05:09:43AM +0200, Willy Tarreau wrote:
> > On Tue, Apr 28, 2026 at 03:13:01PM -0600, Greg KH wrote:
> > > > > We can point at other files, as this list is going to get long over
> > > > > time, which is a good thing.
> > > >
> > > > Sure. I'm just unsure where this could be enumerated, as it's likely
> > > > that there would be just one or two lines max per subsystem for the
> > > > majority of them. Or we could have a totally separate file, "threat
> > > > model", that goes into great lengths detailing all this with sections
> > > > per category or subsystem when they start to grow maybe, and refer only
> > > > to that one from security-bugs ?
> > >
> > > I think a separate file is good, I know I need to write up what the USB
> > > model is, and it's different from PCI, and different from other
> > > subsystems. All should probably be documented eventually.
> >
> > Would you be interested in me trying to initiate a new "threat-model.rst"
> > file that tries to unroll the points mentioned in the list ? I'm concerned
> > that that withuot having many details initially, it could look a bit odd,
> > because the list we currently have would be more suitable for an "other"
> > section.
>
> Sure, a small file to start with would be good for people to work off
> of and add to.
I'm appending below what I came up with today. It's not a patch, just
a dump of what I've been typing for 3 hours and should go into
process/threat-model.rst I think. If you think it constitutes a good
starting point, then I can make a patch to add it, and update my other
patch to reference it by basically saying "what is excluded from the
kernel threat model in threat-model.rst does not have to be reported
as a security issue".
cheers,
Willy
---
.. _threatmodel:
The Linux Kernel threat model
=============================
There are a lot of assumptions regarding what the kernel protects against and
what it does not protect against. These assumptions tend to cause confusion for
bug reports (security-related ones vs non-security ones), and can complicate
security enforcement when the responsibilities for some boundaries is not clear
between the kernel, distros, administrators and users.
This document tries to clarify the responsibilities of the kernel in this
domain.
The kernel's responsibilities
-----------------------------
The kernel abstracts access to local hardware resources and to remote systems
in a way that allows multiple local users to get a fair share of the available
resources granted to them, and, when the underlying hardware permits, to assign
a level of confidentiality to their communications and to the data they are
processing or storing.
The kernel assumes that the underlying hardware behaves according to its
specifications. This includes the integrity of the CPU's instruction set, the
transparency of the branch prediction unit and the cache units, the consistency
of the Memory Management Unit (MMU), the isolation of DMA-capable peripherals
(e.g., via IOMMU), state transitions in controllers, ranges of values read from
registers, the respect of documented hardware limitations, etc.
When hardware fails to maintain its specified isolation (e.g., CPU bugs,
side-channels, hardware response to unexpected inputs), the kernel will usually
attempt to implement reasonable mitigations. These are best-effort measures
intended to reduce the attack surface or elevate the cost of an attack within
the limits of the hardware's facilities; they do not constitute a
kernel-provided safety guarantee.
Users always perform their activities under the authority of an administrator
who is able to grant or deny various types of permissions that may affect how
users benefit from available resources, or the level of confidentiality of
their activities. Administrators may also delegate all or part of their own
permissions to some users, particularly via capabilities but not only. All this
is performed via configuration (sysctl, file-system permissions etc).
The Linux Kernel applies a certain collection of default settings that match
its threat model. Distros have their own threat model and will come with their
own configuration presets, that the administrator may have to adjust to better
suit their expectations (relax or restrict).
By default, the Linux Kernel guarantees the following protections when running
on common processors featuring privilege levels and memory management units:
- user-based isolation: an unprivileged user may restrict access to their own
data from other unprivileged users running on the same system. This includes:
* stored data, via file system permissions
* in-memory data (pages are not accessible by default to other users)
* process activity (ptrace is not permitted to other users)
* inter-process communication (other users may not observe data exchanged via
UNIX domain sockets or other IPC mechanisms)
* network communications within the same or with other systems
- capability-based protection:
* users not having the CAP_SYS_ADMIN capability may not alter the kernel's
configuration, memory nor state, change other users' view of the file
system layout, grant any user capabilities they do not have, nor affect the
system's availability (shutdown, reboot, panic, hang, or making the system
unresponsive via unbounded resource exhaustion).
* users not having the CAP_NET_ADMIN capability may not alter the network
configuration, intercept nor spoof network communications from other
users nor systems.
* users not having CAP_SYS_PTRACE may not observe other users' processes
activities.
When CONFIG_USER_NS is set, the kernel also permits unprivileged users to
create their own user namespace in which they have all capabilities, but with a
number of restrictions (they may not perform actions that have impacts on the
initial user namespace, such as changing time, loading modules or mounting
block devices). Please refer to user_namespaces(7) for more details, the
possibilities of user namespaces are not covered in this document.
The kernel also offers a lot of troubleshooting and debugging facilities, which
can constitute attack vectors when placed in wrong hands. While some of them
are designed to be accessible to regular local users with a low risk (e.g.
kernel logs via /proc/kmsg), some would expose enough information to represent
a risk in most places and the decision to expose them is under the
administrator's responsibility (perf events, traces), and others are not
designed to be accessed by non-privileged users (e.g. debugfs). Access to these
facilities by a user who has been explicitly granted permission by an
administrator does not constitute a security breach.
Bugs that permit to violate the principles above constitute security breaches.
However, bugs that permit one violation only once another one was already
achieved are only weaknesses. The kernel applies a number of self-protection
measures whose purpose is to avoid crossing a security boundary when certain
classes of bugs are found, but a failure of these extra protections do not
constitute a vulnerability alone.
What does not constitute a security bug
--------------------------------------
In the Linux kernel's threat model, the following classes of problems are
**NOT** considered as Linux Kernel security bugs. However, when it is believed
that the kernel could do better, they should be reported, so that they can be
reviewed and fixed where reasonably possible, but they will be handled as any
regular bug:
- configuration:
* outdated kernels and particularly end-of-life branches are out of the scope
of the kernel's threat model: administrators are responsible for keeping
their system up to date. For a bug to qualify as a security bug, it must be
demonstrated that it affects actively maintained versions.
* build-level: changes to the kernel configuration that are explicitly
documented as lowering the security level (e.g. CONFIG_NOMMU), or targeted
at developers only.
* OS-level: changes to command line parameters, sysctls, filesystem
permissions, user capabilities, exposure of privileged interfaces, that
explicitly increase exposure by either offering non-default access to
unprivileged users, or reduce the kernel's ability to enforce some
protections or mitigations. Example: write access to procfs or debugfs.
* issues triggered only when using features intended for development or
debugging (e.g., lockdep, KASAN, fault-injection): these features are known
to introduce overhead and potential instability and are not intended for
production use.
* loading of explicitly insecure/broken/staging modules, and generally any
using any subsystem marked as experimental or not intended for production
use.
* running out-of-tree modules or unofficial kernel forks; these should be
reported to the relevant vendor.
- excess of initial privileges:
* actions performed by a user already possessing the privileges required to
perform that action or modify that state (e.g. CAP_SYS_ADMIN, CAP_NET_ADMIN,
CAP_SYS_RAWIO, CAP_SYS_MODULE with no further boundary being crossed).
* actions performed in user namespace without permitting anything in the
initial namespace that was not already permitted to the same user there.
* anything performed by the root user in the initial namespace (e.g. kernel
oops when writing to a privileged device).
- out of production use:
This covers theoretical/probabilistic attacks that rely on laboratory
conditions with zero system noise, or those requiring an unrealistic number
of attempts (e.g., billions of trials) that would be detected by standard
system monitoring long before success, such as:
* prediction of random numbers that only works in a totally silent
environment (such as IP ID, TCP ports or sequence numbers that can only be
guessed in a lab).
* activity observation and information leaks based on probabilistic
approaches that are prone to measurement noise and not realistically
reproducible on a production system.
* issues that can only be triggered by heavy attacks (e.g. brute force) whose
impact on the system makes it unlikely or impossible to remain undetected
before they succeed (e.g. consuming all memory before succeeding).
* problems seen only under development simulators, emulators, or combinations
that do not exist on real systems at the time of reporting (issues
involving tens of millions of threads, tens of thousands of CPUs,
unrealistic CPU frequencies, RAM sizes or disk capacities, network speeds.
* issues whose reproduction requires hardware modification or emulation,
including fake USB devices that pretend to be another one.
* as well as issues that can be triggered at a cost that is orders of
magnitude higher than the expected benefits (e.g. fully functional keyboard
emulator only to retrieve 7 uninitialized bytes in a structure, or
brute-force method involving millions of connection attempts to guess a
port number).
- hardening failures:
* ability to bypass some of the kernel's hardening measures with no
demonstrable exploit path (e.g. ASLR bypass, events timing or probing with
no demonstrable consequence). These are just weaknesses, not
vulnerabilities.
* missing argument checks and failure to report certain errors with no
immediate consequence.
- random information leaks:
This concerns information leaks of small data parts that happen to be there
and that cannot be chosen by the attacker, or face access restrictions:
* structure padding reported by syscalls or other interfaces.
* identifiers, partial data, non-terminated strings reported in error
messages.
* Leaks of kernel memory addresses/pointers do not constitute an immediately
exploitable vector and are not security bugs, though they must be reported
and fixed.
- crafted file system images:
* bugs triggered by mounting a corrupted or maliciously crafted file system
image are generally not security bugs, as the kernel assumes the underlying
storage media is under the administrator's control, unless the filesystem
driver is specifically documented as being hardened against untrusted media.
* issues that are resolved, mitigated, or detected by running a filesystem
consistency check (fsck) on the image prior to mounting.
- physical access:
Issues that require physical access to the machine, hardware modification, or
the use of specialized hardware (e.g., logic analyzers, DMA-attack tools over
PCI-E/Thunderbolt) are out of scope unless the system is explicitly
configured with technologies meant to defend against such attacks
(e.g. IOMMU).
- functional and performance regressions:
Any issue that can be mitigated by setting proper permissions and limits
doesn't qualify as a security bug.
---
^ permalink raw reply
* [PATCH v2] kunit: tool: Add (primitive) support for outputting JUnit XML
From: David Gow @ 2026-05-02 2:49 UTC (permalink / raw)
To: Brendan Higgins, Rae Moar, Shuah Khan, Thomas Weißschuh
Cc: David Gow, kunit-dev, linux-kernel, workflows
This is used by things like Jenkins and other CI systems, which can
pretty-print the test output and potentially provide test-level comparisons
between runs.
The implementation here is pretty basic: it only provides the raw results,
split into tests and test suites, and doesn't provide any overall metadata.
However, CI systems like Jenkins can injest it and it is already useful.
Signed-off-by: David Gow <david@davidgow.net>
---
Finally got around to doing a new version of this. I'm running this
locally with Jenkins, and it's giving nice summaries of test results.
Changes since v1:
https://lore.kernel.org/all/20260119073426.1952867-1-davidgow@google.com/
- Use python's provided XML quote escaping, rather than coding our own (Thanks Thomas)
- Output proper <skipped> tags for skipped tests
- Report crashed tests as <error>
- Don't output <system-out> tags if there are no lines of log data
---
Documentation/dev-tools/kunit/run_wrapper.rst | 3 ++
tools/testing/kunit/kunit.py | 25 ++++++++++-
tools/testing/kunit/kunit_junit.py | 43 +++++++++++++++++++
tools/testing/kunit/kunit_tool_test.py | 38 ++++++++++++++--
4 files changed, 105 insertions(+), 4 deletions(-)
create mode 100644 tools/testing/kunit/kunit_junit.py
diff --git a/Documentation/dev-tools/kunit/run_wrapper.rst b/Documentation/dev-tools/kunit/run_wrapper.rst
index 770bb09a475a..cecc110a3399 100644
--- a/Documentation/dev-tools/kunit/run_wrapper.rst
+++ b/Documentation/dev-tools/kunit/run_wrapper.rst
@@ -324,6 +324,9 @@ command line arguments:
- ``--json``: If set, stores the test results in a JSON format and prints to `stdout` or
saves to a file if a filename is specified.
+- ``--junit``: If set, stores the test results in JUnit XML format and prints to `stdout` or
+ saves to a file if a filename is specified.
+
- ``--filter``: Specifies filters on test attributes, for example, ``speed!=slow``.
Multiple filters can be used by wrapping input in quotes and separating filters
by commas. Example: ``--filter "speed>slow, module=example"``.
diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
index 742f5c555666..1a7ff594b791 100755
--- a/tools/testing/kunit/kunit.py
+++ b/tools/testing/kunit/kunit.py
@@ -21,6 +21,7 @@ from enum import Enum, auto
from typing import Iterable, List, Optional, Sequence, Tuple
import kunit_json
+import kunit_junit
import kunit_kernel
import kunit_parser
from kunit_printer import stdout, null_printer
@@ -49,6 +50,7 @@ class KunitBuildRequest(KunitConfigRequest):
class KunitParseRequest:
raw_output: Optional[str]
json: Optional[str]
+ junit: Optional[str]
summary: bool
failed: bool
@@ -268,6 +270,17 @@ def parse_tests(request: KunitParseRequest, metadata: kunit_json.Metadata, input
stdout.print_with_timestamp("Test results stored in %s" %
os.path.abspath(request.json))
+ if request.junit:
+ junit_str = kunit_junit.get_junit_result(
+ test=test)
+ if request.junit == 'stdout':
+ print(junit_str)
+ else:
+ with open(request.junit, 'w') as f:
+ f.write(junit_str)
+ stdout.print_with_timestamp("Test results stored in %s" %
+ os.path.abspath(request.junit))
+
if test.status != kunit_parser.TestStatus.SUCCESS:
return KunitResult(KunitStatus.TEST_FAILURE, parse_time), test
@@ -309,6 +322,7 @@ def run_tests(linux: kunit_kernel.LinuxSourceTree,
# So we hackily automatically rewrite --json => --json=stdout
pseudo_bool_flag_defaults = {
'--json': 'stdout',
+ '--junit': 'stdout',
'--raw_output': 'kunit',
}
def massage_argv(argv: Sequence[str]) -> Sequence[str]:
@@ -459,6 +473,11 @@ def add_parse_opts(parser: argparse.ArgumentParser) -> None:
help='Prints parsed test results as JSON to stdout or a file if '
'a filename is specified. Does nothing if --raw_output is set.',
type=str, const='stdout', default=None, metavar='FILE')
+ parser.add_argument('--junit',
+ nargs='?',
+ help='Prints parsed test results as JUnit XML to stdout or a file if '
+ 'a filename is specified. Does nothing if --raw_output is set.',
+ type=str, const='stdout', default=None, metavar='FILE')
parser.add_argument('--summary',
help='Prints only the summary line for parsed test results.'
'Does nothing if --raw_output is set.',
@@ -502,6 +521,7 @@ def run_handler(cli_args: argparse.Namespace) -> None:
jobs=cli_args.jobs,
raw_output=cli_args.raw_output,
json=cli_args.json,
+ junit=cli_args.junit,
summary=cli_args.summary,
failed=cli_args.failed,
timeout=cli_args.timeout,
@@ -552,6 +572,7 @@ def exec_handler(cli_args: argparse.Namespace) -> None:
exec_request = KunitExecRequest(raw_output=cli_args.raw_output,
build_dir=cli_args.build_dir,
json=cli_args.json,
+ junit=cli_args.junit,
summary=cli_args.summary,
failed=cli_args.failed,
timeout=cli_args.timeout,
@@ -580,7 +601,9 @@ def parse_handler(cli_args: argparse.Namespace) -> None:
# We know nothing about how the result was created!
metadata = kunit_json.Metadata()
request = KunitParseRequest(raw_output=cli_args.raw_output,
- json=cli_args.json, summary=cli_args.summary,
+ json=cli_args.json,
+ junit=cli_args.junit,
+ summary=cli_args.summary,
failed=cli_args.failed)
result, _ = parse_tests(request, metadata, kunit_output)
if result.status != KunitStatus.SUCCESS:
diff --git a/tools/testing/kunit/kunit_junit.py b/tools/testing/kunit/kunit_junit.py
new file mode 100644
index 000000000000..f5b5080ad715
--- /dev/null
+++ b/tools/testing/kunit/kunit_junit.py
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Generates JUnit XML files from KUnit test results
+#
+# Copyright (C) 2026, Google LLC and David Gow.
+
+from xml.sax.saxutils import quoteattr
+from kunit_parser import Test, TestStatus
+
+# Get a string representing a tes suite (including subtests) in JUnit XML
+def get_test_suite(test: Test) -> str:
+ xml_output = '<testsuite name=' + quoteattr(test.name) + ' tests="' +\
+ str(test.counts.total()) + '" failures="' + str(test.counts.failed) +\
+ '" skipped="' + str(test.counts.skipped) + '" errors="' + str(test.counts.crashed + test.counts.errors) + '">\n'
+
+ for subtest in test.subtests:
+ if subtest.subtests:
+ xml_output += get_test_suite(subtest)
+ continue
+ xml_output += '<testcase name=' + quoteattr(subtest.name) + '>\n'
+ if subtest.status == TestStatus.FAILURE:
+ xml_output += '<failure>Test Failed</failure>\n'
+ elif subtest.status == TestStatus.SKIPPED:
+ xml_output += '<skipped>Test Skipped</skipped>\n'
+ elif subtest.status == TestStatus.TEST_CRASHED:
+ xml_output += '<error>Test Crashed</error>\n'
+
+ if subtest.log:
+ xml_output +=\
+ '<system-out><![CDATA[' + "\n".join(subtest.log) + ']]></system-out>\n'
+
+ xml_output += '</testcase>\n'
+
+ xml_output += '</testsuite>\n\n'
+
+ return xml_output
+
+# Get a string for an entire XML file for the test structure starting at test
+def get_junit_result(test: Test) -> str:
+ xml_output = '<?xml version="1.0" encoding="UTF-8" ?>\n\n'
+
+ xml_output += get_test_suite(test)
+ return xml_output
diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py
index 267c33cecf87..f8a77d7fab38 100755
--- a/tools/testing/kunit/kunit_tool_test.py
+++ b/tools/testing/kunit/kunit_tool_test.py
@@ -24,6 +24,7 @@ import kunit_config
import kunit_parser
import kunit_kernel
import kunit_json
+import kunit_junit
import kunit
from kunit_printer import stdout
@@ -676,6 +677,37 @@ class StrContains(str):
def __eq__(self, other):
return self in other
+class KUnitJUnitTest(unittest.TestCase):
+ def setUp(self):
+ self.print_mock = mock.patch('kunit_printer.Printer.print').start()
+ self.addCleanup(mock.patch.stopall)
+
+ def _junit_string(self, log_file):
+ with open(_test_data_path(log_file)) as file:
+ test_result = kunit_parser.parse_run_tests(file, stdout)
+ junit_string = kunit_junit.get_junit_result(
+ test=test_result)
+ return junit_string
+
+ def test_failed_test_junit(self):
+ result = self._junit_string('test_is_test_passed-failure.log')
+ self.assertTrue("<failure>" in result)
+
+ def test_skipped_test_junit(self):
+ result = self._junit_string('test_skip_tests.log')
+ self.assertTrue("<skipped>" in result)
+ self.assertTrue("skipped=\"1\"" in result)
+
+ def test_crashed_test_junit(self):
+ result = self._junit_string('test_kernel_panic_interrupt.log')
+ self.assertTrue("<error>" in result);
+
+ def test_no_tests_junit(self):
+ result = self._junit_string('test_is_test_passed-no_tests_run_with_header.log')
+ self.assertTrue("tests=\"0\"" in result)
+ self.assertFalse("testcase" in result)
+
+
class KUnitMainTest(unittest.TestCase):
def setUp(self):
path = _test_data_path('test_is_test_passed-all_passed.log')
@@ -923,7 +955,7 @@ class KUnitMainTest(unittest.TestCase):
self.linux_source_mock.run_kernel.return_value = ['TAP version 14', 'init: random output'] + want
got = kunit._list_tests(self.linux_source_mock,
- kunit.KunitExecRequest(None, None, False, False, '.kunit', 300, 'suite*', '', None, None, 'suite', False, False, False))
+ kunit.KunitExecRequest(None, None, None, False, False, '.kunit', 300, 'suite*', '', None, None, 'suite', False, False, False))
self.assertEqual(got, want)
# Should respect the user's filter glob when listing tests.
self.linux_source_mock.run_kernel.assert_called_once_with(
@@ -936,7 +968,7 @@ class KUnitMainTest(unittest.TestCase):
# Should respect the user's filter glob when listing tests.
mock_tests.assert_called_once_with(mock.ANY,
- kunit.KunitExecRequest(None, None, False, False, '.kunit', 300, 'suite*.test*', '', None, None, 'suite', False, False, False))
+ kunit.KunitExecRequest(None, None, None, False, False, '.kunit', 300, 'suite*.test*', '', None, None, 'suite', False, False, False))
self.linux_source_mock.run_kernel.assert_has_calls([
mock.call(args=None, build_dir='.kunit', filter_glob='suite.test*', filter='', filter_action=None, timeout=300),
mock.call(args=None, build_dir='.kunit', filter_glob='suite2.test*', filter='', filter_action=None, timeout=300),
@@ -949,7 +981,7 @@ class KUnitMainTest(unittest.TestCase):
# Should respect the user's filter glob when listing tests.
mock_tests.assert_called_once_with(mock.ANY,
- kunit.KunitExecRequest(None, None, False, False, '.kunit', 300, 'suite*', '', None, None, 'test', False, False, False))
+ kunit.KunitExecRequest(None, None, None, False, False, '.kunit', 300, 'suite*', '', None, None, 'test', False, False, False))
self.linux_source_mock.run_kernel.assert_has_calls([
mock.call(args=None, build_dir='.kunit', filter_glob='suite.test1', filter='', filter_action=None, timeout=300),
mock.call(args=None, build_dir='.kunit', filter_glob='suite.test2', filter='', filter_action=None, timeout=300),
--
2.54.0
^ permalink raw reply related
* Re: [PATCH 2/3] Documentation: security-bugs: explain what is and is not a security bug
From: Demi Marie Obenour @ 2026-05-02 5:20 UTC (permalink / raw)
To: Greg KH, Willy Tarreau
Cc: leon, security, Jonathan Corbet, skhan, workflows, linux-doc,
linux-kernel, Qubes Developer Mailing List
In-Reply-To: <2026042804-overbook-ripeness-73dd@gregkh>
[-- Attachment #1.1.1: Type: text/plain, Size: 5780 bytes --]
On 4/28/26 17:13, Greg KH wrote:
> On Mon, Apr 27, 2026 at 06:14:15PM +0200, Willy Tarreau wrote:
>> On Mon, Apr 27, 2026 at 09:35:04AM -0600, Greg KH wrote:
>>> On Mon, Apr 27, 2026 at 05:27:46PM +0200, Willy Tarreau wrote:
>>>> On Mon, Apr 27, 2026 at 07:48:23AM -0600, Greg KH wrote:
>>>>> On Sun, Apr 26, 2026 at 06:39:13PM +0200, Willy Tarreau wrote:
>>>>>> +In the Linux kernel's threat model, an issue is **not** a security bug, and
>>>>>> +should not be reported to the security list, when triggering it requires the
>>>>>> +reporter to first undermine the system they are attacking. This includes, but
>>>>>> +is not limited to, behavior that only manifests after the administrator has
>>>>>> +explicitly enabled it (loading a module, setting a sysctl, writing to a debugfs
>>>>>> +knob, or otherwise using an interface documented as privileged or unsafe); bugs
>>>>>> +reachable only through root or CAP_SYS_ADMIN or CAP_NET_ADMIN on a machine the
>>>>>> +actor already fully controls, with no further privilege boundary being crossed;
>>>>>> +prediction of random numbers that only works in a totally silent environment
>>>>>> +(such as IP ID, TCP ports or sequence numbers that can only be guessed in a
>>>>>> +lab), issues that appear only in debug, lockdep, KASAN, fault-injection,
>>>>>> +CONFIG_NOMMU, or other developer-oriented kernel builds that are not intended
>>>>>> +for production use; problems seen only under development simulators, emulators,
>>>>>> +or fuzzing harnesses that present hardware or input states which cannot occur
>>>>>> +on real systems; bugs that require modified or emulated hardware; missing
>>>>>> +hardening or defence-in-depth suggestions with no demonstrable exploit path
>>>>>> +(including local ASLR bypass); mounting file systems that would be fixed or
>>>>>> +rejected by fsck; and bugs in out-of-tree modules or vendor forks, which should
>>>>>> +be reported to the relevant vendor. Functional and performance regressions,
>>>>>> +and disagreements with documented kernel policy (for example, "root can load
>>>>>> +modules"), are likewise ordinary bugs or feature requests rather than security
>>>>>> +issues, and should be reported via the usual channels.
>>>>>
>>>>> This is a great list to start with, but perhaps we should put it in list
>>>>> form so that it's easier to read?
>>>>
>>>> In fact that's what I tried first and it was super long with many short
>>>> lines, making it possibly worse. But maybe aggregating several short
>>>> entries on a line by similarities could work, I can give it a try.
>>>>
>>>>> Also, I can see this turning into a separate document eventually as
>>>>> different subsystems should have a chance to weigh in on what they
>>>>> consider the threat model to be
>>>>
>>>> My fear if we redirect to other files is that it won't be read again.
>>>> However, we could possibly suggest to always look for the subsystem's
>>>> specific rules in this subsytem's doc, leaving enough freedom to
>>>> maintainers to reject more things.
>>>
>>> AI tools are good at following links, so I wouldn't worry about that.
>>
>> Yes but let's not forget the minority of humble humans still sending
>> honest reports ;-)
>>
>>> We can point at other files, as this list is going to get long over
>>> time, which is a good thing.
>>
>> Sure. I'm just unsure where this could be enumerated, as it's likely
>> that there would be just one or two lines max per subsystem for the
>> majority of them. Or we could have a totally separate file, "threat
>> model", that goes into great lengths detailing all this with sections
>> per category or subsystem when they start to grow maybe, and refer only
>> to that one from security-bugs ?
>
> I think a separate file is good, I know I need to write up what the USB
> model is, and it's different from PCI, and different from other
> subsystems. All should probably be documented eventually.
>
>>>>> (like what the IB subsystem does which I
>>>>> don't think you listed above, or the USB subsystem.)
>>>>
>>>> Indeed I didn't list IB (I'm never sure about it, I seem to remember
>>>> we simply trust any peer, is that right?), nor did I make specific
>>>> mentions for USB which is implicitly covered by "hardware emulation
>>>> or modification".
>>>
>>> Ah, but USB does cover "some" modification of devices, so this is going
>>> to be something that is good to document over time, if for no other
>>> reason to keep these scanning tools in check from hallucinating crazy
>>> situations that are obviously not a valid thing we care about.
>>
>> OK but does this mean you still want to get these reports in the end ?
>
> I want a patch if a user cares about that threat-model (as Android does
> but no one else) as it's up to the user groups that want to change the
> default kernel's behavior like this to actually submit patches to do so.
FYI, I don't think this is limited to Android. Chrome OS definitely
cares about malicious USB devices, and the whole purpose of USBGuard is
to prevent a USB device from being able to compromise the system unless
authorized. I believe Qubes OS also cares, as it supports USB device
assignment to virtual machines. CCing qubes-devel for confirmation.
What should that patch look like? Could there be a way for these user
groups to be informed of vulnerabilities in the USB subsystem, so that
they can take responsibility for fixing them before they become public?
It does make sense for those who care about the security of a subsystem
to be responsible for vulnerabilities in that system, but right now
I'm not sure how one would offer to take up that responsibility.
--
Sincerely,
Demi Marie Obenour (she/her/hers)
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 7253 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH 2/3] Documentation: security-bugs: explain what is and is not a security bug
From: Willy Tarreau @ 2026-05-02 5:35 UTC (permalink / raw)
To: Demi Marie Obenour
Cc: Greg KH, leon, security, Jonathan Corbet, skhan, workflows,
linux-doc, linux-kernel, Qubes Developer Mailing List
In-Reply-To: <1d3f8659-8c69-47f6-bb38-4c1d06cf8307@gmail.com>
Hi Demi Marie,
On Sat, May 02, 2026 at 01:20:10AM -0400, Demi Marie Obenour wrote:
> >>> Ah, but USB does cover "some" modification of devices, so this is going
> >>> to be something that is good to document over time, if for no other
> >>> reason to keep these scanning tools in check from hallucinating crazy
> >>> situations that are obviously not a valid thing we care about.
> >>
> >> OK but does this mean you still want to get these reports in the end ?
> >
> > I want a patch if a user cares about that threat-model (as Android does
> > but no one else) as it's up to the user groups that want to change the
> > default kernel's behavior like this to actually submit patches to do so.
> FYI, I don't think this is limited to Android. Chrome OS definitely
> cares about malicious USB devices, and the whole purpose of USBGuard is
> to prevent a USB device from being able to compromise the system unless
> authorized. I believe Qubes OS also cares, as it supports USB device
> assignment to virtual machines. CCing qubes-devel for confirmation.
>
> What should that patch look like? Could there be a way for these user
> groups to be informed of vulnerabilities in the USB subsystem, so that
> they can take responsibility for fixing them before they become public?
I've posted a proposal elsewhere in the same thread:
https://lore.kernel.org/lkml/afSxSX8RK0Z4kkOI@1wt.eu/
> It does make sense for those who care about the security of a subsystem
> to be responsible for vulnerabilities in that system, but right now
> I'm not sure how one would offer to take up that responsibility.
I think that at least some subsystems will want to add their own
restrictions based on the bug reports they keep receiving, and I hope
it can help distros figure where there's a gap between is promised to
users and what the kernel promises, that needs to be filled by userland
verification tools for example.
Willy
^ permalink raw reply
* Re: [PATCH 2/3] Documentation: security-bugs: explain what is and is not a security bug
From: Demi Marie Obenour @ 2026-05-02 5:51 UTC (permalink / raw)
To: Willy Tarreau
Cc: Greg KH, leon, security, Jonathan Corbet, skhan, workflows,
linux-doc, linux-kernel, Qubes Developer Mailing List
In-Reply-To: <afWNHZoN64fldbUK@1wt.eu>
[-- Attachment #1.1.1: Type: text/plain, Size: 3308 bytes --]
On 5/2/26 01:35, Willy Tarreau wrote:
> Hi Demi Marie,
>
> On Sat, May 02, 2026 at 01:20:10AM -0400, Demi Marie Obenour wrote:
>>>>> Ah, but USB does cover "some" modification of devices, so this is going
>>>>> to be something that is good to document over time, if for no other
>>>>> reason to keep these scanning tools in check from hallucinating crazy
>>>>> situations that are obviously not a valid thing we care about.
>>>>
>>>> OK but does this mean you still want to get these reports in the end ?
>>>
>>> I want a patch if a user cares about that threat-model (as Android does
>>> but no one else) as it's up to the user groups that want to change the
>>> default kernel's behavior like this to actually submit patches to do so.
>> FYI, I don't think this is limited to Android. Chrome OS definitely
>> cares about malicious USB devices, and the whole purpose of USBGuard is
>> to prevent a USB device from being able to compromise the system unless
>> authorized. I believe Qubes OS also cares, as it supports USB device
>> assignment to virtual machines. CCing qubes-devel for confirmation.
>>
>> What should that patch look like? Could there be a way for these user
>> groups to be informed of vulnerabilities in the USB subsystem, so that
>> they can take responsibility for fixing them before they become public?
>
> I've posted a proposal elsewhere in the same thread:
>
> https://lore.kernel.org/lkml/afSxSX8RK0Z4kkOI@1wt.eu/
I saw that, but it's still not quite clear what is meant here.
My understanding is that those concerned about malicious USB devices
are generally concerned about _arbitrary_ malicious USB devices.
The one thing a USB device shouldn't be able to spoof is the port
it is plugged into, and userspace tools like USBGuard can use that
information. But to do that, they have to trust that the device
can't harm the system if it isn't assigned to any drivers.
>> It does make sense for those who care about the security of a subsystem
>> to be responsible for vulnerabilities in that system, but right now
>> I'm not sure how one would offer to take up that responsibility.
>
> I think that at least some subsystems will want to add their own
> restrictions based on the bug reports they keep receiving, and I hope
> it can help distros figure where there's a gap between is promised to
> users and what the kernel promises, that needs to be filled by userland
> verification tools for example.
>
> Willy
I think there might be another category, which is were there is a
third party who is much more interested in the security of a subsystem
than its primary maintainers are. I suspect that Google is said
third party in multiple such cases, especially various USB drivers.
In particular, exploiting the kernel via USB is a common attack
technique used in the wild by tools like Cellebrite.
In these cases, I think it makes sense to funnel vulnerability
reports to the people who actually seriously care about fixing them.
For instance, problems in USB might be funneled to the Chrome OS and
Android security teams. They will get fixed much more quickly, and
upstream maintainers won't be flooded with reports that don't have
attached patches.
--
Sincerely,
Demi Marie Obenour (she/her/hers)
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 7253 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH 2/3] Documentation: security-bugs: explain what is and is not a security bug
From: Willy Tarreau @ 2026-05-02 6:07 UTC (permalink / raw)
To: Demi Marie Obenour
Cc: Greg KH, leon, security, Jonathan Corbet, skhan, workflows,
linux-doc, linux-kernel, Qubes Developer Mailing List
In-Reply-To: <a8e60dfe-2965-4a4b-89fb-ce5991395dc5@gmail.com>
On Sat, May 02, 2026 at 01:51:08AM -0400, Demi Marie Obenour wrote:
> On 5/2/26 01:35, Willy Tarreau wrote:
> > Hi Demi Marie,
> >
> > On Sat, May 02, 2026 at 01:20:10AM -0400, Demi Marie Obenour wrote:
> >>>>> Ah, but USB does cover "some" modification of devices, so this is going
> >>>>> to be something that is good to document over time, if for no other
> >>>>> reason to keep these scanning tools in check from hallucinating crazy
> >>>>> situations that are obviously not a valid thing we care about.
> >>>>
> >>>> OK but does this mean you still want to get these reports in the end ?
> >>>
> >>> I want a patch if a user cares about that threat-model (as Android does
> >>> but no one else) as it's up to the user groups that want to change the
> >>> default kernel's behavior like this to actually submit patches to do so.
> >> FYI, I don't think this is limited to Android. Chrome OS definitely
> >> cares about malicious USB devices, and the whole purpose of USBGuard is
> >> to prevent a USB device from being able to compromise the system unless
> >> authorized. I believe Qubes OS also cares, as it supports USB device
> >> assignment to virtual machines. CCing qubes-devel for confirmation.
> >>
> >> What should that patch look like? Could there be a way for these user
> >> groups to be informed of vulnerabilities in the USB subsystem, so that
> >> they can take responsibility for fixing them before they become public?
> >
> > I've posted a proposal elsewhere in the same thread:
> >
> > https://lore.kernel.org/lkml/afSxSX8RK0Z4kkOI@1wt.eu/
>
> I saw that, but it's still not quite clear what is meant here.
> My understanding is that those concerned about malicious USB devices
> are generally concerned about _arbitrary_ malicious USB devices.
> The one thing a USB device shouldn't be able to spoof is the port
> it is plugged into, and userspace tools like USBGuard can use that
> information. But to do that, they have to trust that the device
> can't harm the system if it isn't assigned to any drivers.
The goal sought by that early document precisely is to draw the line
between what is a regular bug and hwat is a kernel bug. The kernel
currently doesn't consider problems posed by a crafted USB device as a
security issue because the kernel trusts the hardware in runs on. Of
course there can be valid reasons to disagree with this, but it's just
the current situation and the purpose of the document is to clarify it
so that bugs are reported to the right place and handled efficiently.
> >> It does make sense for those who care about the security of a subsystem
> >> to be responsible for vulnerabilities in that system, but right now
> >> I'm not sure how one would offer to take up that responsibility.
> >
> > I think that at least some subsystems will want to add their own
> > restrictions based on the bug reports they keep receiving, and I hope
> > it can help distros figure where there's a gap between is promised to
> > users and what the kernel promises, that needs to be filled by userland
> > verification tools for example.
> >
> > Willy
>
> I think there might be another category, which is were there is a
> third party who is much more interested in the security of a subsystem
> than its primary maintainers are. I suspect that Google is said
> third party in multiple such cases, especially various USB drivers.
> In particular, exploiting the kernel via USB is a common attack
> technique used in the wild by tools like Cellebrite.
Possibly that such ones might appear there at some point. The best
way for these might be to have such teams try to step up as
co-maintainers for the parts they care about though.
> In these cases, I think it makes sense to funnel vulnerability
> reports to the people who actually seriously care about fixing them.
> For instance, problems in USB might be funneled to the Chrome OS and
> Android security teams. They will get fixed much more quickly, and
> upstream maintainers won't be flooded with reports that don't have
> attached patches.
Trust me, patches written behind closed doors rarely resist publication
and discovery by the maintainer. And treating bugs as regular ones in
fact tends to make them move faster than as security ones. No need to
go back-and-forth asking for data that reporters hesitate to share, nor
to have to first convince them that their bug needs to be fixed even
though they were planning on speaking about them at a conference, etc.
Cheers,
Willy
^ permalink raw reply
* Re: [PATCH 2/3] Documentation: security-bugs: explain what is and is not a security bug
From: Demi Marie Obenour @ 2026-05-02 6:27 UTC (permalink / raw)
To: Willy Tarreau
Cc: Greg KH, leon, security, Jonathan Corbet, skhan, workflows,
linux-doc, linux-kernel, Qubes Developer Mailing List
In-Reply-To: <afWUjN1FbIHIK99Z@1wt.eu>
[-- Attachment #1.1.1: Type: text/plain, Size: 5195 bytes --]
On 5/2/26 02:07, Willy Tarreau wrote:
> On Sat, May 02, 2026 at 01:51:08AM -0400, Demi Marie Obenour wrote:
>> On 5/2/26 01:35, Willy Tarreau wrote:
>>> Hi Demi Marie,
>>>
>>> On Sat, May 02, 2026 at 01:20:10AM -0400, Demi Marie Obenour wrote:
>>>>>>> Ah, but USB does cover "some" modification of devices, so this is going
>>>>>>> to be something that is good to document over time, if for no other
>>>>>>> reason to keep these scanning tools in check from hallucinating crazy
>>>>>>> situations that are obviously not a valid thing we care about.
>>>>>>
>>>>>> OK but does this mean you still want to get these reports in the end ?
>>>>>
>>>>> I want a patch if a user cares about that threat-model (as Android does
>>>>> but no one else) as it's up to the user groups that want to change the
>>>>> default kernel's behavior like this to actually submit patches to do so.
>>>> FYI, I don't think this is limited to Android. Chrome OS definitely
>>>> cares about malicious USB devices, and the whole purpose of USBGuard is
>>>> to prevent a USB device from being able to compromise the system unless
>>>> authorized. I believe Qubes OS also cares, as it supports USB device
>>>> assignment to virtual machines. CCing qubes-devel for confirmation.
>>>>
>>>> What should that patch look like? Could there be a way for these user
>>>> groups to be informed of vulnerabilities in the USB subsystem, so that
>>>> they can take responsibility for fixing them before they become public?
>>>
>>> I've posted a proposal elsewhere in the same thread:
>>>
>>> https://lore.kernel.org/lkml/afSxSX8RK0Z4kkOI@1wt.eu/
>>
>> I saw that, but it's still not quite clear what is meant here.
>> My understanding is that those concerned about malicious USB devices
>> are generally concerned about _arbitrary_ malicious USB devices.
>> The one thing a USB device shouldn't be able to spoof is the port
>> it is plugged into, and userspace tools like USBGuard can use that
>> information. But to do that, they have to trust that the device
>> can't harm the system if it isn't assigned to any drivers.
>
> The goal sought by that early document precisely is to draw the line
> between what is a regular bug and hwat is a kernel bug. The kernel
> currently doesn't consider problems posed by a crafted USB device as a
> security issue because the kernel trusts the hardware in runs on. Of
> course there can be valid reasons to disagree with this, but it's just
> the current situation and the purpose of the document is to clarify it
> so that bugs are reported to the right place and handled efficiently.
Fair. That does bring up the question of what those who want
to change that situation should do, and they definitely exist.
A documented path for them to follow (even if long and convoluted,
such as becoming co-maintainers of the subsystem) could be helpful.
I'd offer to help write something, but I suspect that this is
something that can only really be written by a member of the kernel
security team. Hence this request.
>>>> It does make sense for those who care about the security of a subsystem
>>>> to be responsible for vulnerabilities in that system, but right now
>>>> I'm not sure how one would offer to take up that responsibility.
>>>
>>> I think that at least some subsystems will want to add their own
>>> restrictions based on the bug reports they keep receiving, and I hope
>>> it can help distros figure where there's a gap between is promised to
>>> users and what the kernel promises, that needs to be filled by userland
>>> verification tools for example.
>>>
>>> Willy
>>
>> I think there might be another category, which is were there is a
>> third party who is much more interested in the security of a subsystem
>> than its primary maintainers are. I suspect that Google is said
>> third party in multiple such cases, especially various USB drivers.
>> In particular, exploiting the kernel via USB is a common attack
>> technique used in the wild by tools like Cellebrite.
>
> Possibly that such ones might appear there at some point. The best
> way for these might be to have such teams try to step up as
> co-maintainers for the parts they care about though.
Makes sense.
>> In these cases, I think it makes sense to funnel vulnerability
>> reports to the people who actually seriously care about fixing them.
>> For instance, problems in USB might be funneled to the Chrome OS and
>> Android security teams. They will get fixed much more quickly, and
>> upstream maintainers won't be flooded with reports that don't have
>> attached patches.
>
> Trust me, patches written behind closed doors rarely resist publication
> and discovery by the maintainer. And treating bugs as regular ones in
> fact tends to make them move faster than as security ones. No need to
> go back-and-forth asking for data that reporters hesitate to share, nor
> to have to first convince them that their bug needs to be fixed even
> though they were planning on speaking about them at a conference, etc.
That doesn't surprise me, actually.
--
Sincerely,
Demi Marie Obenour (she/her/hers)
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 7253 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH v2 1/3] Documentation: security-bugs: do not systematically Cc the security team
From: Willy Tarreau @ 2026-05-03 11:35 UTC (permalink / raw)
To: greg
Cc: leon, security, Jonathan Corbet, skhan, workflows, linux-doc,
linux-kernel, Willy Tarreau, Greg KH
In-Reply-To: <20260503113506.5710-1-w@1wt.eu>
With the increase of automated reports, the security team is dealing
with way more messages than really needed. The reporting process works
well with most teams so there is no need to systematically involve the
security team in reports.
Let's suggest to keep it for small lists of recipients and new reporters
only. This should continue to cover the risk of lost messages while
reducing the volume from prolific reporters.
Cc: Greg KH <gregkh@linuxfoundation.org>
Cc: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
Documentation/process/security-bugs.rst | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/Documentation/process/security-bugs.rst b/Documentation/process/security-bugs.rst
index 27b028e858610..6dc525858125e 100644
--- a/Documentation/process/security-bugs.rst
+++ b/Documentation/process/security-bugs.rst
@@ -148,7 +148,15 @@ run additional tests. Reports where the reporter does not respond promptly
or cannot effectively discuss their findings may be abandoned if the
communication does not quickly improve.
-The report must be sent to maintainers, with the security team in ``Cc:``.
+The report must be sent to maintainers. If there are two or fewer
+recipients in your message, you must also always Cc: the Linux kernel
+security team who will ensure the message is delivered to the proper
+people, and will be able to assist small maintainer teams with processes
+they may not be familiar with. For larger teams, Cc: the Linux kernel
+security team for your first few reports or when seeking specific help,
+such as when resending a message which got no response within a week.
+Once you have become comfortable with the process for a few reports, it is
+no longer necessary to Cc: the security list when sending to large teams.
The Linux kernel security team can be contacted by email at
<security@kernel.org>. This is a private list of security officers
who will help verify the bug report and assist developers working on a fix.
--
2.52.0
^ permalink raw reply related
* [PATCH v2 2/3] Documentation: security-bugs: explain what is and is not a security bug
From: Willy Tarreau @ 2026-05-03 11:35 UTC (permalink / raw)
To: greg
Cc: leon, security, Jonathan Corbet, skhan, workflows, linux-doc,
linux-kernel, Willy Tarreau, Greg KH
In-Reply-To: <20260503113506.5710-1-w@1wt.eu>
The use of automated tools to find bugs in random locations of the kernel
induces a raise of security reports even if most of them should just be
reported as regular bugs. This patch is an attempt at drawing a line
between what qualifies as a security bug and what does not, hoping to
improve the situation and ease decision on the reporter's side.
It defers the enumeration to a new file, threat-model.rst, that tries
to enumerate various classes of issues that are and are not security
bugs. This should permit to more easily update this file for various
subsystem-specific rules without having to revisit the security bug
reporting guide.
Cc: Greg KH <gregkh@linuxfoundation.org>
Cc: Leon Romanovsky <leon@kernel.org>
Suggested-by: Leon Romanovsky <leon@kernel.org>
Suggested-by: Greg KH <gregkh@linuxfoundation.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
Documentation/process/index.rst | 1 +
Documentation/process/security-bugs.rst | 28 +++
Documentation/process/threat-model.rst | 231 ++++++++++++++++++++++++
3 files changed, 260 insertions(+)
create mode 100644 Documentation/process/threat-model.rst
diff --git a/Documentation/process/index.rst b/Documentation/process/index.rst
index dbd6ea16aca70..aa7c959a52b87 100644
--- a/Documentation/process/index.rst
+++ b/Documentation/process/index.rst
@@ -86,6 +86,7 @@ regressions and security problems.
debugging/index
handling-regressions
security-bugs
+ threat-model
cve
embargoed-hardware-issues
diff --git a/Documentation/process/security-bugs.rst b/Documentation/process/security-bugs.rst
index 6dc525858125e..3b44464dd9ba7 100644
--- a/Documentation/process/security-bugs.rst
+++ b/Documentation/process/security-bugs.rst
@@ -66,6 +66,34 @@ In addition, the following information are highly desirable:
the issue appear. It is useful to share them, as they can be helpful to
keep end users protected during the time it takes them to apply the fix.
+What qualifies as a security bug
+--------------------------------
+
+It is important that most bugs are handled publicly so as to involve the widest
+possible audience and find the best solution. By nature, bugs that are handled
+in closed discussions between a small set of participants are less likely to
+produce the best possible fix (e.g., risk of missing valid use cases, limited
+testing abilities).
+
+It turns out that the majority of the bugs reported via the security team are
+just regular bugs that have been improperly qualified as security bugs due to
+ignorance or misunderstanding of the Linux kernel's threat model described in
+Documentation/process/threat-model.rst, and ought to have been sent through
+the normal channels described in Documentation/admin-guide/reporting-issues.rst
+instead.
+
+The security list exists for urgent bugs that grant an attacker a capability
+they are not supposed to have on a correctly configured production system, and
+can be easily exploited, representing an imminent threat to many users. Before
+reporting, consider whether the issue actually crosses a trust boundary on such
+a system.
+
+If you are unsure whether an issue qualifies, err on the side of reporting
+privately: the security team would rather triage a borderline report than miss
+a real vulnerability. Reporting ordinary bugs to the security list, however,
+does not make them move faster and consumes triage capacity that other reports
+need.
+
Identifying contacts
--------------------
diff --git a/Documentation/process/threat-model.rst b/Documentation/process/threat-model.rst
new file mode 100644
index 0000000000000..8cd46483cd8b5
--- /dev/null
+++ b/Documentation/process/threat-model.rst
@@ -0,0 +1,231 @@
+.. _threatmodel:
+
+The Linux Kernel threat model
+=============================
+
+There are a lot of assumptions regarding what the kernel protects against and
+what it does not protect against. These assumptions tend to cause confusion for
+bug reports (:doc:`security-related ones <security-bugs>` vs
+:doc:`non-security ones <../admin-guide/reporting-issues>`), and can complicate
+security enforcement when the responsibilities for some boundaries is not clear
+between the kernel, distros, administrators and users.
+
+This document tries to clarify the responsibilities of the kernel in this
+domain.
+
+The kernel's responsibilities
+-----------------------------
+
+The kernel abstracts access to local hardware resources and to remote systems
+in a way that allows multiple local users to get a fair share of the available
+resources granted to them, and, when the underlying hardware permits, to assign
+a level of confidentiality to their communications and to the data they are
+processing or storing.
+
+The kernel assumes that the underlying hardware behaves according to its
+specifications. This includes the integrity of the CPU's instruction set, the
+transparency of the branch prediction unit and the cache units, the consistency
+of the Memory Management Unit (MMU), the isolation of DMA-capable peripherals
+(e.g., via IOMMU), state transitions in controllers, ranges of values read from
+registers, the respect of documented hardware limitations, etc.
+
+When hardware fails to maintain its specified isolation (e.g., CPU bugs,
+side-channels, hardware response to unexpected inputs), the kernel will usually
+attempt to implement reasonable mitigations. These are best-effort measures
+intended to reduce the attack surface or elevate the cost of an attack within
+the limits of the hardware's facilities; they do not constitute a
+kernel-provided safety guarantee.
+
+Users always perform their activities under the authority of an administrator
+who is able to grant or deny various types of permissions that may affect how
+users benefit from available resources, or the level of confidentiality of
+their activities. Administrators may also delegate all or part of their own
+permissions to some users, particularly via capabilities but not only. All this
+is performed via configuration (sysctl, file-system permissions etc).
+
+The Linux Kernel applies a certain collection of default settings that match
+its threat model. Distros have their own threat model and will come with their
+own configuration presets, that the administrator may have to adjust to better
+suit their expectations (relax or restrict).
+
+By default, the Linux Kernel guarantees the following protections when running
+on common processors featuring privilege levels and memory management units:
+
+* **User-based isolation**: an unprivileged user may restrict access to their
+ own data from other unprivileged users running on the same system. This
+ includes:
+
+ * stored data, via file system permissions
+ * in-memory data (pages are not accessible by default to other users)
+ * process activity (ptrace is not permitted to other users)
+ * inter-process communication (other users may not observe data exchanged via
+ UNIX domain sockets or other IPC mechanisms).
+ * network communications within the same or with other systems
+
+* **Capability-based protection**:
+
+ * users not having the ``CAP_SYS_ADMIN`` capability may not alter the
+ kernel's configuration, memory nor state, change other users' view of the
+ file system layout, grant any user capabilities they do not have, nor
+ affect the system's availability (shutdown, reboot, panic, hang, or making
+ the system unresponsive via unbounded resource exhaustion).
+ * users not having the ``CAP_NET_ADMIN`` capability may not alter the network
+ configuration, intercept nor spoof network communications from other users
+ nor systems.
+ * users not having ``CAP_SYS_PTRACE`` may not observe other users' processes
+ activities.
+
+When ``CONFIG_USER_NS`` is set, the kernel also permits unprivileged users to
+create their own user namespace in which they have all capabilities, but with a
+number of restrictions (they may not perform actions that have impacts on the
+initial user namespace, such as changing time, loading modules or mounting
+block devices). Please refer to ``user_namespaces(7)`` for more details, the
+possibilities of user namespaces are not covered in this document.
+
+The kernel also offers a lot of troubleshooting and debugging facilities, which
+can constitute attack vectors when placed in wrong hands. While some of them
+are designed to be accessible to regular local users with a low risk (e.g.
+kernel logs via ``/proc/kmsg``), some would expose enough information to
+represent a risk in most places and the decision to expose them is under the
+administrator's responsibility (perf events, traces), and others are not
+designed to be accessed by non-privileged users (e.g. debugfs). Access to these
+facilities by a user who has been explicitly granted permission by an
+administrator does not constitute a security breach.
+
+Bugs that permit to violate the principles above constitute security breaches.
+However, bugs that permit one violation only once another one was already
+achieved are only weaknesses. The kernel applies a number of self-protection
+measures whose purpose is to avoid crossing a security boundary when certain
+classes of bugs are found, but a failure of these extra protections do not
+constitute a vulnerability alone.
+
+What does not constitute a security bug
+---------------------------------------
+
+In the Linux kernel's threat model, the following classes of problems are
+**NOT** considered as Linux Kernel security bugs. However, when it is believed
+that the kernel could do better, they should be reported, so that they can be
+reviewed and fixed where reasonably possible, but they will be handled as any
+regular bug:
+
+* **Configuration**:
+
+ * outdated kernels and particularly end-of-life branches are out of the scope
+ of the kernel's threat model: administrators are responsible for keeping
+ their system up to date. For a bug to qualify as a security bug, it must be
+ demonstrated that it affects actively maintained versions.
+
+ * build-level: changes to the kernel configuration that are explicitly
+ documented as lowering the security level (e.g. ``CONFIG_NOMMU``), or
+ targeted at developers only.
+
+ * OS-level: changes to command line parameters, sysctls, filesystem
+ permissions, user capabilities, exposure of privileged interfaces, that
+ explicitly increase exposure by either offering non-default access to
+ unprivileged users, or reduce the kernel's ability to enforce some
+ protections or mitigations. Example: write access to procfs or debugfs.
+
+ * issues triggered only when using features intended for development or
+ debugging (e.g., lockdep, KASAN, fault-injection): these features are known
+ to introduce overhead and potential instability and are not intended for
+ production use.
+
+ * loading of explicitly insecure/broken/staging modules, and generally any
+ using any subsystem marked as experimental or not intended for production
+ use.
+
+ * running out-of-tree modules or unofficial kernel forks; these should be
+ reported to the relevant vendor.
+
+* **Excess of initial privileges**:
+
+ * actions performed by a user already possessing the privileges required to
+ perform that action or modify that state (e.g. ``CAP_SYS_ADMIN``,
+ ``CAP_NET_ADMIN``, ``CAP_SYS_RAWIO``, ``CAP_SYS_MODULE`` with no further
+ boundary being crossed).
+
+ * actions performed in user namespace without permitting anything in the
+ initial namespace that was not already permitted to the same user there.
+
+ * anything performed by the root user in the initial namespace (e.g. kernel
+ oops when writing to a privileged device).
+
+* **Out of production use**:
+
+ This covers theoretical/probabilistic attacks that rely on laboratory
+ conditions with zero system noise, or those requiring an unrealistic number
+ of attempts (e.g., billions of trials) that would be detected by standard
+ system monitoring long before success, such as:
+
+ * prediction of random numbers that only works in a totally silent
+ environment (such as IP ID, TCP ports or sequence numbers that can only be
+ guessed in a lab).
+
+ * activity observation and information leaks based on probabilistic
+ approaches that are prone to measurement noise and not realistically
+ reproducible on a production system.
+
+ * issues that can only be triggered by heavy attacks (e.g. brute force) whose
+ impact on the system makes it unlikely or impossible to remain undetected
+ before they succeed (e.g. consuming all memory before succeeding).
+
+ * problems seen only under development simulators, emulators, or combinations
+ that do not exist on real systems at the time of reporting (issues
+ involving tens of millions of threads, tens of thousands of CPUs,
+ unrealistic CPU frequencies, RAM sizes or disk capacities, network speeds.
+
+ * issues whose reproduction requires hardware modification or emulation,
+ including fake USB devices that pretend to be another one.
+
+ * as well as issues that can be triggered at a cost that is orders of
+ magnitude higher than the expected benefits (e.g. fully functional keyboard
+ emulator only to retrieve 7 uninitialized bytes in a structure, or
+ brute-force method involving millions of connection attempts to guess a
+ port number).
+
+* **Hardening failures**:
+
+ * ability to bypass some of the kernel's hardening measures with no
+ demonstrable exploit path (e.g. ASLR bypass, events timing or probing with
+ no demonstrable consequence). These are just weaknesses, not
+ vulnerabilities.
+
+ * missing argument checks and failure to report certain errors with no
+ immediate consequence.
+
+* **Random information leaks**:
+
+ This concerns information leaks of small data parts that happen to be there
+ and that cannot be chosen by the attacker, or face access restrictions:
+
+ * structure padding reported by syscalls or other interfaces.
+
+ * identifiers, partial data, non-terminated strings reported in error
+ messages.
+
+ * Leaks of kernel memory addresses/pointers do not constitute an immediately
+ exploitable vector and are not security bugs, though they must be reported
+ and fixed.
+
+* **Crafted file system images**:
+
+ * bugs triggered by mounting a corrupted or maliciously crafted file system
+ image are generally not security bugs, as the kernel assumes the underlying
+ storage media is under the administrator's control, unless the filesystem
+ driver is specifically documented as being hardened against untrusted media.
+
+ * issues that are resolved, mitigated, or detected by running a filesystem
+ consistency check (fsck) on the image prior to mounting.
+
+* **Physical access**:
+
+ Issues that require physical access to the machine, hardware modification, or
+ the use of specialized hardware (e.g., logic analyzers, DMA-attack tools over
+ PCI-E/Thunderbolt) are out of scope unless the system is explicitly
+ configured with technologies meant to defend against such attacks
+ (e.g. IOMMU).
+
+* **Functional and performance regressions**:
+
+ Any issue that can be mitigated by setting proper permissions and limits
+ doesn't qualify as a security bug.
--
2.52.0
^ permalink raw reply related
* [PATCH v2 0/3] Documentation: security-bugs: new updates covering triage and AI
From: Willy Tarreau @ 2026-05-03 11:35 UTC (permalink / raw)
To: greg
Cc: leon, security, Jonathan Corbet, skhan, workflows, linux-doc,
linux-kernel, Willy Tarreau
This series tries to translate recent discussions on the security list
on how to better handle reports. It details:
- when not to Cc: the security list
- what classes of bugs do not need to be handled privately
- minimum requirements for AI-assisted reports
As usual, this is probably perfectible but can already help in the short
term as we can point it to reporters, so barring any strong disagreement,
better continue to proceed in small incremental improvements and observe
the effects.
Thanks!
Willy
---
v2:
- fixes for issues reported by Randy
- Greg's ack on the AI part
- reworded the "when to Cc" part based on Greg's feedback
(Greg I didn't take your original ack since the wording changed)
- split the threat model into its own document as per Greg's suggestion
---
Willy Tarreau (3):
Documentation: security-bugs: do not systematically Cc the security
team
Documentation: security-bugs: explain what is and is not a security
bug
Documentation: security-bugs: clarify requirements for AI-assisted
reports
Documentation/process/index.rst | 1 +
Documentation/process/security-bugs.rst | 93 +++++++++-
Documentation/process/threat-model.rst | 231 ++++++++++++++++++++++++
3 files changed, 324 insertions(+), 1 deletion(-)
create mode 100644 Documentation/process/threat-model.rst
--
2.52.0
^ permalink raw reply
* [PATCH v2 3/3] Documentation: security-bugs: clarify requirements for AI-assisted reports
From: Willy Tarreau @ 2026-05-03 11:35 UTC (permalink / raw)
To: greg
Cc: leon, security, Jonathan Corbet, skhan, workflows, linux-doc,
linux-kernel, Willy Tarreau, Greg KH
In-Reply-To: <20260503113506.5710-1-w@1wt.eu>
AI tools are increasingly used to assist in bug discovery. While these
tools can identify valid issues, reports that are submitted without
manual verification often lack context, contain speculative impact
assessments, or include unnecessary formatting. Such reports increase
triage effort, waste maintainers' time and may be ignored.
Reports where the reporter has verified the issue and the proposed fix
typically meet quality standards. This documentation outlines specific
requirements for length, formatting, and impact evaluation to reduce
the effort needed to deal with these reports.
Cc: Greg KH <gregkh@linuxfoundation.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
Documentation/process/security-bugs.rst | 55 +++++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/Documentation/process/security-bugs.rst b/Documentation/process/security-bugs.rst
index 3b44464dd9ba7..bf62469a81266 100644
--- a/Documentation/process/security-bugs.rst
+++ b/Documentation/process/security-bugs.rst
@@ -159,6 +159,61 @@ the Linux kernel security team only. Your message will be triaged, and you
will receive instructions about whom to contact, if needed. Your message may
equally be forwarded as-is to the relevant maintainers.
+Responsible use of AI to find bugs
+----------------------------------
+
+A significant fraction of bug reports submitted to the security team are
+actually the result of code reviews assisted by AI tools. While this can be an
+efficient means to find bugs in rarely explored areas, it causes an overload on
+maintainers, who are sometimes forced to ignore such reports due to their poor
+quality or accuracy. As such, reporters must be particularly cautious about a
+number of points which tend to make these reports needlessly difficult to
+handle:
+
+ * **Length**: AI-generated reports tend to be excessively long, containing
+ multiple sections and excessive detail. This makes it difficult to spot
+ important information such as affected files, versions, and impact. Please
+ ensure that a clear summary of the problem and all critical details are
+ presented first. Do not require triage engineers to scan multiple pages of
+ text. Configure your tools to produce concise, human-style reports.
+
+ * **Formatting**: Most AI-generated reports are littered with Markdown tags.
+ These decorations complicate the search for important information and do
+ not survive the quoting processes involved in forwarding or replying.
+ Please **always convert your report to plain text** without any formatting
+ decorations before sending it.
+
+ * **Impact Evaluation**: Many AI-generated reports lack an understanding of
+ the kernel's threat model and go to great lengths inventing theoretical
+ consequences. This adds noise and complicates triage. Please stick to
+ verifiable facts (e.g., "this bug permits any user to gain CAP_NET_ADMIN")
+ without enumerating speculative implications. Have your tool read this
+ documentation as part of the evaluation process.
+
+ * **Reproducer**: AI-based tools are often capable of generating reproducers.
+ Please always ensure your tool provides one and **test it thoroughly**. If
+ the reproducer does not work, or if the tool cannot produce one, the
+ validity of the report should be seriously questioned.
+
+ * **Propose a Fix**: Many AI tools are actually better at writing code than
+ evaluating it. Please ask your tool to propose a fix and **test it** before
+ reporting the problem. If the fix cannot be tested because it relies on
+ rare hardware or almost extinct network protocols, the issue is likely not
+ a security bug. In any case, if a fix is proposed, it must adhere to
+ Documentation/process/submitting-patches.rst and include a 'Fixes:' tag
+ designating the commit that introduced the bug.
+
+Failure to consider these points exposes your report to the risk of being
+ignored.
+
+Use common sense when evaluating the report. If the affected file has not been
+touched for more than one year and is maintained by a single individual, it is
+likely that usage has declined and exposed users are virtually non-existent
+(e.g., drivers for very old hardware, obsolete filesystems). In such cases,
+there is no need to consume a maintainer's time with an unimportant report. If
+the issue is clearly trivial and publicly discoverable, you should report it
+directly to the public mailing lists.
+
Sending the report
------------------
--
2.52.0
^ permalink raw reply related
* Re: [PATCH v4 0/3] Documentation: adopt new coding style of type-aware kmalloc-family
From: Jonathan Corbet @ 2026-05-03 14:56 UTC (permalink / raw)
To: Manuel Ebner, Shuah Khan, linux-doc, Kees Cook
Cc: linux-kernel, workflows, linux-sound, rcu, linux-media, linux-mm,
Manuel Ebner
In-Reply-To: <20260429070759.309110-3-manuelebner@mailbox.org>
Manuel Ebner <manuelebner@mailbox.org> writes:
> Update the documentation to reflect new type-aware kmalloc-family as
> suggested in commit 2932ba8d9c99 ("slab: Introduce kmalloc_obj()
> and family")
OK, I have applied this series. While doing so, I restored the "gfp"
parameter in the changelog portion where it had been mistakenly removed.
Thanks,
jon
^ permalink raw reply
* Re: [PATCH v4 0/3] Documentation: adopt new coding style of type-aware kmalloc-family
From: Manuel Ebner @ 2026-05-03 15:47 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, linux-doc, Kees Cook
Cc: linux-kernel, workflows, linux-sound, rcu, linux-media, linux-mm
In-Reply-To: <87o6iwczjm.fsf@trenco.lwn.net>
On Sun, 2026-05-03 at 08:56 -0600, Jonathan Corbet wrote:
> Manuel Ebner <manuelebner@mailbox.org> writes:
>
> > Update the documentation to reflect new type-aware kmalloc-family as
> > suggested in commit 2932ba8d9c99 ("slab: Introduce kmalloc_obj()
> > and family")
>
> OK, I have applied this series. While doing so, I restored the "gfp"
> parameter in the changelog portion where it had been mistakenly removed.
That's good, thanks.
I had two more changes lined up for v5 of this series:
- ptr = kmalloc(sizeof(struct foo, gfp);
+ ptr = kmalloc(sizeof(struct foo), gfp);
and
-The argument gfp is optional, the default value is GFP_KERNEL.
+The argument `gfp` is optional, the default value is `GFP_KERNEL`.
I don't know how to go forward with this.
please advice
Thanks
Manuel
> Thanks,
>
> jon
^ permalink raw reply
* Re: [PATCH v4 00/10] Auto-generate maintainer profile entries
From: Jonathan Corbet @ 2026-05-03 15:49 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Albert Ou, Mauro Carvalho Chehab,
Palmer Dabbelt, Paul Walmsley
Cc: Mauro Carvalho Chehab, linux-doc, linux-kernel, linux-riscv,
workflows, Alexandre Ghiti, Shuah Khan, Randy Dunlap,
Dan Williams
In-Reply-To: <cover.1777295258.git.mchehab+huawei@kernel.org>
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
> Hi Jon,
>
> This is basically the same patch series I sent during the merge
> window, rebased on the top of post 7.1-rc1 docs-next branch.
> It is tested both with and without O=DOCS.
>
> It contains just one extra trivial patch adding a missing SPDX
> header, and, on v4, I dropped two patches touching MAINTAINERS,
> as those aren't needed anymore.
>
> This patch series change the way maintainer entry profile links
> are added to the documentation. Instead of having an entry for
> each of them at an ReST file, get them from MAINTAINERS content.
>
> That should likely make easier to maintain, as there will be a single
> point to place all such profiles.
>
> The output is a per-subsystem sorted (*) series of links shown as a
> list like this:
>
> - Arm And Arm64 Soc Sub-Architectures (Common Parts)
> - Arm/Samsung S3C, S5P And Exynos Arm Architectures
> - Arm/Tesla Fsd Soc Support
> ...
> - Xfs Filesystem
>
> Please notice that the series is doing one logical change per patch.
> I could have merged some changes altogether, but I opted doing it
> in small steps to help reviews. If you prefer, feel free to merge
> maintainers_include changes on merge.
>
> There is one interesting side effect of this series: there is no
> need to add rst files containing profiles inside a TOC tree: Just
> creating the file anywhere inside Documentation and adding a P entry
> is enough. Adding them to a TOC won't hurt.
One thing I kind of dislike about these magic mechanisms is that we end
up with a single, essentially unsorted list of stuff that readers have
to go digging their way through. It would be nice if we could somehow
apply a bit of structure; as the number of these handbooks grows, our
readers would appreciate it.
Oh well, one can always hope. Meanwhile, this seems useful, I've
applied it.
Thanks,
jon
^ permalink raw reply
* Re: [PATCH v4 0/3] Documentation: adopt new coding style of type-aware kmalloc-family
From: Jonathan Corbet @ 2026-05-03 15:51 UTC (permalink / raw)
To: Manuel Ebner, Shuah Khan, linux-doc, Kees Cook
Cc: linux-kernel, workflows, linux-sound, rcu, linux-media, linux-mm
In-Reply-To: <df48beafcb0cc9caff40db78285113f0b1bd9b87.camel@mailbox.org>
Manuel Ebner <manuelebner@mailbox.org> writes:
> On Sun, 2026-05-03 at 08:56 -0600, Jonathan Corbet wrote:
>> Manuel Ebner <manuelebner@mailbox.org> writes:
>>
>> > Update the documentation to reflect new type-aware kmalloc-family as
>> > suggested in commit 2932ba8d9c99 ("slab: Introduce kmalloc_obj()
>> > and family")
>>
>> OK, I have applied this series. While doing so, I restored the "gfp"
>> parameter in the changelog portion where it had been mistakenly removed.
>
> That's good, thanks.
> I had two more changes lined up for v5 of this series:
>
> - ptr = kmalloc(sizeof(struct foo, gfp);
> + ptr = kmalloc(sizeof(struct foo), gfp);
>
> and
>
> -The argument gfp is optional, the default value is GFP_KERNEL.
> +The argument `gfp` is optional, the default value is `GFP_KERNEL`.
>
> I don't know how to go forward with this.
> please advice
Make a new patch on top of docs-next with the additional changes you
want to do.
Thanks,
jon
^ permalink raw reply
* Re: [PATCH v2] kunit: tool: Add (primitive) support for outputting JUnit XML
From: Thomas Weißschuh @ 2026-05-04 6:23 UTC (permalink / raw)
To: David Gow
Cc: Brendan Higgins, Rae Moar, Shuah Khan, kunit-dev, linux-kernel,
workflows
In-Reply-To: <20260502024918.1056954-1-david@davidgow.net>
Hi David,
On Sat, May 02, 2026 at 10:49:17AM +0800, David Gow wrote:
> This is used by things like Jenkins and other CI systems, which can
> pretty-print the test output and potentially provide test-level comparisons
> between runs.
>
> The implementation here is pretty basic: it only provides the raw results,
> split into tests and test suites, and doesn't provide any overall metadata.
> However, CI systems like Jenkins can injest it and it is already useful.
"ingest"?
> Signed-off-by: David Gow <david@davidgow.net>
> ---
>
> Finally got around to doing a new version of this. I'm running this
> locally with Jenkins, and it's giving nice summaries of test results.
>
> Changes since v1:
> https://lore.kernel.org/all/20260119073426.1952867-1-davidgow@google.com/
> - Use python's provided XML quote escaping, rather than coding our own (Thanks Thomas)
What I tried to suggest was to do all of the XML generation through the Python
module instead of manual string concatenation. The XML escaping would go away
as a side effect.
A pseudo-code example:
out = xml.sax.saxutils.XMLGenerator(f, encoding='utf-8')
out.startDocument()
for subtest in test.subtests:
out.startElement('testcase', {'name': 'subtest.name' })
if subtest.status == TestStatus.FAILURE:
out.startElement('failure', {})
out.characters('Test failed')
out.endElement('failure')
out.endElement('testcase')
How I used it recently:
https://github.com/Linutronix/elbe/blob/master/website/ext/elbedocoverview.py#L133
> - Output proper <skipped> tags for skipped tests
> - Report crashed tests as <error>
> - Don't output <system-out> tags if there are no lines of log data
>
> ---
> Documentation/dev-tools/kunit/run_wrapper.rst | 3 ++
> tools/testing/kunit/kunit.py | 25 ++++++++++-
> tools/testing/kunit/kunit_junit.py | 43 +++++++++++++++++++
> tools/testing/kunit/kunit_tool_test.py | 38 ++++++++++++++--
> 4 files changed, 105 insertions(+), 4 deletions(-)
> create mode 100644 tools/testing/kunit/kunit_junit.py
>
> diff --git a/Documentation/dev-tools/kunit/run_wrapper.rst b/Documentation/dev-tools/kunit/run_wrapper.rst
> index 770bb09a475a..cecc110a3399 100644
> --- a/Documentation/dev-tools/kunit/run_wrapper.rst
> +++ b/Documentation/dev-tools/kunit/run_wrapper.rst
> @@ -324,6 +324,9 @@ command line arguments:
> - ``--json``: If set, stores the test results in a JSON format and prints to `stdout` or
> saves to a file if a filename is specified.
>
> +- ``--junit``: If set, stores the test results in JUnit XML format and prints to `stdout` or
> + saves to a file if a filename is specified.
> +
> - ``--filter``: Specifies filters on test attributes, for example, ``speed!=slow``.
> Multiple filters can be used by wrapping input in quotes and separating filters
> by commas. Example: ``--filter "speed>slow, module=example"``.
> diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
> index 742f5c555666..1a7ff594b791 100755
> --- a/tools/testing/kunit/kunit.py
> +++ b/tools/testing/kunit/kunit.py
> @@ -21,6 +21,7 @@ from enum import Enum, auto
> from typing import Iterable, List, Optional, Sequence, Tuple
>
> import kunit_json
> +import kunit_junit
> import kunit_kernel
> import kunit_parser
> from kunit_printer import stdout, null_printer
> @@ -49,6 +50,7 @@ class KunitBuildRequest(KunitConfigRequest):
> class KunitParseRequest:
> raw_output: Optional[str]
> json: Optional[str]
> + junit: Optional[str]
> summary: bool
> failed: bool
>
> @@ -268,6 +270,17 @@ def parse_tests(request: KunitParseRequest, metadata: kunit_json.Metadata, input
> stdout.print_with_timestamp("Test results stored in %s" %
> os.path.abspath(request.json))
>
> + if request.junit:
> + junit_str = kunit_junit.get_junit_result(
> + test=test)
Unnecessary linebreak?
> + if request.junit == 'stdout':
> + print(junit_str)
> + else:
> + with open(request.junit, 'w') as f:
> + f.write(junit_str)
> + stdout.print_with_timestamp("Test results stored in %s" %
> + os.path.abspath(request.junit))
f-string?
> +
> if test.status != kunit_parser.TestStatus.SUCCESS:
> return KunitResult(KunitStatus.TEST_FAILURE, parse_time), test
>
> @@ -309,6 +322,7 @@ def run_tests(linux: kunit_kernel.LinuxSourceTree,
> # So we hackily automatically rewrite --json => --json=stdout
> pseudo_bool_flag_defaults = {
> '--json': 'stdout',
> + '--junit': 'stdout',
> '--raw_output': 'kunit',
> }
(...)
But all of it are just suggestions.
Thomas
^ permalink raw reply
* Re: [PATCH v4 00/10] Auto-generate maintainer profile entries
From: Mauro Carvalho Chehab @ 2026-05-04 7:00 UTC (permalink / raw)
To: Jonathan Corbet
Cc: Albert Ou, Mauro Carvalho Chehab, Palmer Dabbelt, Paul Walmsley,
linux-doc, linux-kernel, linux-riscv, workflows, Alexandre Ghiti,
Shuah Khan, Randy Dunlap, Dan Williams
In-Reply-To: <87lde0bii2.fsf@trenco.lwn.net>
On Sun, 03 May 2026 09:49:41 -0600
Jonathan Corbet <corbet@lwn.net> wrote:
> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
>
> > Hi Jon,
> >
> > This is basically the same patch series I sent during the merge
> > window, rebased on the top of post 7.1-rc1 docs-next branch.
> > It is tested both with and without O=DOCS.
> >
> > It contains just one extra trivial patch adding a missing SPDX
> > header, and, on v4, I dropped two patches touching MAINTAINERS,
> > as those aren't needed anymore.
> >
> > This patch series change the way maintainer entry profile links
> > are added to the documentation. Instead of having an entry for
> > each of them at an ReST file, get them from MAINTAINERS content.
> >
> > That should likely make easier to maintain, as there will be a single
> > point to place all such profiles.
> >
> > The output is a per-subsystem sorted (*) series of links shown as a
> > list like this:
> >
> > - Arm And Arm64 Soc Sub-Architectures (Common Parts)
> > - Arm/Samsung S3C, S5P And Exynos Arm Architectures
> > - Arm/Tesla Fsd Soc Support
> > ...
> > - Xfs Filesystem
> >
> > Please notice that the series is doing one logical change per patch.
> > I could have merged some changes altogether, but I opted doing it
> > in small steps to help reviews. If you prefer, feel free to merge
> > maintainers_include changes on merge.
> >
> > There is one interesting side effect of this series: there is no
> > need to add rst files containing profiles inside a TOC tree: Just
> > creating the file anywhere inside Documentation and adding a P entry
> > is enough. Adding them to a TOC won't hurt.
>
> One thing I kind of dislike about these magic mechanisms is that we end
> up with a single, essentially unsorted list of stuff that readers have
> to go digging their way through. It would be nice if we could somehow
> apply a bit of structure; as the number of these handbooks grows, our
> readers would appreciate it.
The output is sorted by subsystem's name:
for profile, entry in sorted(maint.profile_entries.items()):
if entry.startswith("http"):
output += f"- `{profile} <{entry}>`_\n"
else:
output += f"- :doc:`{profile} <{entry}>`\n"
But yeah, as this grows, We can apply some struct there later on.
I expect that this would be good enough for "P" entries: as such entries
are used only by the biggest subsystems, I won't expect that the profiles
list would be too big.
If I'm wrong, though, changing its output is easy, as all the parsing
were done in separate: all we have to do would be to change this part.
-
Now, for the full MAINTAINERS content, I agree with you. I have
a patch series here which splits the parsing from the output,
which allows placing its contents inside a table and with a
filter javascript [1]. On my view, the output is a lot more
interesting for readers this way [2].
> Oh well, one can always hope. Meanwhile, this seems useful, I've
> applied it.
Thanks!
---
[1] On such series, I'm creating a table with two rows:
output += ".. _maintainers_table:\n\n"
output += ".. flat-table::\n"
output += " :header-rows: 1\n\n"
output += " * - Subsystem\n"
output += " - Properties\n\n"
self.state.document['maintainers_included'] = True
for name, fields in maint_parser.maint_entries.items():
output += f" * - {name}\n"
tag = "-"
for field, lines in fields.items():
field_name = maint_parser.fields.get(field, field)
output += f" {tag} :{field_name}:\n "
output += ",\n ".join(lines) + "\n"
tag = " "
output += "\n"
Which is a lot easier to read than the current output, and adding
a small javascript that allows filtering entries, based at the
contents of either subsystem or properties. That should help
readers to seek for things they're interested.
I considered ordering it by subsystems, and did some tests with that,
but at the final version I ended removing.
The main issue is that MAINTAINERS entries aren't grouped by
subsystems. Also, we don't have any field to identify to what
subsystem each entry belongs.
Using the mailing list field helps to have something close enough,
while being fast. Even so, some caveats are needed, as:
1) several entries contain multiple ML entries, which may include:
- subsystem ML;
- LKML;
- driver-specific ML;
- vendor-specific ML.
2) several entries have only LKML.
For the purpose of grouping such entries, even after filtering out LKML,
due to (1), hints are needed to try to pick subsystem ML. Perhaps the
best hint is to check if the entry is @kernel.org, which works reasonably
well. Yet, not all subsystems have its ML there.
I also considered sorting them by the number of files, using iglob
to calculate it. That would help to place the subsystem first, followed
by subsystem drivers, and this is fast enough with my nvme disks but
this could slow kernel builds on mechanical HDs.
So, I suspect that, if we want to have something more structured,
the first step would be to do some rework at the MAINTAINERS file.
[2] I need some time to check if are there any regressions
on the patch that splits the logic.
Regards,
Mauro
^ permalink raw reply
* [PATCH v8 0/4] kunit: Add support for suppressing warning backtraces
From: Albert Esteve @ 2026-05-04 7:41 UTC (permalink / raw)
To: Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti
Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
workflows, linux-riscv, linux-doc, peterz, Alessandro Carminati,
Guenter Roeck, Kees Cook, Albert Esteve,
Linux Kernel Functional Testing, Dan Carpenter, Maíra Canal,
Kees Cook, Simona Vetter, David Gow
Some unit tests intentionally trigger warning backtraces by passing bad
parameters to kernel API functions. Such unit tests typically check the
return value from such calls, not the existence of the warning backtrace.
Such intentionally generated warning backtraces are neither desirable
nor useful for a number of reasons:
- They can result in overlooked real problems.
- A warning that suddenly starts to show up in unit tests needs to be
investigated and has to be marked to be ignored, for example by
adjusting filter scripts. Such filters are ad hoc because there is
no real standard format for warnings. On top of that, such filter
scripts would require constant maintenance.
One option to address the problem would be to add messages such as
"expected warning backtraces start/end here" to the kernel log.
However, that would again require filter scripts, might result in
missing real problematic warning backtraces triggered while the test
is running, and the irrelevant backtrace(s) would still clog the
kernel log.
Solve the problem by providing a means to suppress warning backtraces
originating from the current kthread while executing test code.
Since each KUnit test runs in its own kthread, this effectively scopes
suppression to the test that enabled it, without requiring any
architecture-specific code.
Overview:
Patch#1 Introduces the suppression infrastructure integrated into
KUnit's hook mechanism.
Patch#2 Adds selftests to validate the functionality.
Patch#3 Demonstrates real-world usage in the DRM subsystem.
Patch#4 Documents the new API and usage guidelines.
Design Notes:
Suppression is integrated into the existing KUnit hooks infrastructure,
reusing the kunit_running static branch for zero overhead
when no tests are running. The implementation lives entirely in the
kunit module; only a static-inline wrapper and a function pointer
slot are added to built-in code.
Suppression is checked at three points in the warning path:
- In `warn_slowpath_fmt()` (kernel/panic.c), for architectures without
__WARN_FLAGS. The check runs before any output, fully suppressing
both message and backtrace.
- In `__warn_printk()` (kernel/panic.c), for architectures that define
__WARN_FLAGS but not their own __WARN_printf (arm64, loongarch,
parisc, powerpc, riscv, sh). The check suppresses the warning message
text that is printed before the trap enters __report_bug().
- In `__report_bug()` (lib/bug.c), for architectures that define
__WARN_FLAGS. The check runs before `__warn()` is called, suppressing
the backtrace and stack dump.
To avoid double-counting on architectures where both `__warn_printk()`
and `__report_bug()` run for the same warning, the hook takes a bool
parameter: true to increment the suppression counter, false to suppress
without counting.
The suppression state is dynamically allocated via kunit_kzalloc() and
tied to the KUnit test lifecycle via `kunit_add_action()`, ensuring
automatic cleanup at test exit. Writer-side access to the global
suppression list is serialized with a spinlock; readers use RCU.
Three API forms are provided:
- kunit_warning_suppress(test) { ... }: scoped blocks with automatic
cleanup. The suppression handle is not accessible outside the block,
so warning counts (if needed) must be checked inside. Multiple
suppression blocks are allowed.
- KUNIT_START/END_SUPPRESSED_WARNING(test): manual macros for larger
blocks or post-suppression count checks. Limited to one pair per
scope.
- kunit_start/end_suppress_warning(test): direct functions that return
an explicit handle. Use when the handle needs to be retained, or passed
across helpers. Multiple suppression blocks are allowed.
This series is based on the RFC patch and subsequent discussion at
https://patchwork.kernel.org/project/linux-kselftest/patch/02546e59-1afe-4b08-ba81-d94f3b691c9a@moroto.mountain/
and offers a more comprehensive solution of the problem discussed there.
Changes since RFC:
- Introduced CONFIG_KUNIT_SUPPRESS_BACKTRACE
- Minor cleanups and bug fixes
- Added support for all affected architectures
- Added support for counting suppressed warnings
- Added unit tests using those counters
- Added patch to suppress warning backtraces in dev_addr_lists tests
Changes since v1:
- Rebased to v6.9-rc1
- Added Tested-by:, Acked-by:, and Reviewed-by: tags
[I retained those tags since there have been no functional changes]
- Introduced KUNIT_SUPPRESS_BACKTRACE configuration option, enabled by
default.
Changes since v2:
- Rebased to v6.9-rc2
- Added comments to drm warning suppression explaining why it is needed.
- Added patch to move conditional code in arch/sh/include/asm/bug.h
to avoid kerneldoc warning
- Added architecture maintainers to Cc: for architecture specific patches
- No functional changes
Changes since v3:
- Rebased to v6.14-rc6
- Dropped net: "kunit: Suppress lock warning noise at end of dev_addr_lists tests"
since 3db3b62955cd6d73afde05a17d7e8e106695c3b9
- Added __kunit_ and KUNIT_ prefixes.
- Tested on interessed architectures.
Changes since v4:
- Rebased to v6.15-rc7
- Dropped all code in __report_bug()
- Moved all checks in WARN*() macros.
- Dropped all architecture specific code.
- Made __kunit_is_suppressed_warning nice to noinstr functions.
Changes since v5:
- Rebased to v7.0-rc3
- Added RCU protection for the suppressed warnings list.
- Added static key and branching optimization.
- Removed custom `strcmp` implementation and reworked
__kunit_is_suppressed_warning() entrypoint function.
Changes since v6:
- Moved suppression checks from WARN*() macros to warn_slowpath_fmt()
and __report_bug().
- Replaced stack-allocated suppression struct with kunit_kzalloc() heap
allocation tied to the KUnit test lifecycle.
- Changed suppression strategy from function-name matching to task-scoped:
all warnings on the current task are suppressed between START and END,
rather than only warnings originating from a specific named function.
- Simplified macro API: removed KUNIT_DECLARE_SUPPRESSED_WARNING(),
the START macro now takes (test) and handles allocation internally.
- Removed static key and branching optiomization, as by the time it
was executed, callers are already in warn slowpaths.
- Link to v6: https://lore.kernel.org/r/20260317-kunit_add_support-v6-0-dd22aeb3fe5d@redhat.com
Changes since v7:
- Integrated suppression into existing KUnit hooks infrastructure
- Removed CONFIG_KUNIT_SUPPRESS_BACKTRACE
- Added suppression check in __warn_printk()
- Added spinlock for writer-side RCU protection
- Replaced explicit rcu_read_lock/unlock with guard(rcu)()
- Added scoped API (kunit_warning_suppress) using __cleanup attribute
- Updated DRM patch to use scoped API
- Expanded self-tests: incremental counting, cross-kthread isolation
- Rewrote documentation covering all three API forms with examples
- Link to v7: https://lore.kernel.org/r/20260420-kunit_add_support-v7-0-e8bc6e0f70de@redhat.com
--
2.34.1
---
Alessandro Carminati (1):
bug/kunit: Core support for suppressing warning backtraces
Guenter Roeck (3):
kunit: Add backtrace suppression self-tests
drm: Suppress intentional warning backtraces in scaling unit tests
kunit: Add documentation for warning backtrace suppression API
Documentation/dev-tools/kunit/usage.rst | 63 ++++++++++-
drivers/gpu/drm/tests/drm_rect_test.c | 23 +++-
include/kunit/test-bug.h | 25 +++++
include/kunit/test.h | 138 ++++++++++++++++++++++++
kernel/panic.c | 15 ++-
lib/bug.c | 10 ++
lib/kunit/Makefile | 4 +-
lib/kunit/backtrace-suppression-test.c | 184 ++++++++++++++++++++++++++++++++
lib/kunit/bug.c | 115 ++++++++++++++++++++
lib/kunit/hooks-impl.h | 2 +
10 files changed, 571 insertions(+), 8 deletions(-)
---
base-commit: 80234b5ab240f52fa45d201e899e207b9265ef91
change-id: 20260312-kunit_add_support-2f35806b19dd
Best regards,
--
Albert Esteve <aesteve@redhat.com>
^ permalink raw reply
* [PATCH v8 1/4] bug/kunit: Core support for suppressing warning backtraces
From: Albert Esteve @ 2026-05-04 7:41 UTC (permalink / raw)
To: Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti
Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
workflows, linux-riscv, linux-doc, peterz, Alessandro Carminati,
Guenter Roeck, Kees Cook, Albert Esteve
In-Reply-To: <20260504-kunit_add_support-v8-0-3e5957cdd235@redhat.com>
From: Alessandro Carminati <acarmina@redhat.com>
Some unit tests intentionally trigger warning backtraces by passing bad
parameters to kernel API functions. Such unit tests typically check the
return value from such calls, not the existence of the warning backtrace.
Such intentionally generated warning backtraces are neither desirable
nor useful for a number of reasons:
- They can result in overlooked real problems.
- A warning that suddenly starts to show up in unit tests needs to be
investigated and has to be marked to be ignored, for example by
adjusting filter scripts. Such filters are ad hoc because there is
no real standard format for warnings. On top of that, such filter
scripts would require constant maintenance.
Solve the problem by providing a means to suppress warning backtraces
originating from the current kthread while executing test code. Since
each KUnit test runs in its own kthread, this effectively scopes
suppression to the test that enabled it. Limit changes to generic code
to the absolute minimum.
Implementation details:
Suppression is integrated into the existing KUnit hooks infrastructure
in test-bug.h, reusing the kunit_running static branch for zero
overhead when no tests are running.
Suppression is checked at three points in the warning path:
- In warn_slowpath_fmt(), the check runs before any output, fully
suppressing both message and backtrace. This covers architectures
without __WARN_FLAGS.
- In __warn_printk(), the check suppresses the warning message text.
This covers architectures that define __WARN_FLAGS but not their own
__WARN_printf (arm64, loongarch, parisc, powerpc, riscv, sh), where
the message is printed before the trap enters __report_bug().
- In __report_bug(), the check runs before __warn() is called,
suppressing the backtrace and stack dump.
To avoid double-counting on architectures where both __warn_printk()
and __report_bug() run for the same warning, kunit_is_suppressed_warning()
takes a bool parameter: true to increment the suppression counter
(used in warn_slowpath_fmt and __report_bug), false to check only
(used in __warn_printk).
The suppression state is dynamically allocated via kunit_kzalloc() and
tied to the KUnit test lifecycle via kunit_add_action(), ensuring
automatic cleanup at test exit. Writer-side access to the global
suppression list is serialized with a spinlock; readers use RCU.
Three API forms are provided:
- kunit_warning_suppress(test) { ... }: scoped, uses __cleanup for
automatic teardown on scope exit, kunit_add_action() as safety net
for abnormal exits (e.g. kthread_exit from failed assertions).
Suppression handle is only accessible inside the block.
- KUNIT_START/END_SUPPRESSED_WARNING(test): manual macros for larger
blocks or when warning counts need to be checked after suppression
ends. Limited to one pair per scope.
- kunit_start/end_suppress_warning(test): direct functions returning
an explicit handle, for retaining the handle within the test,
or for cross-function usage.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina@redhat.com>
Reviewed-by: Kees Cook <kees@kernel.org>
Signed-off-by: Albert Esteve <aesteve@redhat.com>
---
include/kunit/test-bug.h | 25 +++++++++
include/kunit/test.h | 138 +++++++++++++++++++++++++++++++++++++++++++++++
kernel/panic.c | 15 +++++-
lib/bug.c | 10 ++++
lib/kunit/Makefile | 3 +-
lib/kunit/bug.c | 115 +++++++++++++++++++++++++++++++++++++++
lib/kunit/hooks-impl.h | 2 +
7 files changed, 305 insertions(+), 3 deletions(-)
diff --git a/include/kunit/test-bug.h b/include/kunit/test-bug.h
index 47aa8f21ccce8..6237e48ceadfd 100644
--- a/include/kunit/test-bug.h
+++ b/include/kunit/test-bug.h
@@ -23,6 +23,7 @@ DECLARE_STATIC_KEY_FALSE(kunit_running);
extern struct kunit_hooks_table {
__printf(3, 4) void (*fail_current_test)(const char*, int, const char*, ...);
void *(*get_static_stub_address)(struct kunit *test, void *real_fn_addr);
+ bool (*is_suppressed_warning)(bool count);
} kunit_hooks;
/**
@@ -60,9 +61,33 @@ static inline struct kunit *kunit_get_current_test(void)
} \
} while (0)
+/**
+ * kunit_is_suppressed_warning() - Check if warnings are being suppressed
+ * by the current KUnit test.
+ * @count: if true, increment the suppression counter on match.
+ *
+ * Returns true if the current task has active warning suppression.
+ * Uses the kunit_running static branch for zero overhead when no tests run.
+ *
+ * A single WARN*() may traverse multiple call sites in the warning path
+ * (e.g., __warn_printk() and __report_bug()). Pass @count = true at the
+ * primary suppression point to count each warning exactly once, and
+ * @count = false at secondary points to suppress output without
+ * inflating the count.
+ */
+static inline bool kunit_is_suppressed_warning(bool count)
+{
+ if (!static_branch_unlikely(&kunit_running))
+ return false;
+
+ return kunit_hooks.is_suppressed_warning &&
+ kunit_hooks.is_suppressed_warning(count);
+}
+
#else
static inline struct kunit *kunit_get_current_test(void) { return NULL; }
+static inline bool kunit_is_suppressed_warning(bool count) { return false; }
#define kunit_fail_current_test(fmt, ...) do {} while (0)
diff --git a/include/kunit/test.h b/include/kunit/test.h
index 9cd1594ab697d..f278ec028019c 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -1795,4 +1795,142 @@ do { \
// include resource.h themselves if they need it.
#include <kunit/resource.h>
+/*
+ * Warning backtrace suppression API.
+ *
+ * Suppresses WARN*() backtraces on the current task while active. Three forms
+ * are provided, in order of convenience:
+ *
+ * - Scoped: kunit_warning_suppress(test) { ... }
+ * Suppression is active for the duration of the block. On normal exit,
+ * the for-loop increment deactivates suppression. On early exit (break,
+ * return, goto), the __cleanup attribute fires. On kthread_exit() (e.g.,
+ * a failed KUnit assertion), kunit_add_action() cleans up at test
+ * teardown. The suppression handle is only accessible inside the block,
+ * so warning counts must be checked before the block exits.
+ *
+ * - Manual macros: KUNIT_[START|END]_SUPPRESSED_WARNING(test)
+ * Suppression spans an explicit range in the same scope. kunit_add_action()
+ * guarantees cleanup even if KUNIT_END_SUPPRESSED_WARNING() is not reached.
+ * Prefer this form when suppressing warnings across a large block where
+ * extra indentation is undesirable, or when the warning count needs to be
+ * checked after suppression ends. Limited to one pair per scope.
+ *
+ * - Direct: kunit_start_suppress_warning() / kunit_end_suppress_warning()
+ * The underlying functions, returning an explicit handle pointer. Use
+ * when the handle needs to be retained (e.g., for post-suppression
+ * count checks) or passed across helper functions.
+ */
+struct kunit_suppressed_warning;
+
+struct kunit_suppressed_warning *
+kunit_start_suppress_warning(struct kunit *test);
+void kunit_end_suppress_warning(struct kunit *test,
+ struct kunit_suppressed_warning *w);
+int kunit_suppressed_warning_count(struct kunit_suppressed_warning *w);
+void __kunit_suppress_auto_cleanup(struct kunit_suppressed_warning **wp);
+bool kunit_has_active_suppress_warning(void);
+
+/**
+ * kunit_warning_suppress() - Suppress WARN*() backtraces for the duration
+ * of a block.
+ * @test: The test context object.
+ *
+ * Scoped form of the suppression API. Suppression starts when the block is
+ * entered and ends automatically when the block exits through any path. See
+ * the section comment above for the cleanup guarantees on each exit path.
+ * Fails the test if suppression is already active; nesting is not supported.
+ *
+ * The warning count can be checked inside the block via
+ * KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(). The handle is not accessible
+ * after the block exits.
+ *
+ * Example::
+ *
+ * kunit_warning_suppress(test) {
+ * trigger_warning();
+ * KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
+ * }
+ */
+#define kunit_warning_suppress(test) \
+ for (struct kunit_suppressed_warning *__kunit_suppress \
+ __cleanup(__kunit_suppress_auto_cleanup) = \
+ kunit_start_suppress_warning(test); \
+ __kunit_suppress; \
+ kunit_end_suppress_warning(test, __kunit_suppress), \
+ __kunit_suppress = NULL)
+
+/**
+ * KUNIT_START_SUPPRESSED_WARNING() - Begin suppressing WARN*() backtraces.
+ * @test: The test context object.
+ *
+ * Manual form of the suppression API. Must be paired with
+ * KUNIT_END_SUPPRESSED_WARNING() in the same scope. See the section comment
+ * above for cleanup guarantees. Fails the test if suppression is already
+ * active; nesting is not supported. Limited to one pair per scope; use
+ * sequential kunit_warning_suppress() blocks or the direct function API
+ * when more than one suppression region is needed.
+ *
+ * Example::
+ *
+ * KUNIT_START_SUPPRESSED_WARNING(test);
+ * trigger_code_that_should_warn_once();
+ * KUNIT_END_SUPPRESSED_WARNING(test);
+ * KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
+ */
+#define KUNIT_START_SUPPRESSED_WARNING(test) \
+ struct kunit_suppressed_warning *__kunit_suppress = \
+ kunit_start_suppress_warning(test)
+
+/**
+ * KUNIT_END_SUPPRESSED_WARNING() - End suppressing WARN*() backtraces.
+ * @test: The test context object.
+ *
+ * Deactivates suppression started by KUNIT_START_SUPPRESSED_WARNING().
+ * The warning count remains readable via KUNIT_SUPPRESSED_WARNING_COUNT()
+ * after this call.
+ */
+#define KUNIT_END_SUPPRESSED_WARNING(test) \
+ kunit_end_suppress_warning(test, __kunit_suppress)
+
+/**
+ * KUNIT_SUPPRESSED_WARNING_COUNT() - Returns the suppressed warning count.
+ *
+ * Returns the number of WARN*() calls suppressed since the current
+ * suppression block started, or 0 if the handle is NULL. Usable inside a
+ * kunit_warning_suppress() block or after KUNIT_END_SUPPRESSED_WARNING().
+ */
+#define KUNIT_SUPPRESSED_WARNING_COUNT() \
+ kunit_suppressed_warning_count(__kunit_suppress)
+
+/**
+ * KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT() - Sets an expectation that the
+ * suppressed warning count equals
+ * @expected.
+ * @test: The test context object.
+ * @expected: an expression that evaluates to the expected warning count.
+ *
+ * Sets an expectation that the number of suppressed WARN*() calls equals
+ * @expected. This is semantically equivalent to
+ * KUNIT_EXPECT_EQ(@test, KUNIT_SUPPRESSED_WARNING_COUNT(), @expected).
+ * See KUNIT_EXPECT_EQ() for more information.
+ */
+#define KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, expected) \
+ KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), expected)
+
+/**
+ * KUNIT_ASSERT_SUPPRESSED_WARNING_COUNT() - Sets an assertion that the
+ * suppressed warning count equals
+ * @expected.
+ * @test: The test context object.
+ * @expected: an expression that evaluates to the expected warning count.
+ *
+ * Sets an assertion that the number of suppressed WARN*() calls equals
+ * @expected. This is the same as KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(),
+ * except it causes an assertion failure (see KUNIT_ASSERT_TRUE()) when the
+ * assertion is not met.
+ */
+#define KUNIT_ASSERT_SUPPRESSED_WARNING_COUNT(test, expected) \
+ KUNIT_ASSERT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), expected)
+
#endif /* _KUNIT_TEST_H */
diff --git a/kernel/panic.c b/kernel/panic.c
index c78600212b6c1..697d8ca054bef 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -39,6 +39,7 @@
#include <linux/sys_info.h>
#include <trace/events/error_report.h>
#include <asm/sections.h>
+#include <kunit/test-bug.h>
#define PANIC_TIMER_STEP 100
#define PANIC_BLINK_SPD 18
@@ -1080,9 +1081,14 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
void warn_slowpath_fmt(const char *file, int line, unsigned taint,
const char *fmt, ...)
{
- bool rcu = warn_rcu_enter();
+ bool rcu;
struct warn_args args;
+ if (kunit_is_suppressed_warning(true))
+ return;
+
+ rcu = warn_rcu_enter();
+
pr_warn(CUT_HERE);
if (!fmt) {
@@ -1102,9 +1108,14 @@ EXPORT_SYMBOL(warn_slowpath_fmt);
#else
void __warn_printk(const char *fmt, ...)
{
- bool rcu = warn_rcu_enter();
+ bool rcu;
va_list args;
+ if (kunit_is_suppressed_warning(false))
+ return;
+
+ rcu = warn_rcu_enter();
+
pr_warn(CUT_HERE);
va_start(args, fmt);
diff --git a/lib/bug.c b/lib/bug.c
index 623c467a8b76c..a5cebde554ed8 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -48,6 +48,7 @@
#include <linux/rculist.h>
#include <linux/ftrace.h>
#include <linux/context_tracking.h>
+#include <kunit/test-bug.h>
extern struct bug_entry __start___bug_table[], __stop___bug_table[];
@@ -223,6 +224,15 @@ static enum bug_trap_type __report_bug(struct bug_entry *bug, unsigned long buga
no_cut = bug->flags & BUGFLAG_NO_CUT_HERE;
has_args = bug->flags & BUGFLAG_ARGS;
+#ifdef CONFIG_KUNIT
+ /*
+ * Before the once logic so suppressed warnings do not consume
+ * the single-fire budget of WARN_ON_ONCE().
+ */
+ if (warning && kunit_is_suppressed_warning(true))
+ return BUG_TRAP_TYPE_WARN;
+#endif
+
if (warning && once) {
if (done)
return BUG_TRAP_TYPE_WARN;
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 656f1fa35abcc..4592f9d0aa8dd 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -10,7 +10,8 @@ kunit-objs += test.o \
executor.o \
attributes.o \
device.o \
- platform.o
+ platform.o \
+ bug.o
ifeq ($(CONFIG_KUNIT_DEBUGFS),y)
kunit-objs += debugfs.o
diff --git a/lib/kunit/bug.c b/lib/kunit/bug.c
new file mode 100644
index 0000000000000..b0b6778d7399a
--- /dev/null
+++ b/lib/kunit/bug.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit helpers for backtrace suppression
+ *
+ * Copyright (C) 2025 Alessandro Carminati <acarmina@redhat.com>
+ * Copyright (C) 2024 Guenter Roeck <linux@roeck-us.net>
+ */
+
+#include <kunit/resource.h>
+#include <linux/export.h>
+#include <linux/rculist.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#include "hooks-impl.h"
+
+struct kunit_suppressed_warning {
+ struct list_head node;
+ struct task_struct *task;
+ struct kunit *test;
+ int counter;
+};
+
+static LIST_HEAD(suppressed_warnings);
+static DEFINE_SPINLOCK(suppressed_warnings_lock);
+
+static void kunit_suppress_warning_remove(struct kunit_suppressed_warning *w)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&suppressed_warnings_lock, flags);
+ list_del_rcu(&w->node);
+ spin_unlock_irqrestore(&suppressed_warnings_lock, flags);
+ synchronize_rcu(); /* Wait for readers to finish */
+}
+
+KUNIT_DEFINE_ACTION_WRAPPER(kunit_suppress_warning_cleanup,
+ kunit_suppress_warning_remove,
+ struct kunit_suppressed_warning *);
+
+bool kunit_has_active_suppress_warning(void)
+{
+ return __kunit_is_suppressed_warning_impl(false);
+}
+EXPORT_SYMBOL_GPL(kunit_has_active_suppress_warning);
+
+struct kunit_suppressed_warning *
+kunit_start_suppress_warning(struct kunit *test)
+{
+ struct kunit_suppressed_warning *w;
+ unsigned long flags;
+ int ret;
+
+ if (kunit_has_active_suppress_warning()) {
+ KUNIT_FAIL(test, "Another suppression block is already active");
+ return NULL;
+ }
+
+ w = kunit_kzalloc(test, sizeof(*w), GFP_KERNEL);
+ if (!w)
+ return NULL;
+
+ w->task = current;
+ w->test = test;
+
+ spin_lock_irqsave(&suppressed_warnings_lock, flags);
+ list_add_rcu(&w->node, &suppressed_warnings);
+ spin_unlock_irqrestore(&suppressed_warnings_lock, flags);
+
+ ret = kunit_add_action_or_reset(test,
+ kunit_suppress_warning_cleanup, w);
+ if (ret)
+ return NULL;
+
+ return w;
+}
+EXPORT_SYMBOL_GPL(kunit_start_suppress_warning);
+
+void kunit_end_suppress_warning(struct kunit *test,
+ struct kunit_suppressed_warning *w)
+{
+ if (!w)
+ return;
+ kunit_release_action(test, kunit_suppress_warning_cleanup, w);
+}
+EXPORT_SYMBOL_GPL(kunit_end_suppress_warning);
+
+void __kunit_suppress_auto_cleanup(struct kunit_suppressed_warning **wp)
+{
+ if (*wp)
+ kunit_end_suppress_warning((*wp)->test, *wp);
+}
+EXPORT_SYMBOL_GPL(__kunit_suppress_auto_cleanup);
+
+int kunit_suppressed_warning_count(struct kunit_suppressed_warning *w)
+{
+ return w ? w->counter : 0;
+}
+EXPORT_SYMBOL_GPL(kunit_suppressed_warning_count);
+
+bool __kunit_is_suppressed_warning_impl(bool count)
+{
+ struct kunit_suppressed_warning *w;
+
+ guard(rcu)();
+ list_for_each_entry_rcu(w, &suppressed_warnings, node) {
+ if (w->task == current) {
+ if (count)
+ w->counter++;
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/lib/kunit/hooks-impl.h b/lib/kunit/hooks-impl.h
index 4e71b2d0143ba..d8720f2616925 100644
--- a/lib/kunit/hooks-impl.h
+++ b/lib/kunit/hooks-impl.h
@@ -19,6 +19,7 @@ void __printf(3, 4) __kunit_fail_current_test_impl(const char *file,
int line,
const char *fmt, ...);
void *__kunit_get_static_stub_address_impl(struct kunit *test, void *real_fn_addr);
+bool __kunit_is_suppressed_warning_impl(bool count);
/* Code to set all of the function pointers. */
static inline void kunit_install_hooks(void)
@@ -26,6 +27,7 @@ static inline void kunit_install_hooks(void)
/* Install the KUnit hook functions. */
kunit_hooks.fail_current_test = __kunit_fail_current_test_impl;
kunit_hooks.get_static_stub_address = __kunit_get_static_stub_address_impl;
+ kunit_hooks.is_suppressed_warning = __kunit_is_suppressed_warning_impl;
}
#endif /* _KUNIT_HOOKS_IMPL_H */
--
2.53.0
^ permalink raw reply related
* [PATCH v8 2/4] kunit: Add backtrace suppression self-tests
From: Albert Esteve @ 2026-05-04 7:41 UTC (permalink / raw)
To: Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti
Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
workflows, linux-riscv, linux-doc, peterz, Guenter Roeck,
Linux Kernel Functional Testing, Dan Carpenter,
Alessandro Carminati, Albert Esteve, Kees Cook
In-Reply-To: <20260504-kunit_add_support-v8-0-3e5957cdd235@redhat.com>
From: Guenter Roeck <linux@roeck-us.net>
Add unit tests to verify that warning backtrace suppression works.
Tests cover all three API forms:
- Scoped: kunit_warning_suppress() with in-block count verification
and post-block inactivity check.
- Manual macros: KUNIT_START/END_SUPPRESSED_WARNING() with WARN()
and WARN_ON(), both direct and through helper functions, as well
as multiple warnings in a single block.
- Direct functions: kunit_start/end_suppress_warning() with
sequential independent suppression blocks and per-block counts.
Furthermore, tests verify incremental warning counting, that
kunit_has_active_suppress_warning() transitions correctly around
suppression boundaries, and that suppression active in the test
kthread does not leak to a separate kthread.
If backtrace suppression does _not_ work, the unit tests will likely
trigger unsuppressed backtraces, which should actually help to get
the affected architectures / platforms fixed.
Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
Acked-by: Dan Carpenter <dan.carpenter@linaro.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina@redhat.com>
Reviewed-by: David Gow <david@davidgow.net>
Signed-off-by: Albert Esteve <aesteve@redhat.com>
---
lib/kunit/Makefile | 1 +
lib/kunit/backtrace-suppression-test.c | 184 +++++++++++++++++++++++++++++++++
2 files changed, 185 insertions(+)
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 4592f9d0aa8dd..2e8a6b71a2ab0 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -22,6 +22,7 @@ obj-$(if $(CONFIG_KUNIT),y) += hooks.o
obj-$(CONFIG_KUNIT_TEST) += kunit-test.o
obj-$(CONFIG_KUNIT_TEST) += platform-test.o
+obj-$(CONFIG_KUNIT_TEST) += backtrace-suppression-test.o
# string-stream-test compiles built-in only.
ifeq ($(CONFIG_KUNIT_TEST),y)
diff --git a/lib/kunit/backtrace-suppression-test.c b/lib/kunit/backtrace-suppression-test.c
new file mode 100644
index 0000000000000..0e6fb685d2cbb
--- /dev/null
+++ b/lib/kunit/backtrace-suppression-test.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit test for suppressing warning tracebacks.
+ *
+ * Copyright (C) 2024, Guenter Roeck
+ * Author: Guenter Roeck <linux@roeck-us.net>
+ */
+
+#include <kunit/test.h>
+#include <linux/bug.h>
+#include <linux/completion.h>
+#include <linux/kthread.h>
+
+static void backtrace_suppression_test_warn_direct(struct kunit *test)
+{
+ kunit_warning_suppress(test) {
+ WARN(1, "This backtrace should be suppressed");
+ /*
+ * Count must be checked inside the scope; the handle
+ * is not accessible after the block exits.
+ */
+ KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
+ }
+ KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());
+}
+
+static void trigger_backtrace_warn(void)
+{
+ WARN(1, "This backtrace should be suppressed");
+}
+
+static void backtrace_suppression_test_warn_indirect(struct kunit *test)
+{
+ KUNIT_START_SUPPRESSED_WARNING(test);
+ trigger_backtrace_warn();
+ KUNIT_END_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
+}
+
+static void backtrace_suppression_test_warn_multi(struct kunit *test)
+{
+ KUNIT_START_SUPPRESSED_WARNING(test);
+ WARN(1, "This backtrace should be suppressed");
+ trigger_backtrace_warn();
+ KUNIT_END_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 2);
+}
+
+static void backtrace_suppression_test_warn_on_direct(struct kunit *test)
+{
+ if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE) && !IS_ENABLED(CONFIG_KALLSYMS))
+ kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE or CONFIG_KALLSYMS");
+
+ KUNIT_START_SUPPRESSED_WARNING(test);
+ WARN_ON(1);
+ KUNIT_END_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
+}
+
+static void trigger_backtrace_warn_on(void)
+{
+ WARN_ON(1);
+}
+
+static void backtrace_suppression_test_warn_on_indirect(struct kunit *test)
+{
+ if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE))
+ kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE");
+
+ KUNIT_START_SUPPRESSED_WARNING(test);
+ trigger_backtrace_warn_on();
+ KUNIT_END_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
+}
+
+static void backtrace_suppression_test_count(struct kunit *test)
+{
+ KUNIT_START_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 0);
+
+ WARN(1, "suppressed");
+ KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
+
+ WARN(1, "suppressed again");
+ KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 2);
+
+ KUNIT_END_SUPPRESSED_WARNING(test);
+}
+
+static void backtrace_suppression_test_active_state(struct kunit *test)
+{
+ KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());
+
+ KUNIT_START_SUPPRESSED_WARNING(test);
+ KUNIT_EXPECT_TRUE(test, kunit_has_active_suppress_warning());
+ KUNIT_END_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());
+
+ kunit_warning_suppress(test) {
+ KUNIT_EXPECT_TRUE(test, kunit_has_active_suppress_warning());
+ }
+
+ KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());
+}
+
+static void backtrace_suppression_test_multi_scope(struct kunit *test)
+{
+ struct kunit_suppressed_warning *sw1, *sw2;
+
+ if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE))
+ kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE");
+
+ sw1 = kunit_start_suppress_warning(test);
+ trigger_backtrace_warn_on();
+ WARN(1, "suppressed by sw1");
+ kunit_end_suppress_warning(test, sw1);
+
+ sw2 = kunit_start_suppress_warning(test);
+ WARN(1, "suppressed by sw2");
+ kunit_end_suppress_warning(test, sw2);
+
+ KUNIT_EXPECT_EQ(test, kunit_suppressed_warning_count(sw1), 2);
+ KUNIT_EXPECT_EQ(test, kunit_suppressed_warning_count(sw2), 1);
+}
+
+struct cross_kthread_data {
+ bool was_active;
+ struct completion done;
+};
+
+static int cross_kthread_fn(void *data)
+{
+ struct cross_kthread_data *d = data;
+
+ d->was_active = kunit_has_active_suppress_warning();
+ complete(&d->done);
+ return 0;
+}
+
+static void backtrace_suppression_test_cross_kthread(struct kunit *test)
+{
+ struct cross_kthread_data data;
+ struct task_struct *task;
+
+ init_completion(&data.done);
+
+ KUNIT_START_SUPPRESSED_WARNING(test);
+
+ task = kthread_run(cross_kthread_fn, &data, "kunit-cross-test");
+ KUNIT_ASSERT_FALSE(test, IS_ERR(task));
+ wait_for_completion(&data.done);
+
+ KUNIT_END_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_FALSE(test, data.was_active);
+}
+
+static struct kunit_case backtrace_suppression_test_cases[] = {
+ KUNIT_CASE(backtrace_suppression_test_warn_direct),
+ KUNIT_CASE(backtrace_suppression_test_warn_indirect),
+ KUNIT_CASE(backtrace_suppression_test_warn_multi),
+ KUNIT_CASE(backtrace_suppression_test_warn_on_direct),
+ KUNIT_CASE(backtrace_suppression_test_warn_on_indirect),
+ KUNIT_CASE(backtrace_suppression_test_count),
+ KUNIT_CASE(backtrace_suppression_test_active_state),
+ KUNIT_CASE(backtrace_suppression_test_multi_scope),
+ KUNIT_CASE(backtrace_suppression_test_cross_kthread),
+ {}
+};
+
+static struct kunit_suite backtrace_suppression_test_suite = {
+ .name = "backtrace-suppression-test",
+ .test_cases = backtrace_suppression_test_cases,
+};
+kunit_test_suites(&backtrace_suppression_test_suite);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("KUnit test to verify warning backtrace suppression");
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox