* Re: [PATCH 3/3] kallsyms: delta-compress lineinfo tables for ~2.7x size reduction
From: Vivian Wang @ 2026-03-11 3:34 UTC (permalink / raw)
To: Sasha Levin, Andrew Morton, Masahiro Yamada, Luis Chamberlain,
Linus Torvalds, Richard Weinberger, Juergen Gross,
Geert Uytterhoeven, James Bottomley
Cc: Jonathan Corbet, Nathan Chancellor, Nicolas Schier, Petr Pavlu,
Daniel Gomez, Greg KH, Petr Mladek, Steven Rostedt, Kees Cook,
Peter Zijlstra, Thorsten Leemhuis, Vlastimil Babka, linux-kernel,
linux-kbuild, linux-modules, linux-doc
In-Reply-To: <20260303182103.3523438-4-sashal@kernel.org>
Hi Sasha,
I've been trying this out and AFAICT this does work perfectly. Thank you
for this.
There are a few oddities I found:
Firstly I've been building with something like O=_riscv out of
convenience, and the file names have an extra ../ in the front. (This is
just me exiting out of init=/bin/sh.)
[ 2.317268] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000
[ 2.320283] CPU: 0 UID: 0 PID: 1 Comm: sh Not tainted 7.0.0-rc3-00004-g8ad18f1a1a2f #31 PREEMPTLAZY
[ 2.322048] Hardware name: riscv-virtio,qemu (DT)
[ 2.323220] Call Trace:
[ 2.324465] [<ffffffff800172a8>] dump_backtrace+0x1c/0x24 (../arch/riscv/kernel/stacktrace.c:150)
[ 2.329061] [<ffffffff8000241e>] show_stack+0x2a/0x34 (../arch/riscv/kernel/stacktrace.c:156)
[ 2.330334] [<ffffffff8000fe32>] dump_stack_lvl+0x4a/0x68 (../lib/dump_stack.c:122)
[ 2.331462] [<ffffffff8000fe64>] dump_stack+0x14/0x1c (../lib/dump_stack.c:130)
[ 2.332571] [<ffffffff80002a88>] vpanic+0x108/0x2bc (../kernel/panic.c:651)
[ 2.333674] [<ffffffff80002c6e>] panic+0x32/0x34 (../kernel/panic.c:787)
[ 2.334427] [<ffffffff8002e97a>] do_exit+0x7ee/0x7f4 (../kernel/exit.c:930)
[ 2.335194] [<ffffffff8002eade>] do_group_exit+0x1a/0x88 (../kernel/exit.c:1099)
[ 2.335945] [<ffffffff8002eb62>] __riscv_sys_exit_group+0x16/0x18 (../kernel/exit.c:1129)
[ 2.336763] [<ffffffff80b3e868>] do_trap_ecall_u+0x260/0x45c (../arch/riscv/include/asm/syscall.h:112)
[ 2.337765] [<ffffffff80b4c034>] handle_exception+0x168/0x174 (../arch/riscv/kernel/entry.S:233)
This is fine by me, but I've seen mentions of O= builds but I'm not sure
if it's expected.
Also, toggling CONFIG_KALLSYMS_LINEINFO seems to rebuild every single
file. I haven't debugged why, but is this expected?
I have a few ideas about the code as well. Since this patch 3 touches
most of the files involved, I'll just dump my thoughts on the whole
series here. I want to note that I haven't read the RFC thread too
carefully, but I don't think there were many comments on the implementation.
On 3/4/26 02:21, Sasha Levin wrote:
> Replace the flat uncompressed parallel arrays (lineinfo_addrs[],
> lineinfo_file_ids[], lineinfo_lines[]) with a block-indexed,
> delta-encoded, ULEB128 varint compressed format.
>
> The sorted address array has small deltas between consecutive entries
> (typically 1-50 bytes), file IDs have high locality (delta often 0,
> same file), and line numbers change slowly. Delta-encoding followed
> by ULEB128 varint compression shrinks most values from 4 bytes to 1.
>
> Entries are grouped into blocks of 64. A small uncompressed block
> index (first addr + byte offset per block) enables O(log(N/64)) binary
> search, followed by sequential decode of at most 64 varints within the
> matching block. All decode state lives on the stack -- zero
> allocations, still safe for NMI/panic context.
>
> Measured on a defconfig+debug x86_64 build (3,017,154 entries, 4,822
> source files, 47,144 blocks):
>
> Before (flat arrays):
> lineinfo_addrs[] 12,068,616 bytes (u32 x 3.0M)
> lineinfo_file_ids[] 6,034,308 bytes (u16 x 3.0M)
> lineinfo_lines[] 12,068,616 bytes (u32 x 3.0M)
> Total: 30,171,540 bytes (28.8 MiB, 10.0 bytes/entry)
>
> After (block-indexed delta + ULEB128):
> lineinfo_block_addrs[] 188,576 bytes (184 KiB)
> lineinfo_block_offsets[] 188,576 bytes (184 KiB)
> lineinfo_data[] 10,926,128 bytes (10.4 MiB)
> Total: 11,303,280 bytes (10.8 MiB, 3.7 bytes/entry)
>
> Savings: 18.0 MiB (2.7x reduction)
>
> Booted in QEMU and verified with SysRq-l that annotations still work:
>
> default_idle+0x9/0x10 (arch/x86/kernel/process.c:767)
> default_idle_call+0x6c/0xb0 (kernel/sched/idle.c:122)
> do_idle+0x335/0x490 (kernel/sched/idle.c:191)
> cpu_startup_entry+0x4e/0x60 (kernel/sched/idle.c:429)
> rest_init+0x1aa/0x1b0 (init/main.c:760)
>
> Suggested-by: Juergen Gross <jgross@suse.com>
> Assisted-by: Claude:claude-opus-4-6
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
> .../admin-guide/kallsyms-lineinfo.rst | 7 +-
> include/linux/mod_lineinfo.h | 103 ++++++++--
> init/Kconfig | 8 +-
> kernel/kallsyms.c | 91 +++++++--
> kernel/kallsyms_internal.h | 7 +-
> kernel/module/kallsyms.c | 107 +++++++---
> scripts/gen_lineinfo.c | 192 ++++++++++++++----
> scripts/kallsyms.c | 7 +-
> scripts/link-vmlinux.sh | 16 +-
> 9 files changed, 423 insertions(+), 115 deletions(-)
>
> diff --git a/Documentation/admin-guide/kallsyms-lineinfo.rst b/Documentation/admin-guide/kallsyms-lineinfo.rst
> index 21450569d5324..fe92c5dde16b3 100644
> --- a/Documentation/admin-guide/kallsyms-lineinfo.rst
> +++ b/Documentation/admin-guide/kallsyms-lineinfo.rst
> @@ -76,10 +76,11 @@ Memory Overhead
> ===============
>
> The vmlinux lineinfo tables are stored in ``.rodata`` and typically add
> -approximately 44 MiB to the kernel image for a standard configuration
> -(~4.6 million DWARF line entries, ~10 bytes per entry after deduplication).
> +approximately 10-15 MiB to the kernel image for a standard configuration
> +(~4.6 million DWARF line entries, ~2-3 bytes per entry after delta
> +compression).
>
> -Per-module lineinfo adds approximately 10 bytes per DWARF line entry to each
> +Per-module lineinfo adds approximately 2-3 bytes per DWARF line entry to each
> ``.ko`` file.
>
Maybe this could be given in terms of percentages? It wasn't obvious to
me what 10-15 MiB amounts to.
On riscv64, I'm seeing a 24.2 MiB to 30.2 MiB increase in
arch/riscv/boot/Image size on an approximately defconfig+mod2noconfig
build, which is about a 25% increase. I haven't checked yet, but if 25%
is similar to what other archs get, that's a more useful figure than
10-15 MiB, given that the size increase is correlated to the total
amount of code linked into the kernel/module.
> Known Limitations
> diff --git a/include/linux/mod_lineinfo.h b/include/linux/mod_lineinfo.h
> index d62e9608f0f82..ab758acfadceb 100644
> --- a/include/linux/mod_lineinfo.h
> +++ b/include/linux/mod_lineinfo.h
> @@ -8,13 +8,19 @@
> *
> * Section layout (all values in target-native endianness):
> *
> - * struct mod_lineinfo_header (16 bytes)
> - * u32 addrs[num_entries] -- offsets from .text base, sorted
> - * u16 file_ids[num_entries] -- parallel to addrs
> - * <2-byte pad if num_entries is odd>
> - * u32 lines[num_entries] -- parallel to addrs
> + * struct mod_lineinfo_header (24 bytes)
> + * u32 block_addrs[num_blocks] -- first addr per block, for binary search
> + * u32 block_offsets[num_blocks] -- byte offset into compressed data stream
> + * u8 data[data_size] -- ULEB128 delta-compressed entries
> * u32 file_offsets[num_files] -- byte offset into filenames[]
> * char filenames[filenames_size] -- concatenated NUL-terminated strings
> + *
> + * Compressed stream format (per block of LINEINFO_BLOCK_ENTRIES entries):
> + * Entry 0: file_id (ULEB128), line (ULEB128)
> + * addr is in block_addrs[]
> + * Entry 1..N: addr_delta (ULEB128),
> + * file_id_delta (zigzag-encoded ULEB128),
> + * line_delta (zigzag-encoded ULEB128)
> */
> #ifndef _LINUX_MOD_LINEINFO_H
> #define _LINUX_MOD_LINEINFO_H
> @@ -25,44 +31,107 @@
> #include <stdint.h>
> typedef uint32_t u32;
> typedef uint16_t u16;
> +typedef uint8_t u8;
> #endif
>
> +#define LINEINFO_BLOCK_ENTRIES 64
> +
> struct mod_lineinfo_header {
> u32 num_entries;
> u32 num_files;
> u32 filenames_size; /* total bytes of concatenated filenames */
> + u32 num_blocks;
> + u32 data_size; /* total bytes of compressed data stream */
> u32 reserved; /* padding, must be 0 */
> };
>
> /* Offset helpers: compute byte offset from start of section to each array */
>
> -static inline u32 mod_lineinfo_addrs_off(void)
> +static inline u32 mod_lineinfo_block_addrs_off(void)
> {
> return sizeof(struct mod_lineinfo_header);
> }
>
> -static inline u32 mod_lineinfo_file_ids_off(u32 num_entries)
> +static inline u32 mod_lineinfo_block_offsets_off(u32 num_blocks)
> {
> - return mod_lineinfo_addrs_off() + num_entries * sizeof(u32);
> + return mod_lineinfo_block_addrs_off() + num_blocks * sizeof(u32);
> }
>
> -static inline u32 mod_lineinfo_lines_off(u32 num_entries)
> +static inline u32 mod_lineinfo_data_off(u32 num_blocks)
> {
> - /* u16 file_ids[] may need 2-byte padding to align lines[] to 4 bytes */
> - u32 off = mod_lineinfo_file_ids_off(num_entries) +
> - num_entries * sizeof(u16);
> - return (off + 3) & ~3u;
> + return mod_lineinfo_block_offsets_off(num_blocks) +
> + num_blocks * sizeof(u32);
> }
>
> -static inline u32 mod_lineinfo_file_offsets_off(u32 num_entries)
> +static inline u32 mod_lineinfo_file_offsets_off(u32 num_blocks, u32 data_size)
> {
> - return mod_lineinfo_lines_off(num_entries) + num_entries * sizeof(u32);
> + return mod_lineinfo_data_off(num_blocks) + data_size;
> }
>
> -static inline u32 mod_lineinfo_filenames_off(u32 num_entries, u32 num_files)
> +static inline u32 mod_lineinfo_filenames_off(u32 num_blocks, u32 data_size,
> + u32 num_files)
> {
> - return mod_lineinfo_file_offsets_off(num_entries) +
> + return mod_lineinfo_file_offsets_off(num_blocks, data_size) +
> num_files * sizeof(u32);
> }
>
I wonder if these headers could use a slightly simpler representation,
with each part represented with its offset from header start and total
size in bytes, a bit like flattened devicetrees. So like, blocks_offset,
blocks_size, files_offset, files_size...
This would make the assembly generation below more readable, and IMO
make understanding offset and array bound calculations way simpler, at
the cost of a few extra words in the header.
(Re: array bounds, I know there are easier ways to break the kernel
intentionally if you're writing kernel code. but these things that run
in the "ouch something bad happened" cases really should be a bit more
defensive against possibly bad data, esp. in dealing with loadable
modules. I haven't looked closely to the in-kernel lookup code, but I
don't see much sanity checks against lineinfo data? I *think* for
badly-sorted binary search just spits out a nonsensical offset, but I
really don't want to find out what happens to the whole
binary-then-linear search code with negative sizes or out-of-bounds
offsets or something like that.)
> +/* Zigzag encoding: map signed to unsigned so small magnitudes are small */
> +static inline u32 zigzag_encode(int32_t v)
> +{
> + return ((u32)v << 1) ^ (u32)(v >> 31);
> +}
> +
> +static inline int32_t zigzag_decode(u32 v)
> +{
> + return (int32_t)((v >> 1) ^ -(v & 1));
> +}
> +
> +/*
> + * Read a ULEB128 varint from a byte stream.
> + * Returns the decoded value and advances *pos past the encoded bytes.
> + * If *pos would exceed 'end', returns 0 and sets *pos = end (safe for
> + * NMI/panic context -- no crash, just a missed annotation).
What does that last bit mean...?
> + */
> +static inline u32 lineinfo_read_uleb128(const u8 *data, u32 *pos, u32 end)
> +{
> + u32 result = 0;
> + unsigned int shift = 0;
> +
> + while (*pos < end) {
> + u8 byte = data[*pos];
> + (*pos)++;
> + result |= (u32)(byte & 0x7f) << shift;
> + if (!(byte & 0x80))
> + return result;
> + shift += 7;
> + if (shift >= 32) {
> + /* Malformed -- skip remaining continuation bytes */
> + while (*pos < end && (data[*pos] & 0x80))
> + (*pos)++;
> + if (*pos < end)
> + (*pos)++;
> + return result;
> + }
> + }
> + return result;
> +}
> +
> +/* Write a ULEB128 varint -- build tool only */
> +#ifndef __KERNEL__
> +static inline unsigned int lineinfo_write_uleb128(u8 *buf, u32 value)
> +{
> + unsigned int len = 0;
> +
> + do {
> + u8 byte = value & 0x7f;
> +
> + value >>= 7;
> + if (value)
> + byte |= 0x80;
> + buf[len++] = byte;
> + } while (value);
> + return len;
> +}
> +#endif /* !__KERNEL__ */
> +
> #endif /* _LINUX_MOD_LINEINFO_H */
> diff --git a/init/Kconfig b/init/Kconfig
> index bf53275bc405a..6e3795b3dbd62 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -2065,8 +2065,9 @@ config KALLSYMS_LINEINFO
> anon_vma_clone+0x2ed/0xcf0 (mm/rmap.c:412)
>
> This requires elfutils (libdw-dev/elfutils-devel) on the build host.
> - Adds approximately 44MB to a typical kernel image (10 bytes per
> - DWARF line-table entry, ~4.6M entries for a typical config).
> + Adds approximately 10-15MB to a typical kernel image (~2-3 bytes
> + per entry after delta compression, ~4.6M entries for a typical
> + config).
>
> If unsure, say N.
>
> @@ -2079,7 +2080,8 @@ config KALLSYMS_LINEINFO_MODULES
> so stack traces from module code include (file.c:123) annotations.
>
> Requires elfutils (libdw-dev/elfutils-devel) on the build host.
> - Increases .ko sizes by approximately 10 bytes per DWARF line entry.
> + Increases .ko sizes by approximately 2-3 bytes per DWARF line
> + entry after delta compression.
>
> If unsure, say N.
>
(Same as above, maybe use percentages when talking about sizes?)
> diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
> index cea74992e5427..de4aa8fcfd69d 100644
> --- a/kernel/kallsyms.c
> +++ b/kernel/kallsyms.c
> @@ -468,14 +468,20 @@ static int append_buildid(char *buffer, const char *modname,
> #endif /* CONFIG_STACKTRACE_BUILD_ID */
>
> #ifdef CONFIG_KALLSYMS_LINEINFO
> +#include <linux/mod_lineinfo.h>
> +
> bool kallsyms_lookup_lineinfo(unsigned long addr, unsigned long sym_start,
> const char **file, unsigned int *line)
> {
[...]
> diff --git a/kernel/kallsyms_internal.h b/kernel/kallsyms_internal.h
> index 868a1d5035212..691be44440395 100644
> --- a/kernel/kallsyms_internal.h
> +++ b/kernel/kallsyms_internal.h
> @@ -17,10 +17,11 @@ extern const u8 kallsyms_seqs_of_names[];
>
> #ifdef CONFIG_KALLSYMS_LINEINFO
> extern const u32 lineinfo_num_entries;
> -extern const u32 lineinfo_addrs[];
> -extern const u16 lineinfo_file_ids[];
> -extern const u32 lineinfo_lines[];
> extern const u32 lineinfo_num_files;
> +extern const u32 lineinfo_num_blocks;
> +extern const u32 lineinfo_block_addrs[];
> +extern const u32 lineinfo_block_offsets[];
> +extern const u8 lineinfo_data[];
> extern const u32 lineinfo_file_offsets[];
> extern const char lineinfo_filenames[];
> #endif
> diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c
> index 7af414bd65e79..0ead1bb69de4e 100644
> --- a/kernel/module/kallsyms.c
> +++ b/kernel/module/kallsyms.c
> @@ -512,15 +512,19 @@ bool module_lookup_lineinfo(struct module *mod, unsigned long addr,
> {
This and kallsyms_lookup_lineinfo() above look like almost exactly the
same code twice. Some refactoring would be nice, just so that others
don't have to read the same code twice, or worse, change the same code
twice later on.
[...]
> diff --git a/scripts/gen_lineinfo.c b/scripts/gen_lineinfo.c
> index 609de59f47ffd..9507ed9bcbe55 100644
> --- a/scripts/gen_lineinfo.c
> +++ b/scripts/gen_lineinfo.c
> @@ -8,6 +8,9 @@
> * file containing sorted lookup tables that the kernel uses to annotate
> * stack traces with source file:line information.
> *
> + * The output uses a block-indexed, delta-encoded, ULEB128-compressed format
> + * for ~3-4x size reduction compared to flat arrays.
> + *
> * Requires libdw from elfutils.
> */
>
> @@ -53,6 +56,15 @@ static struct file_entry *files;
> static unsigned int num_files;
> static unsigned int files_capacity;
>
> +/* Compressed output */
> +static unsigned char *compressed_data;
> +static unsigned int compressed_size;
> +static unsigned int compressed_capacity;
> +
> +static unsigned int *block_addrs;
> +static unsigned int *block_offsets;
> +static unsigned int num_blocks;
> +
> #define FILE_HASH_BITS 13
> #define FILE_HASH_SIZE (1 << FILE_HASH_BITS)
>
> @@ -352,6 +364,93 @@ static void deduplicate(void)
> num_entries = j + 1;
> }
>
> +static void compressed_ensure(unsigned int need)
> +{
> + if (compressed_size + need <= compressed_capacity)
> + return;
> + compressed_capacity = compressed_capacity ? compressed_capacity * 2 : 1024 * 1024;
> + while (compressed_capacity < compressed_size + need)
> + compressed_capacity *= 2;
> + compressed_data = realloc(compressed_data, compressed_capacity);
> + if (!compressed_data) {
> + fprintf(stderr, "out of memory\n");
> + exit(1);
> + }
> +}
> +
> +static void compress_entries(void)
> +{
> + unsigned int i, block;
> +
> + if (num_entries == 0) {
> + num_blocks = 0;
> + return;
> + }
> +
> + num_blocks = (num_entries + LINEINFO_BLOCK_ENTRIES - 1) / LINEINFO_BLOCK_ENTRIES;
> + block_addrs = calloc(num_blocks, sizeof(*block_addrs));
> + block_offsets = calloc(num_blocks, sizeof(*block_offsets));
> + if (!block_addrs || !block_offsets) {
> + fprintf(stderr, "out of memory\n");
> + exit(1);
> + }
> +
> + for (block = 0; block < num_blocks; block++) {
> + unsigned int base = block * LINEINFO_BLOCK_ENTRIES;
> + unsigned int count = num_entries - base;
> + unsigned int prev_addr, prev_file_id, prev_line;
> + unsigned char buf[10]; /* max 5 bytes per ULEB128 */
> +
> + if (count > LINEINFO_BLOCK_ENTRIES)
> + count = LINEINFO_BLOCK_ENTRIES;
> +
> + block_addrs[block] = entries[base].offset;
> + block_offsets[block] = compressed_size;
> +
> + /* Entry 0: file_id (ULEB128), line (ULEB128) */
> + compressed_ensure(20);
> + compressed_size += lineinfo_write_uleb128(
> + compressed_data + compressed_size,
> + entries[base].file_id);
> + compressed_size += lineinfo_write_uleb128(
> + compressed_data + compressed_size,
> + entries[base].line);
> +
> + prev_addr = entries[base].offset;
> + prev_file_id = entries[base].file_id;
> + prev_line = entries[base].line;
> +
> + /* Entries 1..N: deltas */
> + for (i = 1; i < count; i++) {
> + unsigned int idx = base + i;
> + unsigned int addr_delta;
> + int32_t file_delta, line_delta;
> + unsigned int n;
> +
> + addr_delta = entries[idx].offset - prev_addr;
> + file_delta = (int32_t)entries[idx].file_id - (int32_t)prev_file_id;
> + line_delta = (int32_t)entries[idx].line - (int32_t)prev_line;
> +
> + compressed_ensure(15);
> + n = lineinfo_write_uleb128(buf, addr_delta);
> + memcpy(compressed_data + compressed_size, buf, n);
> + compressed_size += n;
> +
> + n = lineinfo_write_uleb128(buf, zigzag_encode(file_delta));
> + memcpy(compressed_data + compressed_size, buf, n);
> + compressed_size += n;
> +
> + n = lineinfo_write_uleb128(buf, zigzag_encode(line_delta));
> + memcpy(compressed_data + compressed_size, buf, n);
> + compressed_size += n;
> +
> + prev_addr = entries[idx].offset;
> + prev_file_id = entries[idx].file_id;
> + prev_line = entries[idx].line;
> + }
> + }
> +}
> +
> static void compute_file_offsets(void)
> {
> unsigned int offset = 0;
> @@ -395,28 +494,40 @@ static void output_assembly(void)
> printf("lineinfo_num_files:\n");
> printf("\t.long %u\n\n", num_files);
>
> - /* Sorted address offsets from _text */
> - printf("\t.globl lineinfo_addrs\n");
> + /* Number of blocks */
> + printf("\t.globl lineinfo_num_blocks\n");
> printf("\t.balign 4\n");
> - printf("lineinfo_addrs:\n");
> - for (unsigned int i = 0; i < num_entries; i++)
> - printf("\t.long 0x%x\n", entries[i].offset);
> - printf("\n");
> + printf("lineinfo_num_blocks:\n");
> + printf("\t.long %u\n\n", num_blocks);
>
> - /* File IDs, parallel to addrs (u16 -- supports up to 65535 files) */
> - printf("\t.globl lineinfo_file_ids\n");
> - printf("\t.balign 2\n");
> - printf("lineinfo_file_ids:\n");
> - for (unsigned int i = 0; i < num_entries; i++)
> - printf("\t.short %u\n", entries[i].file_id);
> + /* Block first-addresses for binary search */
> + printf("\t.globl lineinfo_block_addrs\n");
> + printf("\t.balign 4\n");
> + printf("lineinfo_block_addrs:\n");
> + for (unsigned int i = 0; i < num_blocks; i++)
> + printf("\t.long 0x%x\n", block_addrs[i]);
> printf("\n");
>
> - /* Line numbers, parallel to addrs */
> - printf("\t.globl lineinfo_lines\n");
> + /* Block byte offsets into compressed stream */
> + printf("\t.globl lineinfo_block_offsets\n");
> printf("\t.balign 4\n");
> - printf("lineinfo_lines:\n");
> - for (unsigned int i = 0; i < num_entries; i++)
> - printf("\t.long %u\n", entries[i].line);
> + printf("lineinfo_block_offsets:\n");
> + for (unsigned int i = 0; i < num_blocks; i++)
> + printf("\t.long %u\n", block_offsets[i]);
> + printf("\n");
> +
> + /* Compressed data stream */
> + printf("\t.globl lineinfo_data\n");
> + printf("lineinfo_data:\n");
> + for (unsigned int i = 0; i < compressed_size; i++) {
> + if ((i % 16) == 0)
> + printf("\t.byte ");
> + else
> + printf(",");
> + printf("0x%02x", compressed_data[i]);
> + if ((i % 16) == 15 || i == compressed_size - 1)
> + printf("\n");
> + }
> printf("\n");
>
Note how compute_file_offsets() gives symbol names to the data it
generates. Meanwhile...
> /* File string offset table */
> @@ -450,33 +561,38 @@ static void output_module_assembly(void)
>
> printf("\t.section .mod_lineinfo, \"a\"\n\n");
>
> - /* Header: num_entries, num_files, filenames_size, reserved */
> + /* Header: num_entries, num_files, filenames_size, num_blocks, data_size, reserved */
> printf("\t.balign 4\n");
> printf("\t.long %u\n", num_entries);
> printf("\t.long %u\n", num_files);
> printf("\t.long %u\n", filenames_size);
> + printf("\t.long %u\n", num_blocks);
> + printf("\t.long %u\n", compressed_size);
> printf("\t.long 0\n\n");
>
> - /* addrs[] */
> - for (unsigned int i = 0; i < num_entries; i++)
> - printf("\t.long 0x%x\n", entries[i].offset);
> - if (num_entries)
> + /* block_addrs[] */
> + for (unsigned int i = 0; i < num_blocks; i++)
> + printf("\t.long 0x%x\n", block_addrs[i]);
> + if (num_blocks)
> printf("\n");
>
For the modules, it's comments in the C code that doesn't end up in the
assembly.
I'm thinking we could have something like:
printf(".Lmod_lineinfo_block_addrs:\n")
for (unsigned int i = 0; i < num_entries; i++)
printf("\t.long 0x%x\n", ...);
printf("\n")
(And similarly for the other blocks of data.)
This would make the assembly a tiny bit more readable, get rid of the
kinda ugly printf("\n") checks and prints, and would be useful for the
offset + size header format I mentioned earlier.
> - /* file_ids[] */
> - for (unsigned int i = 0; i < num_entries; i++)
> - printf("\t.short %u\n", entries[i].file_id);
> -
> - /* Padding to align lines[] to 4 bytes */
> - if (num_entries & 1)
> - printf("\t.short 0\n");
> - if (num_entries)
> + /* block_offsets[] */
> + for (unsigned int i = 0; i < num_blocks; i++)
> + printf("\t.long %u\n", block_offsets[i]);
> + if (num_blocks)
> printf("\n");
>
> - /* lines[] */
> - for (unsigned int i = 0; i < num_entries; i++)
> - printf("\t.long %u\n", entries[i].line);
> - if (num_entries)
> + /* compressed data[] */
> + for (unsigned int i = 0; i < compressed_size; i++) {
> + if ((i % 16) == 0)
> + printf("\t.byte ");
> + else
> + printf(",");
> + printf("0x%02x", compressed_data[i]);
> + if ((i % 16) == 15 || i == compressed_size - 1)
> + printf("\n");
> + }
> + if (compressed_size)
> printf("\n");
>
Also, maybe we can use .uleb128/.sleb128 here, and generate something like:
printf("\t.sleb128 %#x - %#x\n", cur_addr, prev_addr);
And have the assembler do the subtraction and encoding for us? If that
works it should significantly simplify the compression code above.
Speaking of... Why do we use uleb128(zigzag(num)) and not just sleb128(num)?
[...]
> @@ -558,10 +674,11 @@ int main(int argc, char *argv[])
> skipped_overflow);
>
> deduplicate();
> + compress_entries();
> compute_file_offsets();
>
> - fprintf(stderr, "lineinfo: %u entries, %u files\n",
> - num_entries, num_files);
> + fprintf(stderr, "lineinfo: %u entries, %u files, %u blocks, %u compressed bytes\n",
> + num_entries, num_files, num_blocks, compressed_size);
>
> if (module_mode)
> output_module_assembly();
> @@ -577,6 +694,9 @@ int main(int argc, char *argv[])
> for (unsigned int i = 0; i < num_files; i++)
> free(files[i].name);
> free(files);
> + free(compressed_data);
> + free(block_addrs);
> + free(block_offsets);
>
> return 0;
> }
> diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
> index 42662c4fbc6c9..94fbdad3df7c6 100644
> --- a/scripts/kallsyms.c
> +++ b/scripts/kallsyms.c
> @@ -80,11 +80,12 @@ static bool is_ignored_symbol(const char *name, char type)
> {
> /* Ignore lineinfo symbols for kallsyms pass stability */
> static const char * const lineinfo_syms[] = {
> - "lineinfo_addrs",
> - "lineinfo_file_ids",
> + "lineinfo_block_addrs",
> + "lineinfo_block_offsets",
> + "lineinfo_data",
> "lineinfo_file_offsets",
> "lineinfo_filenames",
> - "lineinfo_lines",
> + "lineinfo_num_blocks",
> "lineinfo_num_entries",
> "lineinfo_num_files",
> };
> diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
> index 640209f2e9eb9..3c122cf9b95c5 100755
> --- a/scripts/link-vmlinux.sh
> +++ b/scripts/link-vmlinux.sh
> @@ -235,12 +235,16 @@ lineinfo_num_entries:
> .balign 4
> lineinfo_num_files:
> .long 0
> - .globl lineinfo_addrs
> -lineinfo_addrs:
> - .globl lineinfo_file_ids
> -lineinfo_file_ids:
> - .globl lineinfo_lines
> -lineinfo_lines:
> + .globl lineinfo_num_blocks
> + .balign 4
> +lineinfo_num_blocks:
> + .long 0
> + .globl lineinfo_block_addrs
> +lineinfo_block_addrs:
> + .globl lineinfo_block_offsets
> +lineinfo_block_offsets:
> + .globl lineinfo_data
> +lineinfo_data:
> .globl lineinfo_file_offsets
> lineinfo_file_offsets:
> .globl lineinfo_filenames
The contents of this .tmp_lineinfo.S is fixed, so it feels like it could
just be a proper file, instead of something "generated" dynamically.
Thanks,
Vivian "dramforever" Wang
^ permalink raw reply
* Re: [PATCH 56/61] clk: Prefer IS_ERR_OR_NULL over manual NULL check
From: Chen-Yu Tsai @ 2026-03-11 2:07 UTC (permalink / raw)
To: Philipp Hahn
Cc: amd-gfx, apparmor, bpf, ceph-devel, cocci, dm-devel, dri-devel,
gfs2, intel-gfx, intel-wired-lan, iommu, kvm, linux-arm-kernel,
linux-block, linux-bluetooth, linux-btrfs, linux-cifs, linux-clk,
linux-erofs, linux-ext4, linux-fsdevel, linux-gpio, linux-hyperv,
linux-input, linux-kernel, linux-leds, linux-media, linux-mips,
linux-mm, linux-modules, linux-mtd, linux-nfs, linux-omap,
linux-phy, linux-pm, linux-rockchip, linux-s390, linux-scsi,
linux-sctp, linux-security-module, linux-sh, linux-sound,
linux-stm32, linux-trace-kernel, linux-usb, linux-wireless,
netdev, ntfs3, samba-technical, sched-ext, target-devel,
tipc-discussion, v9fs, Michael Turquette, Stephen Boyd,
Daniel Lezcano, Thomas Gleixner
In-Reply-To: <20260310-b4-is_err_or_null-v1-56-bd63b656022d@avm.de>
On Tue, Mar 10, 2026 at 9:57 PM Philipp Hahn <phahn-oss@avm.de> wrote:
>
> Prefer using IS_ERR_OR_NULL() over using IS_ERR() and a manual NULL
> check.
>
> Semantich change: Previously the code only printed the warning on error,
> but not when the pointer was NULL. Now the warning is printed in both
> cases!
>
> Change found with coccinelle.
>
> To: Michael Turquette <mturquette@baylibre.com>
> To: Stephen Boyd <sboyd@kernel.org>
> To: Daniel Lezcano <daniel.lezcano@kernel.org>
> To: Thomas Gleixner <tglx@kernel.org>
> Cc: linux-clk@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Philipp Hahn <phahn-oss@avm.de>
> ---
> drivers/clk/clk.c | 4 ++--
> drivers/clocksource/timer-pxa.c | 2 +-
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 47093cda9df32223c1120c3710261296027c4cd3..35146e3869a7dd93741d10b7223d4488a9216ed1 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -4558,7 +4558,7 @@ void clk_unregister(struct clk *clk)
> unsigned long flags;
> const struct clk_ops *ops;
>
> - if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> + if (WARN_ON_ONCE(IS_ERR_OR_NULL(clk)))
> return;
>
> clk_debug_unregister(clk->core);
> @@ -4744,7 +4744,7 @@ void __clk_put(struct clk *clk)
> {
> struct module *owner;
>
> - if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> + if (WARN_ON_ONCE(IS_ERR_OR_NULL(clk)))
clk_get_optional() returns NULL if the clk isn't present.
Drivers would just pass this to clk_put(). Your change here would cause
this pattern to emit a very big warning.
I don't think this change should be landed.
ChenYu
> return;
>
> clk_prepare_lock();
> diff --git a/drivers/clocksource/timer-pxa.c b/drivers/clocksource/timer-pxa.c
> index 7ad0e5adb2ffac4125c34710fc67f4b45f30331d..f65fb0b7fc318b766227e5e7a4c0fb08ba11c8f9 100644
> --- a/drivers/clocksource/timer-pxa.c
> +++ b/drivers/clocksource/timer-pxa.c
> @@ -218,7 +218,7 @@ void __init pxa_timer_nodt_init(int irq, void __iomem *base)
>
> timer_base = base;
> clk = clk_get(NULL, "OSTIMER0");
> - if (clk && !IS_ERR(clk)) {
> + if (!IS_ERR_OR_NULL(clk)) {
> clk_prepare_enable(clk);
> pxa_timer_common_init(irq, clk_get_rate(clk));
> } else {
>
> --
> 2.43.0
>
>
^ permalink raw reply
* Re: [PATCH v4 15/17] module: Introduce hash-based integrity checking
From: Eric Biggers @ 2026-03-11 1:18 UTC (permalink / raw)
To: Petr Pavlu
Cc: Thomas Weißschuh, Nathan Chancellor, Arnd Bergmann,
Luis Chamberlain, Sami Tolvanen, Daniel Gomez, Paul Moore,
James Morris, Serge E. Hallyn, Jonathan Corbet,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Naveen N Rao, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Nicolas Schier, Daniel Gomez, Aaron Tomlin,
Christophe Leroy (CS GROUP), Nicolas Schier, Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <fab2af64-e396-45f9-8876-feff4002e04b@suse.com>
On Tue, Feb 03, 2026 at 01:19:20PM +0100, Petr Pavlu wrote:
> > +static unsigned int get_pow2(unsigned int val)
> > +{
> > + return 31 - __builtin_clz(val);
> > +}
> > +
> > +static unsigned int roundup_pow2(unsigned int val)
> > +{
> > + return 1 << (get_pow2(val - 1) + 1);
> > +}
> > +
> > +static unsigned int log2_roundup(unsigned int val)
> > +{
> > + return get_pow2(roundup_pow2(val));
> > +}
>
> In the edge case when the kernel is built with only one module, the code
> calls log2_roundup(1) -> roundup_pow2(1) -> get_pow2(0) ->
> __builtin_clz(0). The return value of __builtin_clz() is undefined if
> the input is zero.
A suggestion:
static unsigned int log2_roundup(unsigned int val)
{
if (val <= 1)
return 0;
return 32 - __builtin_clz(val - 1);
}
- Eric
^ permalink raw reply
* Re: [PATCH v4 15/17] module: Introduce hash-based integrity checking
From: Eric Biggers @ 2026-03-11 1:12 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Schier, Nicolas Bouchinet, Xiu Jianfeng,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-15-0b932db9b56b@weissschuh.net>
On Tue, Jan 13, 2026 at 01:28:59PM +0100, Thomas Weißschuh wrote:
> The current signature-based module integrity checking has some drawbacks
> in combination with reproducible builds. Either the module signing key
> is generated at build time, which makes the build unreproducible, or a
> static signing key is used, which precludes rebuilds by third parties
> and makes the whole build and packaging process much more complicated.
I think this actually undersells the feature. It's also much simpler
than the signature-based module authentication. The latter relies on
PKCS#7, X.509, ASN.1, OID registry, crypto_sig API, etc in addition to
the implementations of the actual signature algorithm (RSA / ECDSA /
ML-DSA) and at least one hash algorithm.
I've even seen a case where the vmlinux size decreases by almost 200KB
just by disabling module signing. That's not even counting the
signatures themselves, which ML-DSA has increased to 2-5 KB each.
The hashes are much simpler, even accounting for the Merkle tree proofs
that make them scalable. They're less likely to have vulnerabilities
like the PKCS#7 bugs the kernel has had historically. They also
eliminate the dependency on a lot of userspace libcrypto functionality
that has been causing portability problems, such as the CMS functions.
So I think this is how module authentication should have been done
originally, and I'm glad to see this is finally being fixed.
> +struct module_hashes_proof {
> + __be32 pos;
> + u8 hash_sigs[][MODULE_HASHES_HASH_SIZE];
> +} __packed;
Is the choice of big endian for consistency with struct
module_signature? Little endian is the usual choice in new code.
> diff --git a/include/linux/module_signature.h b/include/linux/module_signature.h
> index a45ce3b24403..3b510651830d 100644
> --- a/include/linux/module_signature.h
> +++ b/include/linux/module_signature.h
> @@ -18,6 +18,7 @@ enum pkey_id_type {
> PKEY_ID_PGP, /* OpenPGP generated key ID */
> PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */
> PKEY_ID_PKCS7, /* Signature in PKCS#7 message */
> + PKEY_ID_MERKLE, /* Merkle proof for modules */
I recommend making the hash algorithm explicit:
PKEY_ID_MERKLE_SHA256, /* SHA-256 merkle proof for modules */
While I wouldn't encourage the addition of another hash algorithm
(specifying one good algorithm for now is absolutely the right choice),
if someone ever does need to add another one, we'd want them to be
guided to simply introduce a new value of this enum rather than hack it
in some other way.
> +static void hash_entry(const void *left, const void *right, void *out)
Byte arrays should use u8 instead of void
> diff --git a/scripts/modules-merkle-tree.c b/scripts/modules-merkle-tree.c
[...]
> +struct file_entry {
> + char *name;
> + unsigned int pos;
> + unsigned char hash[EVP_MAX_MD_SIZE];
Considering that the hash algorithm is fixed, EVP_MAX_MD_SIZE can be
replaced with a tighter local definition:
#define MAX_HASH_SIZE 32
> +static struct file_entry *fh_list;
> +static size_t num_files;
> +
> +struct leaf_hash {
> + unsigned char hash[EVP_MAX_MD_SIZE];
> +};
> +
> +struct mtree {
> + struct leaf_hash **l;
> + unsigned int *entries;
> + unsigned int levels;
> +};
'struct leaf_hash' is confusing because it's actually used for the
hashes of internal nodes, not leaf nodes.
Maybe rename it to 'struct hash' and use it for both the hashes and leaf
nodes and internal nodes.
Also, clearer naming would improve readability, e.g.:
struct merkle_tree {
struct hash **level_hashes;
unsigned int level_size;
unsigned int num_levels;
};
> +static void hash_data(void *p, unsigned int pos, size_t size, void *ret_hash)
static void hash_data(const uint8_t *data, unsigned int pos,
size_t size, struct hash *ret_hash)
> + unsigned char magic = 0x01;
uint8_t
Also, when defining these magic numbers, maybe explicitly document that
they are domain separation prefixes:
uint8_t magic = 0x01; /* domain separation prefix */
> + unsigned int pos_be;
uint32_t
> +static void hash_entry(void *left, void *right, void *ret_hash)
Could use stronger typing:
static void hash_entry(const struct hash *left, const struct hash *right,
struct hash *ret_hash)
> +static struct mtree *build_merkle(struct file_entry *fh, size_t num)
Could use clearer names, and constify the file_entry array:
static struct merkle_tree *build_merkle(const struct file_entry *files,
size_t num_files)
> + /* First level of pairs */
> + for (unsigned int i = 0; i < num; i += 2) {
> + if (i == num - 1) {
> + /* Odd number of files, no pair. Hash with itself */
> + hash_entry(fh[i].hash, fh[i].hash, mt->l[0][i / 2].hash);
> + } else {
> + hash_entry(fh[i].hash, fh[i + 1].hash, mt->l[0][i / 2].hash);
> + }
> + }
> + for (unsigned int i = 1; i < mt->levels; i++) {
> + int odd = 0;
> +
> + if (le & 1) {
> + le++;
> + odd++;
> + }
> +
> + mt->entries[i] = le / 2;
> + mt->l[i] = xcalloc(sizeof(**mt->l), le);
> +
> + for (unsigned int n = 0; n < le; n += 2) {
> + if (n == le - 2 && odd) {
> + /* Odd number of pairs, no pair. Hash with itself */
> + hash_entry(mt->l[i - 1][n].hash, mt->l[i - 1][n].hash,
> + mt->l[i][n / 2].hash);
> + } else {
> + hash_entry(mt->l[i - 1][n].hash, mt->l[i - 1][n + 1].hash,
> + mt->l[i][n / 2].hash);
> + }
> + }
> + le = mt->entries[i];
> + }
There should be an assertion at the end that we ended up with exactly 1
hash in the root level.
It might also be possible to refactor this code such that the leaf nodes
and internal nodes are handled in the same loop, rather than handling
the leaf nodes as a special case.
> +static void write_merkle_root(struct mtree *mt, const char *fp)
fp => filename since it's a string, not e.g. a 'FILE *'.
> +{
> + char buf[1024];
> + unsigned int levels;
> + unsigned char *h;
> + FILE *f;
> +
> + if (mt) {
> + levels = mt->levels;
> + h = mt->l[mt->levels - 1][0].hash;
> + } else {
> + levels = 0;
> + h = xcalloc(1, hash_size);
> + }
> +
> + f = fopen(fp, "w");
> + if (!f)
> + err(1, "Failed to create %s", buf);
Above should log the name of the file. 'buf' should be removed.
> +static char *xstrdup_replace_suffix(const char *str, const char *new_suffix)
> +{
> + const char *current_suffix;
> + size_t base_len;
> +
> + current_suffix = strchr(str, '.');
> + if (!current_suffix)
> + errx(1, "No existing suffix in '%s'", str);
This doesn't handle base names that contain a period. strrchr() would
work if the old suffix always contains exactly one period. Otherwise
another solution would be needed to identify the old suffix.
> +static __attribute__((noreturn))
> +void format(void)
usage()
> +{
> + fprintf(stderr,
> + "Usage: scripts/modules-merkle-tree <root definition>\n");
> + exit(2);
This should show both parameters, <root hash> <new suffix>
But they probably should be flipped to put the output second.
Though, is <new suffix> needed at all? It looks like it doesn't
actually affect the output.
> + hash_evp = EVP_get_digestbyname("sha256");
EVP_sha256()
> + hash_size = EVP_MD_get_size(hash_evp);
The old name 'EVP_MD_size()' would have wider compatibility.
> + ERR(hash_size <= 0, "EVP_get_digestbyname");
Log message should say EVP_MD_size
> + for (unsigned int i = 0; i < num_files; i++) {
size_t, for consistency with the type of num_files
> + fd = open(signame, O_WRONLY | O_CREAT | O_TRUNC, 0644);
> + if (fd < 0)
> + err(1, "Can't create %s", signame);
> +
> + build_proof(mt, i, fd);
> + append_module_signature_magic(fd, lseek(fd, 0, SEEK_CUR));
Maybe build_and_append_proof()?
- Eric
^ permalink raw reply
* Re: [PATCH 1/3] kallsyms: embed source file:line info in kernel stack traces
From: Sasha Levin @ 2026-03-11 0:58 UTC (permalink / raw)
To: Petr Mladek
Cc: Andrew Morton, Masahiro Yamada, Luis Chamberlain, Linus Torvalds,
Richard Weinberger, Juergen Gross, Geert Uytterhoeven,
James Bottomley, Jonathan Corbet, Nathan Chancellor,
Nicolas Schier, Petr Pavlu, Daniel Gomez, Greg KH, Steven Rostedt,
Kees Cook, Peter Zijlstra, Thorsten Leemhuis, Vlastimil Babka,
linux-kernel, linux-kbuild, linux-modules, linux-doc
In-Reply-To: <abA2wOsJtK-g2NxY@pathway.suse.cz>
On Tue, Mar 10, 2026 at 04:20:32PM +0100, Petr Mladek wrote:
>On Fri 2026-03-06 12:14:45, Sasha Levin wrote:
>> On Fri, Mar 06, 2026 at 05:36:36PM +0100, Petr Mladek wrote:
>> > On Tue 2026-03-03 13:21:01, Sasha Levin wrote:
>> > > Add CONFIG_KALLSYMS_LINEINFO, which embeds a compact address-to-line
>> > > lookup table in the kernel image so stack traces directly print source
>> > > file and line number information:
>> > >
>> > > --- a/include/linux/kallsyms.h
>> > > +++ b/include/linux/kallsyms.h
>> > > @@ -16,10 +16,19 @@
>> > > #include <asm/sections.h>
>> > >
>> > > #define KSYM_NAME_LEN 512
>> > > +
>> > > +#ifdef CONFIG_KALLSYMS_LINEINFO
>> > > +/* Extra space for " (path/to/file.c:12345)" suffix */
>> > > +#define KSYM_LINEINFO_LEN 128
>> > > +#else
>> > > +#define KSYM_LINEINFO_LEN 0
>> > > +#endif
>> > > +
>> > > #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s %s]") + \
>> >
>> > I guess that this is used also in ftrace where there formatting
>> > is delayed. We might want:
>> >
>> > #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s %s] (%s:%u)") + \
>>
>> KSYM_LINEINFO_LEN already covers the full expansion of the path and line
>> number, not just the literal format characters. ftrace stores raw addresses and
>> formats via %pS at print time into a KSYM_SYMBOL_LEN-sized buffer, so there
>> shouldn't be an issue here.
>
>I was curious why the sizeof("%s+%#lx/%#lx [%s %s]") was there.
>It did not make much sense to count some "random" part of the
>format string.
>
>I expected that it was related to the ftrace delayed formatting.
>But they are written to the tracing buffer, see trace_vbprintk().
>
>But I believe that it does not need to be counted. It seems to be some
>cargo-cult programming. The size has been counted first by the commit
>d069cf94ca296b7fb ("kallsyms for new modules") back in v2.6.12-rc2,
>see
>https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?id=d069cf94ca296b7fb4c7e362e8f27e2c8aca70f1
>And it seems that it was not needed there.
>
>That said, we could not simply remove it witout revisiting the rest of
>the computation. Especilly, we need to make sure that it counts all
>extra characters, like spaces, brackets, and the trailing '\0'.
>
>Ideally, we should replace the unsafe sprintf() with snprintf() in
>all users. (>> TODO ;-)
Yeah, good catch. The sizeof() counts the format specifiers too which never
end up in the output since their expansions are already covered by the other
terms.
I'd rather not poke that bear as part of this series, we can try it in a follow
up and see if anything explodes?
--
Thanks,
Sasha
^ permalink raw reply
* Re: [PATCH 38/61] net: Prefer IS_ERR_OR_NULL over manual NULL check
From: Russell King (Oracle) @ 2026-03-11 0:16 UTC (permalink / raw)
To: Philipp Hahn
Cc: amd-gfx, apparmor, bpf, ceph-devel, cocci, dm-devel, dri-devel,
gfs2, intel-gfx, intel-wired-lan, iommu, kvm, linux-arm-kernel,
linux-block, linux-bluetooth, linux-btrfs, linux-cifs, linux-clk,
linux-erofs, linux-ext4, linux-fsdevel, linux-gpio, linux-hyperv,
linux-input, linux-kernel, linux-leds, linux-media, linux-mips,
linux-mm, linux-modules, linux-mtd, linux-nfs, linux-omap,
linux-phy, linux-pm, linux-rockchip, linux-s390, linux-scsi,
linux-sctp, linux-security-module, linux-sh, linux-sound,
linux-stm32, linux-trace-kernel, linux-usb, linux-wireless,
netdev, ntfs3, samba-technical, sched-ext, target-devel,
tipc-discussion, v9fs, Igor Russkikh, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Pavan Chebbi, Michael Chan, Potnuri Bharat Teja, Tony Nguyen,
Przemek Kitszel, Taras Chornyi, Maxime Coquelin, Alexandre Torgue,
Iyappan Subramanian, Keyur Chudgar, Quan Nguyen, Heiner Kallweit
In-Reply-To: <20260310-b4-is_err_or_null-v1-38-bd63b656022d@avm.de>
On Tue, Mar 10, 2026 at 12:49:04PM +0100, Philipp Hahn wrote:
> diff --git a/drivers/net/mdio/mdio-xgene.c b/drivers/net/mdio/mdio-xgene.c
> index a8f91a4b7fed0927ee14e408000cd3a2bfb9b09a..09b30b563295c6085dc1358ac361301e5cf6b2a8 100644
> --- a/drivers/net/mdio/mdio-xgene.c
> +++ b/drivers/net/mdio/mdio-xgene.c
> @@ -265,7 +265,7 @@ struct phy_device *xgene_enet_phy_register(struct mii_bus *bus, int phy_addr)
> struct phy_device *phy_dev;
>
> phy_dev = get_phy_device(bus, phy_addr, false);
> - if (!phy_dev || IS_ERR(phy_dev))
> + if (IS_ERR_OR_NULL(phy_dev))
As noted in reply to your cover message, the check for NULL here is
incorrect - get_phy_device() returns either a valid pointer or an
error pointer, but never NULL.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply
* Re: [PATCH 00/61] treewide: Use IS_ERR_OR_NULL over manual NULL check - refactor
From: Russell King (Oracle) @ 2026-03-11 0:09 UTC (permalink / raw)
To: Philipp Hahn
Cc: amd-gfx, apparmor, bpf, ceph-devel, cocci, dm-devel, dri-devel,
gfs2, intel-gfx, intel-wired-lan, iommu, kvm, linux-arm-kernel,
linux-block, linux-bluetooth, linux-btrfs, linux-cifs, linux-clk,
linux-erofs, linux-ext4, linux-fsdevel, linux-gpio, linux-hyperv,
linux-input, linux-kernel, linux-leds, linux-media, linux-mips,
linux-mm, linux-modules, linux-mtd, linux-nfs, linux-omap,
linux-phy, linux-pm, linux-rockchip, linux-s390, linux-scsi,
linux-sctp, linux-security-module, linux-sh, linux-sound,
linux-stm32, linux-trace-kernel, linux-usb, linux-wireless,
netdev, ntfs3, samba-technical, sched-ext, target-devel,
tipc-discussion, v9fs, Julia Lawall, Nicolas Palix, Chris Mason,
David Sterba, Ilya Dryomov, Alex Markuze, Viacheslav Dubeyko,
Theodore Ts'o, Andreas Dilger, Steve French, Paulo Alcantara,
Ronnie Sahlberg, Shyam Prasad N, Tom Talpey, Bharath SM,
Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
Christian Schoenebeck, Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu,
Sandeep Dhavale, Hongbo Li, Chunhai Guo, Miklos Szeredi,
Konstantin Komarov, Andreas Gruenbacher, Kees Cook, Tony Luck,
Guilherme G. Piccoli, Jan Kara, Phillip Lougher, Alexander Viro,
Christian Brauner, Jan Kara, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Tejun Heo, David Vernet, Andrea Righi,
Changwoo Min, Ingo Molnar, Peter Zijlstra, Juri Lelli,
Vincent Guittot, Dietmar Eggemann, Ben Segall, Mel Gorman,
Valentin Schneider, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Sylwester Nawrocki, Liam Girdwood,
Mark Brown, Jaroslav Kysela, Takashi Iwai, Max Filippov,
Paolo Bonzini, John Johansen, Paul Moore, James Morris,
Serge E. Hallyn, Andrew Morton, Alasdair Kergon, Mike Snitzer,
Mikulas Patocka, Benjamin Marzinski, David S. Miller, David Ahern,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Marcel Holtmann, Johan Hedberg, Luiz Augusto von Dentz,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, Stanislav Fomichev, Jamal Hadi Salim, Jiri Pirko,
Marcelo Ricardo Leitner, Xin Long, Trond Myklebust,
Anna Schumaker, Chuck Lever, Jeff Layton, NeilBrown,
Olga Kornievskaia, Dai Ngo, Jon Maloy, Johannes Berg,
Catalin Marinas, John Crispin, Thomas Bogendoerfer,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Zhenyu Wang,
Zhi Wang, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, Sandy Huang,
Heiko Stübner, Andy Yan, Igor Russkikh, Andrew Lunn,
Pavan Chebbi, Michael Chan, Potnuri Bharat Teja, Tony Nguyen,
Przemek Kitszel, Taras Chornyi, Maxime Coquelin, Alexandre Torgue,
Iyappan Subramanian, Keyur Chudgar, Quan Nguyen, Heiner Kallweit,
Marc Zyngier, Thomas Gleixner, Andrew Lunn, Gregory Clement,
Sebastian Hesselbarth, Vinod Koul, Linus Walleij, Ulf Hansson,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Christian Borntraeger, Sven Schnelle, Martin K. Petersen,
Eduardo Valentin, Keerthy, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Alex Williamson, Mark Greer,
Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
Shuah Khan, Kieran Bingham, Mauro Carvalho Chehab, Joerg Roedel,
Will Deacon, Robin Murphy, Lee Jones, Pavel Machek, Dave Penkler,
K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
Justin Sanders, Jens Axboe, Georgi Djakov, Michael Turquette,
Stephen Boyd, Philipp Zabel, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Pali Rohár, Dmitry Torokhov
In-Reply-To: <20260310-b4-is_err_or_null-v1-0-bd63b656022d@avm.de>
On Tue, Mar 10, 2026 at 12:48:26PM +0100, Philipp Hahn wrote:
> While doing some static code analysis I stumbled over a common pattern,
> where IS_ERR() is combined with a NULL check. For that there is
> IS_ERR_OR_NULL().
One thing you need to check for each of these cases is whether the tests
are actually correct.
There are certainly cases amongst those that you have identified where
the check for NULL is redundant.
For example, get_phy_device() never returns NULL, yet in your netdev
patch, you have at least one instance where the return value of
get_phy_device() is checked for NULL and IS_ERR() which you then
turn into IS_ERR_OR_NULL(). Instead, the NULL check should be dropped
(as a separate patch.)
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply
* Re: [PATCH v2 2/2] tree-wide: rename do_exit() to task_exit()
From: Steven Rostedt @ 2026-03-11 0:02 UTC (permalink / raw)
To: Christian Brauner
Cc: Linus Torvalds, linux-kernel, linux-modules, linux-nfs, bpf,
kunit-dev, linux-doc, linux-trace-kernel, netfs, io-uring, audit,
rcu, kvm, virtualization, netdev, linux-mm, linux-security-module,
Christian Loehle, linux-fsdevel
In-Reply-To: <20260310-work-kernel-exit-v2-2-30711759d87b@kernel.org>
On Tue, 10 Mar 2026 15:56:10 +0100
Christian Brauner <brauner@kernel.org> wrote:
> diff --git a/tools/testing/selftests/bpf/progs/tracing_failure.c b/tools/testing/selftests/bpf/progs/tracing_failure.c
> index 65e485c4468c..5144f4cc5787 100644
> --- a/tools/testing/selftests/bpf/progs/tracing_failure.c
> +++ b/tools/testing/selftests/bpf/progs/tracing_failure.c
> @@ -25,7 +25,7 @@ int BPF_PROG(tracing_deny)
> return 0;
> }
>
> -SEC("?fexit/do_exit")
> +SEC("?fexit/task_exit")
> int BPF_PROG(fexit_noreturns)
> {
> return 0;
> diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc
> index fee479295e2f..7e00d8ecd110 100644
> --- a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc
> +++ b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc
> @@ -82,7 +82,7 @@ check_error 'f vfs_read arg1=^' # NO_ARG_BODY
> # multiprobe errors
> if grep -q "Create/append/" README && grep -q "imm-value" README; then
> echo "f:fprobes/testevent $FUNCTION_FORK" > dynamic_events
> -check_error '^f:fprobes/testevent do_exit%return' # DIFF_PROBE_TYPE
> +check_error '^f:fprobes/testevent task_exit%return' # DIFF_PROBE_TYPE
>
> # Explicitly use printf "%s" to not interpret \1
> printf "%s" "f:fprobes/testevent $FUNCTION_FORK abcd=\\1" > dynamic_events
> diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc
> index f0d5b7777ed7..a95e3824690a 100644
> --- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc
> +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc
> @@ -5,7 +5,7 @@
>
> # Choose 2 symbols for target
> SYM1=$FUNCTION_FORK
> -SYM2=do_exit
> +SYM2=task_exit
> EVENT_NAME=kprobes/testevent
>
> DEF1="p:$EVENT_NAME $SYM1"
> diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
> index 8f1c58f0c239..b55ea3c05cfa 100644
> --- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
> +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
> @@ -87,7 +87,7 @@ esac
> # multiprobe errors
> if grep -q "Create/append/" README && grep -q "imm-value" README; then
> echo "p:kprobes/testevent $FUNCTION_FORK" > kprobe_events
> -check_error '^r:kprobes/testevent do_exit' # DIFF_PROBE_TYPE
> +check_error '^r:kprobes/testevent task_exit' # DIFF_PROBE_TYPE
>
> # Explicitly use printf "%s" to not interpret \1
> printf "%s" "p:kprobes/testevent $FUNCTION_FORK abcd=\\1" > kprobe_events
These tests need to pass on old kernels too. So we can't just do a
"s/do_exit/task_exit/" conversion. It needs to test for task_exit first,
and if not found, fallback to do_exit.
See how we handled the _do_fork() > kernel_clone() rename:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/testing/selftests/ftrace/test.d/functions#n182
-- Steve
^ permalink raw reply
* Re: [PATCH v2 2/2] tree-wide: rename do_exit() to task_exit()
From: Frederic Weisbecker @ 2026-03-10 22:30 UTC (permalink / raw)
To: Christian Brauner
Cc: Linus Torvalds, linux-kernel, linux-modules, linux-nfs, bpf,
kunit-dev, linux-doc, linux-trace-kernel, netfs, io-uring, audit,
rcu, kvm, virtualization, netdev, linux-mm, linux-security-module,
Christian Loehle, linux-fsdevel
In-Reply-To: <20260310-work-kernel-exit-v2-2-30711759d87b@kernel.org>
Le Tue, Mar 10, 2026 at 03:56:10PM +0100, Christian Brauner a écrit :
> Rename do_exit() to task_exit() so it's clear that this is an api and
> not a hidden internal helper.
>
> Signed-off-by: Christian Brauner <brauner@kernel.org>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
--
Frederic Weisbecker
SUSE Labs
^ permalink raw reply
* Re: [PATCH v2 1/2] kthread: remove kthread_exit()
From: Frederic Weisbecker @ 2026-03-10 22:26 UTC (permalink / raw)
To: Christian Brauner
Cc: Linus Torvalds, linux-kernel, linux-modules, linux-nfs, bpf,
kunit-dev, linux-doc, linux-trace-kernel, netfs, io-uring, audit,
rcu, kvm, virtualization, netdev, linux-mm, linux-security-module,
Christian Loehle, linux-fsdevel
In-Reply-To: <20260310-work-kernel-exit-v2-1-30711759d87b@kernel.org>
Le Tue, Mar 10, 2026 at 03:56:09PM +0100, Christian Brauner a écrit :
> In 28aaa9c39945 ("kthread: consolidate kthread exit paths to prevent use-after-free")
> we folded kthread_exit() into do_exit() when we fixed a nasty UAF bug.
> We left kthread_exit() around as an alias to do_exit(). Remove it
> completely.
Thanks for fixing that UAF! I unfortunately missed it.
>
> Reported-by: Christian Loehle <christian.loehle@arm.com>
> Link: https://lore.kernel.org/1ff1bce2-8bb4-463c-a631-16e14f4ea7e2@arm.com
> Signed-off-by: Christian Brauner <brauner@kernel.org>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
--
Frederic Weisbecker
SUSE Labs
^ permalink raw reply
* Re: [PATCH v4 10/17] module: Move integrity checks into dedicated function
From: Eric Biggers @ 2026-03-10 22:06 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Schier, Nicolas Bouchinet, Xiu Jianfeng,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-10-0b932db9b56b@weissschuh.net>
On Tue, Jan 13, 2026 at 01:28:54PM +0100, Thomas Weißschuh wrote:
> +static int module_integrity_check(struct load_info *info, int flags)
> +{
> + int err = 0;
> +
> + if (IS_ENABLED(CONFIG_MODULE_SIG))
> + err = module_sig_check(info, flags);
> +
> + return err;
> +}
Maybe module_authenticity_check()? The purpose is authenticity, not
merely integrity.
- Eric
^ permalink raw reply
* Re: [PATCH v4 09/17] module: Make module loading policy usable without MODULE_SIG
From: Eric Biggers @ 2026-03-10 22:01 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Schier, Nicolas Bouchinet, Xiu Jianfeng,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-9-0b932db9b56b@weissschuh.net>
On Tue, Jan 13, 2026 at 01:28:53PM +0100, Thomas Weißschuh wrote:
> The loading policy functionality will also be used by the hash-based
> module validation. Split it out from CONFIG_MODULE_SIG so it is usable
> by both.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> include/linux/module.h | 8 ++++----
> kernel/module/Kconfig | 5 ++++-
> kernel/module/main.c | 26 +++++++++++++++++++++++++-
> kernel/module/signing.c | 21 ---------------------
> 4 files changed, 33 insertions(+), 27 deletions(-)
>
> diff --git a/include/linux/module.h b/include/linux/module.h
> index f288ca5cd95b..f9601cba47cd 100644
> --- a/include/linux/module.h
> +++ b/include/linux/module.h
> @@ -444,7 +444,7 @@ struct module {
> const u32 *gpl_crcs;
> bool using_gplonly_symbols;
>
> -#ifdef CONFIG_MODULE_SIG
> +#ifdef CONFIG_MODULE_SIG_POLICY
> /* Signature was verified. */
> bool sig_ok;
> #endif
[...]
> +config MODULE_SIG_POLICY
> + def_bool MODULE_SIG
Maybe MODULE_AUTH_POLICY? Hash-based module authentication does not use
signatures.
This issue appears elsewhere in the code too. There are lots of places
that still refer to module signatures or "sigs", when really module
authentication is meant.
I'm not sure how far you want to go with the renaming, but it's
something to think about. It's confusing to use the term "signature" to
mean something that is not a signature.
- Eric
^ permalink raw reply
* Re: [PATCH v4 06/17] kbuild: add stamp file for vmlinux BTF data
From: Eric Biggers @ 2026-03-10 21:36 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Schier, Nicolas Bouchinet, Xiu Jianfeng,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-6-0b932db9b56b@weissschuh.net>
On Tue, Jan 13, 2026 at 01:28:50PM +0100, Thomas Weißschuh wrote:
> The upcoming module hashes functionality will build the modules in
> between the generation of the BTF data and the final link of vmlinux.
> Having a dependency from the modules on vmlinux would make this
> impossible as it would mean having a cyclic dependency.
> Break this cyclic dependency by introducing a new target.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> scripts/Makefile.modfinal | 4 ++--
> scripts/link-vmlinux.sh | 6 ++++++
> 2 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
> index 149e12ff5700..adfef1e002a9 100644
> --- a/scripts/Makefile.modfinal
> +++ b/scripts/Makefile.modfinal
> @@ -56,8 +56,8 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
> printf '%s\n' 'savedcmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
>
> # Re-generate module BTFs if either module's .ko or vmlinux changed
> -%.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/vmlinux) FORCE
> - +$(call if_changed_except,ld_ko_o,$(objtree)/vmlinux)
> +%.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/.tmp_vmlinux_btf.stamp) FORCE
> + +$(call if_changed_except,ld_ko_o,$(objtree)/.tmp_vmlinux_btf.stamp)
> ifdef CONFIG_DEBUG_INFO_BTF_MODULES
> +$(if $(newer-prereqs),$(call cmd,btf_ko))
> endif
> diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
> index 4ab44c73da4d..8c98f8645a5c 100755
> --- a/scripts/link-vmlinux.sh
> +++ b/scripts/link-vmlinux.sh
> @@ -111,6 +111,7 @@ vmlinux_link()
> gen_btf()
> {
> local btf_data=${1}.btf.o
> + local btf_stamp=.tmp_vmlinux_btf.stamp
>
> info BTF "${btf_data}"
> LLVM_OBJCOPY="${OBJCOPY}" ${PAHOLE} -J ${PAHOLE_FLAGS} ${1}
> @@ -131,6 +132,11 @@ gen_btf()
> fi
> printf "${et_rel}" | dd of="${btf_data}" conv=notrunc bs=1 seek=16 status=none
>
> + info STAMP $btf_stamp
> + if ! cmp --silent $btf_data $btf_stamp; then
> + cp $btf_data $btf_stamp
> + fi
A "stamp file" is traditionally an empty file that is written when some
build step has completed. The above code is instead copying the entire
.tmp_vmlinux1.btf.o file (megabytes in size) to .tmp_vmlinux_btf.stamp.
So, it's not clear to me why the stamp file is needed at all, versus
depending directly on .tmp_vmlinux1.btf.o.
I guess 'make' doesn't know about the dependencies of
.tmp_vmlinux1.btf.o. But the same is true of the stamp file, right? So
either way, how would 'make' know to finish rebuilding the file before
starting to execute the "Re-generate module BTFs" rule?
Also, passing the long option '--silent' to 'cmp' creates a dependency
on the GNU implementation of 'cmp', which isn't documented as a kernel
build dependency. Probably better to use the short option '-s'.
Also, the stamp file isn't being deleted by 'make clean'. It looks like
it would need to be added to cleanup() in link-vmlinux.sh.
- Eric
^ permalink raw reply
* Re: [PATCH v4 04/17] module: Make mod_verify_sig() static
From: Eric Biggers @ 2026-03-10 21:12 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Schier, Nicolas Bouchinet, Xiu Jianfeng,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-4-0b932db9b56b@weissschuh.net>
On Tue, Jan 13, 2026 at 01:28:48PM +0100, Thomas Weißschuh wrote:
> It is not used outside of signing.c.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> kernel/module/internal.h | 1 -
> kernel/module/signing.c | 2 +-
> 2 files changed, 1 insertion(+), 2 deletions(-)
Reviewed-by: Eric Biggers <ebiggers@kernel.org>
- Eric
^ permalink raw reply
* Re: [PATCH v4 03/17] ima: efi: Drop unnecessary check for CONFIG_MODULE_SIG/CONFIG_KEXEC_SIG
From: Eric Biggers @ 2026-03-10 21:11 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Schier, Nicolas Bouchinet, Xiu Jianfeng,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-3-0b932db9b56b@weissschuh.net>
On Tue, Jan 13, 2026 at 01:28:47PM +0100, Thomas Weißschuh wrote:
> When configuration settings are disabled the guarded functions are
> defined as empty stubs, so the check is unnecessary.
> The specific configuration option for set_module_sig_enforced() is
> about to change and removing the checks avoids some later churn.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> security/integrity/ima/ima_efi.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
Reviewed-by: Eric Biggers <ebiggers@kernel.org>
- Eric
^ permalink raw reply
* Re: [PATCH v4 02/17] powerpc/ima: Drop unnecessary check for CONFIG_MODULE_SIG
From: Eric Biggers @ 2026-03-10 21:11 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Schier, Nicolas Bouchinet, Xiu Jianfeng,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-2-0b932db9b56b@weissschuh.net>
On Tue, Jan 13, 2026 at 01:28:46PM +0100, Thomas Weißschuh wrote:
> When CONFIG_MODULE_SIG is disabled set_module_sig_enforced() is defined
> as an empty stub, so the check is unnecessary.
> The specific configuration option for set_module_sig_enforced() is
> about to change and removing the check avoids some later churn.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> arch/powerpc/kernel/ima_arch.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
Reviewed-by: Eric Biggers <ebiggers@kernel.org>
- Eric
^ permalink raw reply
* Re: [PATCH 00/61] treewide: Use IS_ERR_OR_NULL over manual NULL check - refactor
From: Kuan-Wei Chiu @ 2026-03-10 18:40 UTC (permalink / raw)
To: Philipp Hahn
Cc: amd-gfx, apparmor, bpf, ceph-devel, cocci, dm-devel, dri-devel,
gfs2, intel-gfx, intel-wired-lan, iommu, kvm, linux-arm-kernel,
linux-block, linux-bluetooth, linux-btrfs, linux-cifs, linux-clk,
linux-erofs, linux-ext4, linux-fsdevel, linux-gpio, linux-hyperv,
linux-input, linux-kernel, linux-leds, linux-media, linux-mips,
linux-mm, linux-modules, linux-mtd, linux-nfs, linux-omap,
linux-phy, linux-pm, linux-rockchip, linux-s390, linux-scsi,
linux-sctp, linux-security-module, linux-sh, linux-sound,
linux-stm32, linux-trace-kernel, linux-usb, linux-wireless,
netdev, ntfs3, samba-technical, sched-ext, target-devel,
tipc-discussion, v9fs
In-Reply-To: <20260310-b4-is_err_or_null-v1-0-bd63b656022d@avm.de>
Hi Philipp,
On Tue, Mar 10, 2026 at 12:48:26PM +0100, Philipp Hahn wrote:
> While doing some static code analysis I stumbled over a common pattern,
> where IS_ERR() is combined with a NULL check. For that there is
> IS_ERR_OR_NULL().
>
> I've written a Coccinelle patch to find and patch those instances.
> The patches follow grouped by subsystem.
>
> Patches 55-58 may be dropped as they have a (minor?) semantic change:
> They use WARN_ON() or WARN_ON_ONCE(), but only in the IS_ERR() path, not
> for the NULL check. Iff it is okay to print the warning also for NULL,
> then the patches can be applied.
>
> While generating the patch set `checkpatch` complained about mixing
> [un]likely() with IS_ERR_OR_NULL(), which already uses likely()
> internally. I found and fixed several locations, where that combination
> has been used.
Thanks for the patchset. However, I think we need a explanation for why
switching to IS_ERR_OR_NULL() is an improvement over the existing code.
IMHO, the necessity of IS_ERR_OR_NULL() often highlights a confusing or
flawed API design. It usually implies that the caller is unsure whether
a failure results in an error pointer or a NULL pointer. Rather than
doing a treewide conversion of this pattern, I believe it would be much
more meaningful to review these instances case-by-case and fix the
underlying APIs or caller logic instead.
Additionally, a treewide refactoring like this has the practical
drawback of creating unnecessary merge conflicts when backporting to
stable trees.
Regards,
Kuan-Wei
^ permalink raw reply
* Re: [PATCH 03/61] ceph: Prefer IS_ERR_OR_NULL over manual NULL check
From: Viacheslav Dubeyko @ 2026-03-10 18:13 UTC (permalink / raw)
To: dm-devel@lists.linux.dev, phahn-oss@avm.de,
intel-wired-lan@lists.osuosl.org, linux-erofs@lists.ozlabs.org,
linux-security-module@vger.kernel.org, kvm@vger.kernel.org,
linux-sctp@vger.kernel.org, linux-pm@vger.kernel.org,
apparmor@lists.ubuntu.com, linux-ext4@vger.kernel.org,
amd-gfx@lists.freedesktop.org, linux-clk@vger.kernel.org,
linux-mips@vger.kernel.org, linux-media@vger.kernel.org,
netdev@vger.kernel.org, iommu@lists.linux.dev,
linux-block@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-fsdevel@vger.kernel.org, linux-usb@vger.kernel.org,
sched-ext@lists.linux.dev, linux-btrfs@vger.kernel.org,
linux-bluetooth@vger.kernel.org, linux-s390@vger.kernel.org,
samba-technical@lists.samba.org, intel-gfx@lists.freedesktop.org,
linux-trace-kernel@vger.kernel.org, ntfs3@lists.linux.dev,
linux-phy@lists.infradead.org, v9fs@lists.linux.dev,
ceph-devel@vger.kernel.org, tipc-discussion@lists.sourceforge.net,
linux-mtd@lists.infradead.org, linux-scsi@vger.kernel.org,
target-devel@vger.kernel.org, linux-gpio@vger.kernel.org,
cocci@inria.fr, linux-sh@vger.kernel.org,
linux-rockchip@lists.infradead.org,
linux-stm32@st-md-mailman.stormreply.com,
linux-cifs@vger.kernel.org, linux-modules@vger.kernel.org,
linux-sound@vger.kernel.org, bpf@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux-input@vger.kernel.org,
linux-leds@vger.kernel.org, dri-devel@lists.freedesktop.org,
linux-hyperv@vger.kernel.org, linux-mm@kvack.org,
linux-nfs@vger.kernel.org, gfs2@lists.linux.dev,
linux-wireless@vger.kernel.org, linux-omap@vger.kernel.org
Cc: idryomov@gmail.com, Alex Markuze, slava@dubeyko.com
In-Reply-To: <20260310-b4-is_err_or_null-v1-3-bd63b656022d@avm.de>
On Tue, 2026-03-10 at 12:48 +0100, Philipp Hahn wrote:
> Prefer using IS_ERR_OR_NULL() over using IS_ERR() and a manual NULL
> check.
>
> Change generated with coccinelle.
>
> To: Ilya Dryomov <idryomov@gmail.com>
> To: Alex Markuze <amarkuze@redhat.com>
> To: Viacheslav Dubeyko <slava@dubeyko.com>
> Cc: ceph-devel@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Philipp Hahn <phahn-oss@avm.de>
> ---
> fs/ceph/dir.c | 2 +-
> fs/ceph/snap.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
> index 86d7aa594ea99335af3e91a95c0a418fdc1b8a8a..934250748ae4fd4c148fd27bdf91175047c2877d 100644
> --- a/fs/ceph/dir.c
> +++ b/fs/ceph/dir.c
> @@ -889,7 +889,7 @@ int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry)
> {
> struct dentry *result = ceph_lookup(dir, dentry, 0);
>
> - if (result && !IS_ERR(result)) {
> + if (!IS_ERR_OR_NULL(result)) {
> /*
> * We created the item, then did a lookup, and found
> * it was already linked to another inode we already
> diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
> index 52b4c2684f922bfed39550311e793bfe3622cd26..528ad581be160713f91416115659e2dc6f259576 100644
> --- a/fs/ceph/snap.c
> +++ b/fs/ceph/snap.c
> @@ -902,7 +902,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
> bad:
> err = -EIO;
> fail:
> - if (realm && !IS_ERR(realm))
> + if (!IS_ERR_OR_NULL(realm))
> ceph_put_snap_realm(mdsc, realm);
> if (first_realm)
> ceph_put_snap_realm(mdsc, first_realm);
Looks good.
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Thanks,
Slava.
^ permalink raw reply
* Re: [PATCH 01/61] Coccinelle: Prefer IS_ERR_OR_NULL over manual NULL check
From: Markus Elfring @ 2026-03-10 15:41 UTC (permalink / raw)
To: Philipp Hahn, cocci, Julia Lawall
Cc: amd-gfx, apparmor, bpf, ceph-devel, dm-devel, dri-devel, gfs2,
intel-gfx, intel-wired-lan, iommu, kvm, linux-arm-kernel,
linux-block, linux-bluetooth, linux-btrfs, linux-cifs, linux-clk,
linux-erofs, linux-ext4, linux-fsdevel, linux-gpio, linux-hyperv,
linux-input, linux-kernel, linux-leds, linux-media, linux-mips,
linux-mm, linux-modules, linux-mtd, linux-nfs, linux-omap,
linux-phy, linux-pm, linux-rockchip, linux-s390, linux-scsi,
linux-sctp, linux-security-module, linux-sh, linux-sound,
linux-stm32, linux-trace-kernel, linux-usb, linux-wireless,
netdev, nicolas.palix, ntfs3, samba-technical, sched-ext,
target-devel, tipc-discussion, v9fs
In-Reply-To: <20260310-b4-is_err_or_null-v1-1-bd63b656022d@avm.de>
> Find and convert uses of IS_ERR() plus NULL check to IS_ERR_OR_NULL().
…
Can this information trigger any more consequences on corresponding summary phrases?
…
> +++ b/scripts/coccinelle/api/is_err_or_null.cocci
> @@ -0,0 +1,125 @@
…
> +virtual patch
> +virtual report
> +virtual org
How will interests evolve further for the support of the operation mode “context”?
> +@p1 depends on patch@
> +expression E;
> +@@
> +(
> +- E != NULL && !IS_ERR(E)
> ++ !IS_ERR_OR_NULL(E)
> +|
> +- E == NULL || IS_ERR(E)
> ++ IS_ERR_OR_NULL(E)
> +|
> +- !IS_ERR(E) && E != NULL
> ++ !IS_ERR_OR_NULL(E)
> +|
> +- IS_ERR(E) || E == NULL
> ++ IS_ERR_OR_NULL(E)
> +)
Did you eventually check probabilities for the occurrence of mentioned case distinctions?
> +@p2 depends on patch@
…
I suggest to reconsider “side effects” according to the splitting of these SmPL rules
once more.
…
> +@r2 depends on report || org@
> +identifier I;
> +expression E;
> +position p;
> +@@
> +(
> +* (I = E) != NULL && ... && !IS_ERR@p(I)
> +|
> +* (I = E) == NULL || ... || IS_ERR@p(I)
> +)
I doubt that the usage of SmPL asterisks fits to these two operation modes.
…
> +@p5 depends on patch disable unlikely @
> +expression E;
> +@@
> +-\( likely \| unlikely \)(
> +(
> + IS_ERR_OR_NULL(E)
> +|
> + !IS_ERR_OR_NULL(E)
> +)
> +-)
* Would it be nicer to move such SmPL code to the end of the patch rule listing?
* Can this source code search pattern matter also for further operation modes?
Regards,
Markus
^ permalink raw reply
* Re: [PATCH 1/3] kallsyms: embed source file:line info in kernel stack traces
From: Petr Mladek @ 2026-03-10 15:20 UTC (permalink / raw)
To: Sasha Levin
Cc: Andrew Morton, Masahiro Yamada, Luis Chamberlain, Linus Torvalds,
Richard Weinberger, Juergen Gross, Geert Uytterhoeven,
James Bottomley, Jonathan Corbet, Nathan Chancellor,
Nicolas Schier, Petr Pavlu, Daniel Gomez, Greg KH, Steven Rostedt,
Kees Cook, Peter Zijlstra, Thorsten Leemhuis, Vlastimil Babka,
linux-kernel, linux-kbuild, linux-modules, linux-doc
In-Reply-To: <aasLhbZmvcQ8sA9P@laps>
On Fri 2026-03-06 12:14:45, Sasha Levin wrote:
> On Fri, Mar 06, 2026 at 05:36:36PM +0100, Petr Mladek wrote:
> > On Tue 2026-03-03 13:21:01, Sasha Levin wrote:
> > > Add CONFIG_KALLSYMS_LINEINFO, which embeds a compact address-to-line
> > > lookup table in the kernel image so stack traces directly print source
> > > file and line number information:
> > >
> > > --- a/include/linux/kallsyms.h
> > > +++ b/include/linux/kallsyms.h
> > > @@ -16,10 +16,19 @@
> > > #include <asm/sections.h>
> > >
> > > #define KSYM_NAME_LEN 512
> > > +
> > > +#ifdef CONFIG_KALLSYMS_LINEINFO
> > > +/* Extra space for " (path/to/file.c:12345)" suffix */
> > > +#define KSYM_LINEINFO_LEN 128
> > > +#else
> > > +#define KSYM_LINEINFO_LEN 0
> > > +#endif
> > > +
> > > #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s %s]") + \
> >
> > I guess that this is used also in ftrace where there formatting
> > is delayed. We might want:
> >
> > #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s %s] (%s:%u)") + \
>
> KSYM_LINEINFO_LEN already covers the full expansion of the path and line
> number, not just the literal format characters. ftrace stores raw addresses and
> formats via %pS at print time into a KSYM_SYMBOL_LEN-sized buffer, so there
> shouldn't be an issue here.
I was curious why the sizeof("%s+%#lx/%#lx [%s %s]") was there.
It did not make much sense to count some "random" part of the
format string.
I expected that it was related to the ftrace delayed formatting.
But they are written to the tracing buffer, see trace_vbprintk().
But I believe that it does not need to be counted. It seems to be some
cargo-cult programming. The size has been counted first by the commit
d069cf94ca296b7fb ("kallsyms for new modules") back in v2.6.12-rc2,
see
https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?id=d069cf94ca296b7fb4c7e362e8f27e2c8aca70f1
And it seems that it was not needed there.
That said, we could not simply remove it witout revisiting the rest of
the computation. Especilly, we need to make sure that it counts all
extra characters, like spaces, brackets, and the trailing '\0'.
Ideally, we should replace the unsafe sprintf() with snprintf() in
all users. (>> TODO ;-)
> > > (KSYM_NAME_LEN - 1) + \
> > > 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + \
> > > - (BUILD_ID_SIZE_MAX * 2) + 1)
> > > + (BUILD_ID_SIZE_MAX * 2) + 1 + \
> > > + KSYM_LINEINFO_LEN)
> > >
> > > struct cred;
> > > struct module;
Best Regards,
Petr
^ permalink raw reply
* RE: [EXTERNAL] [PATCH 38/61] net: Prefer IS_ERR_OR_NULL over manual NULL check
From: Elad Nachman @ 2026-03-10 15:07 UTC (permalink / raw)
To: Philipp Hahn, amd-gfx@lists.freedesktop.org,
apparmor@lists.ubuntu.com, bpf@vger.kernel.org,
ceph-devel@vger.kernel.org, cocci@inria.fr,
dm-devel@lists.linux.dev, dri-devel@lists.freedesktop.org,
gfs2@lists.linux.dev, intel-gfx@lists.freedesktop.org,
intel-wired-lan@lists.osuosl.org, iommu@lists.linux.dev,
kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-block@vger.kernel.org, linux-bluetooth@vger.kernel.org,
linux-btrfs@vger.kernel.org, linux-cifs@vger.kernel.org,
linux-clk@vger.kernel.org, linux-erofs@lists.ozlabs.org,
linux-ext4@vger.kernel.org, linux-fsdevel@vger.kernel.org,
linux-gpio@vger.kernel.org, linux-hyperv@vger.kernel.org,
linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-leds@vger.kernel.org, linux-media@vger.kernel.org,
linux-mips@vger.kernel.org, linux-mm@kvack.org,
linux-modules@vger.kernel.org, linux-mtd@lists.infradead.org,
linux-nfs@vger.kernel.org, linux-omap@vger.kernel.org,
linux-phy@lists.infradead.org, linux-pm@vger.kernel.org,
linux-rockchip@lists.infradead.org, linux-s390@vger.kernel.org,
linux-scsi@vger.kernel.org, linux-sctp@vger.kernel.org,
linux-security-module@vger.kernel.org, linux-sh@vger.kernel.org,
linux-sound@vger.kernel.org,
linux-stm32@st-md-mailman.stormreply.com,
linux-trace-kernel@vger.kernel.org, linux-usb@vger.kernel.org,
linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
ntfs3@lists.linux.dev, samba-technical@lists.samba.org,
sched-ext@lists.linux.dev, target-devel@vger.kernel.org,
tipc-discussion@lists.sourceforge.net, v9fs@lists.linux.dev
Cc: Igor Russkikh, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Pavan Chebbi, Michael Chan,
Potnuri Bharat Teja, Tony Nguyen, Przemek Kitszel, Taras Chornyi,
Maxime Coquelin, Alexandre Torgue, Iyappan Subramanian,
Keyur Chudgar, Quan Nguyen, Heiner Kallweit, Russell King
In-Reply-To: <20260310-b4-is_err_or_null-v1-38-bd63b656022d@avm.de>
>
>
> From: Philipp Hahn <phahn-oss@avm.de>
> Sent: Tuesday, March 10, 2026 1:49 PM
> To: amd-gfx@lists.freedesktop.org; apparmor@lists.ubuntu.com; bpf@vger.kernel.org; ceph-devel@vger.kernel.org; cocci@inria.fr; dm-devel@lists.linux.dev; dri-devel@lists.freedesktop.org; gfs2@lists.linux.dev; intel-gfx@lists.freedesktop.org; intel-wired-lan@lists.osuosl.org; iommu@lists.linux.dev; kvm@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-block@vger.kernel.org; linux-bluetooth@vger.kernel.org; linux-btrfs@vger.kernel.org; linux-cifs@vger.kernel.org; linux-clk@vger.kernel.org; linux-erofs@lists.ozlabs.org; linux-ext4@vger.kernel.org; linux-fsdevel@vger.kernel.org; linux-gpio@vger.kernel.org; linux-hyperv@vger.kernel.org; linux-input@vger.kernel.org; linux-kernel@vger.kernel.org; linux-leds@vger.kernel.org; linux-media@vger.kernel.org; linux-mips@vger.kernel.org; linux-mm@kvack.org; linux-modules@vger.kernel.org; linux-mtd@lists.infradead.org; linux-nfs@vger.kernel.org; linux-omap@vger.kernel.org; linux-phy@lists.infradead.org; linux-pm@vger.kernel.org; linux-rockchip@lists.infradead.org; linux-s390@vger.kernel.org; linux-scsi@vger.kernel.org; linux-sctp@vger.kernel.org; linux-security-module@vger.kernel.org; linux-sh@vger.kernel.org; linux-sound@vger.kernel.org; linux-stm32@st-md-mailman.stormreply.com; linux-trace-kernel@vger.kernel.org; linux-usb@vger.kernel.org; linux-wireless@vger.kernel.org; netdev@vger.kernel.org; ntfs3@lists.linux.dev; samba-technical@lists.samba.org; sched-ext@lists.linux.dev; target-devel@vger.kernel.org; tipc-discussion@lists.sourceforge.net; v9fs@lists.linux.dev; Philipp Hahn <phahn-oss@avm.de>
> Cc: Igor Russkikh <irusskikh@marvell.com>; Andrew Lunn <andrew+netdev@lunn.ch>; David S. Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>; Pavan Chebbi <pavan.chebbi@broadcom.com>; Michael Chan <mchan@broadcom.com>; Potnuri Bharat Teja <bharat@chelsio.com>; Tony Nguyen <anthony.l.nguyen@intel.com>; Przemek Kitszel <przemyslaw.kitszel@intel.com>; Taras Chornyi <taras.chornyi@plvision.eu>; Maxime Coquelin <mcoquelin.stm32@gmail.com>; Alexandre Torgue <alexandre.torgue@foss.st.com>; Iyappan Subramanian <iyappan@os.amperecomputing.com>; Keyur Chudgar <keyur@os.amperecomputing.com>; Quan Nguyen <quan@os.amperecomputing.com>; Heiner Kallweit <hkallweit1@gmail.com>; Russell King <linux@armlinux.org.uk>
> Subject: [EXTERNAL] [PATCH 38/61] net: Prefer IS_ERR_OR_NULL over manual NULL check
> ZjQcmQRYFpfptBannerEnd
> Prefer using IS_ERR_OR_NULL() over using IS_ERR() and a manual NULL
> check.
>
> Change generated with coccinelle.
>
> To: Igor Russkikh <mailto:irusskikh@marvell.com>
> To: Andrew Lunn <mailto:andrew+netdev@lunn.ch>
> To: "David S. Miller" <mailto:davem@davemloft.net>
> To: Eric Dumazet <mailto:edumazet@google.com>
> To: Jakub Kicinski <mailto:kuba@kernel.org>
> To: Paolo Abeni <mailto:pabeni@redhat.com>
> To: Pavan Chebbi <mailto:pavan.chebbi@broadcom.com>
> To: Michael Chan <mailto:mchan@broadcom.com>
> To: Potnuri Bharat Teja <mailto:bharat@chelsio.com>
> To: Tony Nguyen <mailto:anthony.l.nguyen@intel.com>
> To: Przemek Kitszel <mailto:przemyslaw.kitszel@intel.com>
> To: Taras Chornyi <mailto:taras.chornyi@plvision.eu>
> To: Maxime Coquelin <mailto:mcoquelin.stm32@gmail.com>
> To: Alexandre Torgue <mailto:alexandre.torgue@foss.st.com>
> To: Iyappan Subramanian <mailto:iyappan@os.amperecomputing.com>
> To: Keyur Chudgar <mailto:keyur@os.amperecomputing.com>
> To: Quan Nguyen <mailto:quan@os.amperecomputing.com>
> To: Heiner Kallweit <mailto:hkallweit1@gmail.com>
> To: Russell King <mailto:linux@armlinux.org.uk>
> Cc: mailto:netdev@vger.kernel.org
> Cc: mailto:linux-kernel@vger.kernel.org
> Cc: mailto:intel-wired-lan@lists.osuosl.org
> Cc: mailto:linux-stm32@st-md-mailman.stormreply.com
> Cc: mailto:linux-arm-kernel@lists.infradead.org
> Cc: mailto:linux-usb@vger.kernel.org
> Signed-off-by: Philipp Hahn <mailto:phahn-oss@avm.de>
> ---
> drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 2 +-
> drivers/net/ethernet/broadcom/tg3.c | 2 +-
> drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c | 3 +--
> drivers/net/ethernet/intel/ice/devlink/devlink.c | 2 +-
> drivers/net/ethernet/marvell/prestera/prestera_router.c | 2 +-
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +-
> drivers/net/mdio/mdio-xgene.c | 2 +-
> drivers/net/usb/r8152.c | 2 +-
> 8 files changed, 8 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
> index e270327e47fd804cc8ee5cfd53ed1b993c955c41..43edef35c4b1ff606b2f1519a07fad4c9a990ad4 100644
> --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
> +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
> @@ -810,7 +810,7 @@ static int __aq_ring_xdp_clean(struct aq_ring_s *rx_ring,
> }
>
> skb = aq_xdp_run_prog(aq_nic, &xdp, rx_ring, buff);
> - if (IS_ERR(skb) || !skb)
> + if (IS_ERR_OR_NULL(skb))
> continue;
>
> if (ptp_hwtstamp_len > 0)
> diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
> index 2328fce336447eb4a796f9300ccc0ab536ff0a35..8ed79f34f03d81184dcc12e6eaff009cb8f7756e 100644
> --- a/drivers/net/ethernet/broadcom/tg3.c
> +++ b/drivers/net/ethernet/broadcom/tg3.c
> @@ -7943,7 +7943,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
>
> segs = skb_gso_segment(skb, tp->dev->features &
> ~(NETIF_F_TSO | NETIF_F_TSO6));
> - if (IS_ERR(segs) || !segs) {
> + if (IS_ERR_OR_NULL(segs)) {
> tnapi->tx_dropped++;
> goto tg3_tso_bug_end;
> }
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> index 3307e50426819087ad985178c4a5383f16b8e7b4..1c8a6445d4b2e3535d8f1b7908dd02d8dd2f23fa 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> @@ -1032,8 +1032,7 @@ static void ch_flower_stats_handler(struct work_struct *work)
> do {
> rhashtable_walk_start(&iter);
>
> - while ((flower_entry = rhashtable_walk_next(&iter)) &&
> - !IS_ERR(flower_entry)) {
> + while (!IS_ERR_OR_NULL((flower_entry = rhashtable_walk_next(&iter)))) {
> ret = cxgb4_get_filter_counters(adap->port[0],
> flower_entry->filter_id,
> &packets, &bytes,
> diff --git a/drivers/net/ethernet/intel/ice/devlink/devlink.c b/drivers/net/ethernet/intel/ice/devlink/devlink.c
> index 6c72bd15db6d75a1d4fa04ef8fefbd26fb6e84bd..3d08b9187fd76ca3198af28111b6f1c1765ea01e 100644
> --- a/drivers/net/ethernet/intel/ice/devlink/devlink.c
> +++ b/drivers/net/ethernet/intel/ice/devlink/devlink.c
> @@ -791,7 +791,7 @@ static void ice_traverse_tx_tree(struct devlink *devlink, struct ice_sched_node
> node->parent->rate_node);
> }
>
> - if (rate_node && !IS_ERR(rate_node))
> + if (!IS_ERR_OR_NULL(rate_node))
> node->rate_node = rate_node;
>
> traverse_children:
> diff --git a/drivers/net/ethernet/marvell/prestera/prestera_router.c b/drivers/net/ethernet/marvell/prestera/prestera_router.c
> index b036b173a308b5f994ad8538eb010fa27196988c..4492938e8a3da91d32efe8d45ccbe2eb437c0e49 100644
> --- a/drivers/net/ethernet/marvell/prestera/prestera_router.c
> +++ b/drivers/net/ethernet/marvell/prestera/prestera_router.c
> @@ -1061,7 +1061,7 @@ static void __prestera_k_arb_hw_state_upd(struct prestera_switch *sw,
> n = NULL;
> }
>
> - if (!IS_ERR(n) && n) {
> + if (!IS_ERR_OR_NULL(n)) {
> neigh_event_send(n, NULL);
> neigh_release(n);
> } else {
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 6827c99bde8c22db42b363d2d36ad6f26075ed50..356a4e9ce04b1fcf8786d7274d31ace404be2cf6 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -1275,7 +1275,7 @@ static int stmmac_init_phy(struct net_device *dev)
> /* Some DT bindings do not set-up the PHY handle. Let's try to
> * manually parse it
> */
> - if (!phy_fwnode || IS_ERR(phy_fwnode)) {
> + if (IS_ERR_OR_NULL(phy_fwnode)) {
> int addr = priv->plat->phy_addr;
> struct phy_device *phydev;
>
> diff --git a/drivers/net/mdio/mdio-xgene.c b/drivers/net/mdio/mdio-xgene.c
> index a8f91a4b7fed0927ee14e408000cd3a2bfb9b09a..09b30b563295c6085dc1358ac361301e5cf6b2a8 100644
> --- a/drivers/net/mdio/mdio-xgene.c
> +++ b/drivers/net/mdio/mdio-xgene.c
> @@ -265,7 +265,7 @@ struct phy_device *xgene_enet_phy_register(struct mii_bus *bus, int phy_addr)
> struct phy_device *phy_dev;
>
> phy_dev = get_phy_device(bus, phy_addr, false);
> - if (!phy_dev || IS_ERR(phy_dev))
> + if (IS_ERR_OR_NULL(phy_dev))
> return NULL;
>
> if (phy_device_register(phy_dev))
> diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
> index 0c83bbbea2e7c322ee6339893e281237663bd3ae..73f17ebd7d40007eec5004f887a46249defd28ab 100644
> --- a/drivers/net/usb/r8152.c
> +++ b/drivers/net/usb/r8152.c
> @@ -2218,7 +2218,7 @@ static void r8152_csum_workaround(struct r8152 *tp, struct sk_buff *skb,
>
> features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
> segs = skb_gso_segment(skb, features);
> - if (IS_ERR(segs) || !segs)
> + if (IS_ERR_OR_NULL(segs))
> goto drop;
>
> __skb_queue_head_init(&seg_list);
>
> --
> 2.43.0
>
>
Acked-by: Elad Nachman <enachman@marvell.com>
^ permalink raw reply
* [PATCH v2 2/2] tree-wide: rename do_exit() to task_exit()
From: Christian Brauner @ 2026-03-10 14:56 UTC (permalink / raw)
To: Linus Torvalds
Cc: linux-kernel, linux-modules, linux-nfs, bpf, kunit-dev, linux-doc,
linux-trace-kernel, netfs, io-uring, audit, rcu, kvm,
virtualization, netdev, linux-mm, linux-security-module,
Christian Loehle, linux-fsdevel, Christian Brauner
In-Reply-To: <20260310-work-kernel-exit-v2-0-30711759d87b@kernel.org>
Rename do_exit() to task_exit() so it's clear that this is an api and
not a hidden internal helper.
Signed-off-by: Christian Brauner <brauner@kernel.org>
---
Documentation/accounting/taskstats-struct.rst | 2 +-
Documentation/locking/robust-futexes.rst | 8 ++++----
Documentation/trace/kprobes.rst | 2 +-
fs/cachefiles/namei.c | 2 +-
include/linux/kernel.h | 2 +-
include/linux/module.h | 2 +-
include/linux/sunrpc/svc.h | 2 +-
io_uring/io-wq.c | 2 +-
io_uring/sqpoll.c | 2 +-
kernel/acct.c | 2 +-
kernel/auditsc.c | 4 ++--
kernel/bpf/verifier.c | 2 +-
kernel/exit.c | 10 +++++-----
kernel/futex/futex.h | 2 +-
kernel/futex/pi.c | 2 +-
kernel/futex/syscalls.c | 2 +-
kernel/kthread.c | 8 ++++----
kernel/locking/rwsem.c | 2 +-
kernel/module/main.c | 2 +-
kernel/pid_namespace.c | 2 +-
kernel/rcu/tasks.h | 12 ++++++------
kernel/reboot.c | 6 +++---
kernel/seccomp.c | 8 ++++----
kernel/signal.c | 4 ++--
kernel/time/posix-timers.c | 2 +-
kernel/umh.c | 2 +-
kernel/vhost_task.c | 2 +-
lib/kunit/try-catch.c | 2 +-
mm/hugetlb.c | 2 +-
security/tomoyo/gc.c | 2 +-
tools/objtool/noreturns.h | 2 +-
tools/testing/selftests/bpf/prog_tests/tracing_failure.c | 2 +-
tools/testing/selftests/bpf/progs/tracing_failure.c | 2 +-
.../selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc | 2 +-
.../selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc | 2 +-
.../selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc | 2 +-
36 files changed, 58 insertions(+), 58 deletions(-)
diff --git a/Documentation/accounting/taskstats-struct.rst b/Documentation/accounting/taskstats-struct.rst
index acca51c34157..a09ec032da81 100644
--- a/Documentation/accounting/taskstats-struct.rst
+++ b/Documentation/accounting/taskstats-struct.rst
@@ -9,7 +9,7 @@ There are three different groups of fields in the struct taskstats:
1) Common and basic accounting fields
If CONFIG_TASKSTATS is set, the taskstats interface is enabled and
the common fields and basic accounting fields are collected for
- delivery at do_exit() of a task.
+ delivery at task_exit() of a task.
2) Delay accounting fields
These fields are placed between::
diff --git a/Documentation/locking/robust-futexes.rst b/Documentation/locking/robust-futexes.rst
index 6361fb01c9c1..c10a2fabf3f9 100644
--- a/Documentation/locking/robust-futexes.rst
+++ b/Documentation/locking/robust-futexes.rst
@@ -55,7 +55,7 @@ To solve this problem, the traditional approach was to extend the vma
(virtual memory area descriptor) concept to have a notion of 'pending
robust futexes attached to this area'. This approach requires 3 new
syscall variants to sys_futex(): FUTEX_REGISTER, FUTEX_DEREGISTER and
-FUTEX_RECOVER. At do_exit() time, all vmas are searched to see whether
+FUTEX_RECOVER. At task_exit() time, all vmas are searched to see whether
they have a robust_head set. This approach has two fundamental problems
left:
@@ -89,11 +89,11 @@ New approach to robust futexes
At the heart of this new approach there is a per-thread private list of
robust locks that userspace is holding (maintained by glibc) - which
userspace list is registered with the kernel via a new syscall [this
-registration happens at most once per thread lifetime]. At do_exit()
+registration happens at most once per thread lifetime]. At task_exit()
time, the kernel checks this user-space list: are there any robust futex
locks to be cleaned up?
-In the common case, at do_exit() time, there is no list registered, so
+In the common case, at task_exit() time, there is no list registered, so
the cost of robust futexes is just a simple current->robust_list != NULL
comparison. If the thread has registered a list, then normally the list
is empty. If the thread/process crashed or terminated in some incorrect
@@ -102,7 +102,7 @@ walks the list [not trusting it], and marks all locks that are owned by
this thread with the FUTEX_OWNER_DIED bit, and wakes up one waiter (if
any).
-The list is guaranteed to be private and per-thread at do_exit() time,
+The list is guaranteed to be private and per-thread at task_exit() time,
so it can be accessed by the kernel in a lockless way.
There is one race possible though: since adding to and removing from the
diff --git a/Documentation/trace/kprobes.rst b/Documentation/trace/kprobes.rst
index 5e606730cec6..ca9c22588dff 100644
--- a/Documentation/trace/kprobes.rst
+++ b/Documentation/trace/kprobes.rst
@@ -593,7 +593,7 @@ produce undesirable results. In such a case, a line:
kretprobe BUG!: Processing kretprobe d000000000041aa8 @ c00000000004f48c
gets printed. With this information, one will be able to correlate the
exact instance of the kretprobe that caused the problem. We have the
-do_exit() case covered. do_execve() and do_fork() are not an issue.
+task_exit() case covered. do_execve() and do_fork() are not an issue.
We're unaware of other specific cases where this could be a problem.
If, upon entry to or exit from a function, the CPU is running on
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index e5ec90dccc27..803657450f6b 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -555,7 +555,7 @@ static bool cachefiles_open_file(struct cachefiles_object *object,
}
/* We need to open a file interface onto a data file now as we can't do
- * it on demand because writeback called from do_exit() sees
+ * it on demand because writeback called from task_exit() sees
* current->fs == NULL - which breaks d_path() called from ext4 open.
*/
path.mnt = cache->mnt;
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e5570a16cbb1..91ce3abd65ad 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -148,7 +148,7 @@ void __might_fault(const char *file, int line);
static inline void might_fault(void) { }
#endif
-void do_exit(long error_code) __noreturn;
+void task_exit(long error_code) __noreturn;
extern int core_kernel_text(unsigned long addr);
extern int __kernel_text_address(unsigned long addr);
diff --git a/include/linux/module.h b/include/linux/module.h
index 79ac4a700b39..61254c7af4b8 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -855,7 +855,7 @@ static inline int unregister_module_notifier(struct notifier_block *nb)
return 0;
}
-#define module_put_and_kthread_exit(code) do_exit(code)
+#define module_put_and_kthread_exit(code) task_exit(code)
static inline void print_modules(void)
{
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index c86fc8a87eae..41cc1a8bfc95 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -338,7 +338,7 @@ static inline void svc_thread_init_status(struct svc_rqst *rqstp, int err)
{
store_release_wake_up(&rqstp->rq_err, err);
if (err)
- do_exit(1);
+ task_exit(1);
}
struct svc_deferred_req {
diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c
index 7a9f94a0ce6f..6befba7b9473 100644
--- a/io_uring/io-wq.c
+++ b/io_uring/io-wq.c
@@ -261,7 +261,7 @@ static void io_worker_exit(struct io_worker *worker)
kfree_rcu(worker, rcu);
io_worker_ref_put(wq);
- do_exit(0);
+ task_exit(0);
}
static inline bool __io_acct_run_queue(struct io_wq_acct *acct)
diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c
index c6bb938ec5ea..b7968a0aa748 100644
--- a/io_uring/sqpoll.c
+++ b/io_uring/sqpoll.c
@@ -423,7 +423,7 @@ static int io_sq_thread(void *data)
mutex_unlock(&sqd->lock);
err_out:
complete(&sqd->exited);
- do_exit(0);
+ task_exit(0);
}
void io_sqpoll_wait_sq(struct io_ring_ctx *ctx)
diff --git a/kernel/acct.c b/kernel/acct.c
index 1e19722c64c3..0c9a2280b1ff 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -424,7 +424,7 @@ static u32 encode_float(u64 value)
* The acct_process() call is the workhorse of the process
* accounting system. The struct acct is built here and then written
* into the accounting file. This function should only be called from
- * do_exit() or when switching to a different output file.
+ * task_exit() or when switching to a different output file.
*/
static void fill_ac(struct bsd_acct_struct *acct)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index f6af6a8f68c4..921acd5c8e77 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1797,7 +1797,7 @@ static void audit_log_exit(void)
* __audit_free - free a per-task audit context
* @tsk: task whose audit context block to free
*
- * Called from copy_process, do_exit, and the io_uring code
+ * Called from copy_process, task_exit, and the io_uring code
*/
void __audit_free(struct task_struct *tsk)
{
@@ -1810,7 +1810,7 @@ void __audit_free(struct task_struct *tsk)
if (!list_empty(&context->killed_trees))
audit_kill_trees(context);
- /* We are called either by do_exit() or the fork() error handling code;
+ /* We are called either by task_exit() or the fork() error handling code;
* in the former case tsk == current and in the latter tsk is a
* random task_struct that doesn't have any meaningful data we
* need to log via audit_log_exit().
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 159b25f8269d..4dff24eb86b0 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -25289,10 +25289,10 @@ BTF_ID(func, __module_put_and_kthread_exit)
BTF_ID(func, __x64_sys_exit)
BTF_ID(func, __x64_sys_exit_group)
#endif
-BTF_ID(func, do_exit)
BTF_ID(func, do_group_exit)
BTF_ID(func, kthread_complete_and_exit)
BTF_ID(func, make_task_dead)
+BTF_ID(func, task_exit)
BTF_SET_END(noreturn_deny)
static bool can_be_sleepable(struct bpf_prog *prog)
diff --git a/kernel/exit.c b/kernel/exit.c
index ede3117fa7d4..6c5c0968da14 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -893,7 +893,7 @@ static void synchronize_group_exit(struct task_struct *tsk, long code)
coredump_task_exit(tsk, core_state);
}
-void __noreturn do_exit(long code)
+void __noreturn task_exit(long code)
{
struct task_struct *tsk = current;
struct kthread *kthread;
@@ -1018,7 +1018,7 @@ void __noreturn do_exit(long code)
lockdep_free_task(tsk);
do_task_dead();
}
-EXPORT_SYMBOL(do_exit);
+EXPORT_SYMBOL(task_exit);
void __noreturn make_task_dead(int signr)
{
@@ -1077,12 +1077,12 @@ void __noreturn make_task_dead(int signr)
do_task_dead();
}
- do_exit(signr);
+ task_exit(signr);
}
SYSCALL_DEFINE1(exit, int, error_code)
{
- do_exit((error_code&0xff)<<8);
+ task_exit((error_code&0xff)<<8);
}
/*
@@ -1115,7 +1115,7 @@ do_group_exit(int exit_code)
spin_unlock_irq(&sighand->siglock);
}
- do_exit(exit_code);
+ task_exit(exit_code);
/* NOTREACHED */
}
diff --git a/kernel/futex/futex.h b/kernel/futex/futex.h
index 30c2afa03889..00fb2fc6579c 100644
--- a/kernel/futex/futex.h
+++ b/kernel/futex/futex.h
@@ -144,7 +144,7 @@ struct futex_hash_bucket {
struct futex_pi_state {
/*
* list of 'owned' pi_state instances - these have to be
- * cleaned up in do_exit() if the task exits prematurely:
+ * cleaned up in task_exit() if the task exits prematurely:
*/
struct list_head list;
diff --git a/kernel/futex/pi.c b/kernel/futex/pi.c
index bc1f7e83a37e..735b117574af 100644
--- a/kernel/futex/pi.c
+++ b/kernel/futex/pi.c
@@ -336,7 +336,7 @@ static int handle_exit_race(u32 __user *uaddr, u32 uval,
* CPU0 CPU1
*
* sys_exit() sys_futex()
- * do_exit() futex_lock_pi()
+ * task_exit() futex_lock_pi()
* futex_lock_pi_atomic()
* exit_signals(tsk) No waiters:
* tsk->flags |= PF_EXITING; *uaddr == 0x00000PID
diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c
index 743c7a728237..0ab5af6b9caf 100644
--- a/kernel/futex/syscalls.c
+++ b/kernel/futex/syscalls.c
@@ -10,7 +10,7 @@
* thread exit time.
*
* Implementation: user-space maintains a per-thread list of locks it
- * is holding. Upon do_exit(), the kernel carefully walks this list,
+ * is holding. Upon task_exit(), the kernel carefully walks this list,
* and marks all locks that are owned by this thread with the
* FUTEX_OWNER_DIED bit, and wakes up a waiter (if any). The list is
* always manipulated with the lock held, so the list is private and
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 1447c14c8540..e3d456e8d1e4 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -323,7 +323,7 @@ void __noreturn kthread_complete_and_exit(struct completion *comp, long code)
if (comp)
complete(comp);
- do_exit(code);
+ task_exit(code);
}
EXPORT_SYMBOL(kthread_complete_and_exit);
@@ -395,7 +395,7 @@ static int kthread(void *_create)
if (!done) {
kfree(create->full_name);
kfree(create);
- do_exit(-EINTR);
+ task_exit(-EINTR);
}
self->full_name = create->full_name;
@@ -435,7 +435,7 @@ static int kthread(void *_create)
__kthread_parkme(self);
ret = threadfn(data);
}
- do_exit(ret);
+ task_exit(ret);
}
/* called from kernel_clone() to get node information for about to be created task */
@@ -738,7 +738,7 @@ EXPORT_SYMBOL_GPL(kthread_park);
* instead of calling wake_up_process(): the thread will exit without
* calling threadfn().
*
- * If threadfn() may call do_exit() itself, the caller must ensure
+ * If threadfn() may call task_exit() itself, the caller must ensure
* task_struct can't go away.
*
* Returns the result of threadfn(), or %-EINTR if wake_up_process()
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index 24df4d98f7d2..390170de66af 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -554,7 +554,7 @@ static void rwsem_mark_wake(struct rw_semaphore *sem,
/*
* Ensure calling get_task_struct() before setting the reader
* waiter to nil such that rwsem_down_read_slowpath() cannot
- * race with do_exit() by always holding a reference count
+ * race with task_exit() by always holding a reference count
* to the task to wakeup.
*/
smp_store_release(&waiter->task, NULL);
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 340b4dc5c692..a06b6cc7402f 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -228,7 +228,7 @@ static int mod_strncmp(const char *str_a, const char *str_b, size_t n)
void __noreturn __module_put_and_kthread_exit(struct module *mod, long code)
{
module_put(mod);
- do_exit(code);
+ task_exit(code);
}
EXPORT_SYMBOL(__module_put_and_kthread_exit);
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index e48f5de41361..ef84e15530f3 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -339,7 +339,7 @@ int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)
send_sig(SIGKILL, pid_ns->child_reaper, 1);
read_unlock(&tasklist_lock);
- do_exit(0);
+ task_exit(0);
/* Not reached */
return 0;
diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
index 2b55e6acf3c1..657770e8b1cc 100644
--- a/kernel/rcu/tasks.h
+++ b/kernel/rcu/tasks.h
@@ -32,7 +32,7 @@ typedef void (*postgp_func_t)(struct rcu_tasks *rtp);
* @rtp_irq_work: IRQ work queue for deferred wakeups.
* @barrier_q_head: RCU callback for barrier operation.
* @rtp_blkd_tasks: List of tasks blocked as readers.
- * @rtp_exit_list: List of tasks in the latter portion of do_exit().
+ * @rtp_exit_list: List of tasks in the latter portion of task_exit().
* @cpu: CPU number corresponding to this entry.
* @index: Index of this CPU in rtpcp_array of the rcu_tasks structure.
* @rtpp: Pointer to the rcu_tasks structure.
@@ -922,12 +922,12 @@ static void rcu_tasks_wait_gp(struct rcu_tasks *rtp)
// number of voluntary context switches, and add that task to the
// holdout list.
// rcu_tasks_postscan():
-// Gather per-CPU lists of tasks in do_exit() to ensure that all
+// Gather per-CPU lists of tasks in task_exit() to ensure that all
// tasks that were in the process of exiting (and which thus might
// not know to synchronize with this RCU Tasks grace period) have
// completed exiting. The synchronize_rcu() in rcu_tasks_postgp()
// will take care of any tasks stuck in the non-preemptible region
-// of do_exit() following its call to exit_tasks_rcu_finish().
+// of task_exit() following its call to exit_tasks_rcu_finish().
// check_all_holdout_tasks(), repeatedly until holdout list is empty:
// Scans the holdout list, attempting to identify a quiescent state
// for each task on the list. If there is a quiescent state, the
@@ -1038,10 +1038,10 @@ static void rcu_tasks_postscan(struct list_head *hop)
*
* 1) A task_struct list addition before calling exit_notify(),
* which may remove the task from the tasklist, with the
- * removal after the final preempt_disable() call in do_exit().
+ * removal after the final preempt_disable() call in task_exit().
*
* 2) An _RCU_ read side starting with the final preempt_disable()
- * call in do_exit() and ending with the final call to schedule()
+ * call in task_exit() and ending with the final call to schedule()
* with TASK_DEAD state.
*
* This handles the part 1). And postgp will handle part 2) with a
@@ -1301,7 +1301,7 @@ void exit_tasks_rcu_start(void)
}
/*
- * Remove the task from the "yet another list" because do_exit() is now
+ * Remove the task from the "yet another list" because task_exit() is now
* non-preemptible, allowing synchronize_rcu() to wait beyond this point.
*/
void exit_tasks_rcu_finish(void)
diff --git a/kernel/reboot.c b/kernel/reboot.c
index 695c33e75efd..ceaf725bb423 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -747,7 +747,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
/*
* If pid namespaces are enabled and the current task is in a child
* pid_namespace, the command is handled by reboot_pid_ns() which will
- * call do_exit().
+ * call task_exit().
*/
ret = reboot_pid_ns(pid_ns, cmd);
if (ret)
@@ -777,11 +777,11 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
case LINUX_REBOOT_CMD_HALT:
kernel_halt();
- do_exit(0);
+ task_exit(0);
case LINUX_REBOOT_CMD_POWER_OFF:
kernel_power_off();
- do_exit(0);
+ task_exit(0);
break;
case LINUX_REBOOT_CMD_RESTART2:
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 066909393c38..f55d1c242e41 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -1081,7 +1081,7 @@ static void __secure_computing_strict(int this_syscall)
#endif
current->seccomp.mode = SECCOMP_MODE_DEAD;
seccomp_log(this_syscall, SIGKILL, SECCOMP_RET_KILL_THREAD, true);
- do_exit(SIGKILL);
+ task_exit(SIGKILL);
}
#ifndef CONFIG_HAVE_ARCH_SECCOMP_FILTER
@@ -1365,7 +1365,7 @@ static int __seccomp_filter(int this_syscall, const bool recheck_after_trace)
/* Trigger a coredump with SIGSYS */
force_sig_seccomp(this_syscall, data, true);
} else {
- do_exit(SIGSYS);
+ task_exit(SIGSYS);
}
return -1; /* skip the syscall go directly to signal handling */
}
@@ -1398,14 +1398,14 @@ int __secure_computing(void)
switch (mode) {
case SECCOMP_MODE_STRICT:
- __secure_computing_strict(this_syscall); /* may call do_exit */
+ __secure_computing_strict(this_syscall); /* may call task_exit */
return 0;
case SECCOMP_MODE_FILTER:
return __seccomp_filter(this_syscall, false);
/* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */
case SECCOMP_MODE_DEAD:
WARN_ON_ONCE(1);
- do_exit(SIGKILL);
+ task_exit(SIGKILL);
return -1;
default:
BUG();
diff --git a/kernel/signal.c b/kernel/signal.c
index d65d0fe24bfb..675f222074e1 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2238,7 +2238,7 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
* or setting the SA_NOCLDWAIT flag: we should be reaped
* automatically and not left for our parent's wait4 call.
* Rather than having the parent do it as a magic kind of
- * signal handler, we just set this to tell do_exit that we
+ * signal handler, we just set this to tell task_exit that we
* can be cleaned up without becoming a zombie. Note that
* we still call __wake_up_parent in this case, because a
* blocked sys_wait4 might now return -ECHILD.
@@ -3022,7 +3022,7 @@ bool get_signal(struct ksignal *ksig)
/*
* PF_USER_WORKER threads will catch and exit on fatal signals
* themselves. They have cleanup that must be performed, so we
- * cannot call do_exit() on their behalf. Note that ksig won't
+ * cannot call task_exit() on their behalf. Note that ksig won't
* be properly initialized, PF_USER_WORKER's shouldn't use it.
*/
if (current->flags & PF_USER_WORKER)
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 413e2389f0a5..08657975d714 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1063,7 +1063,7 @@ SYSCALL_DEFINE1(timer_delete, timer_t, timer_id)
}
/*
- * Invoked from do_exit() when the last thread of a thread group exits.
+ * Invoked from task_exit() when the last thread of a thread group exits.
* At that point no other task can access the timers of the dying
* task anymore.
*/
diff --git a/kernel/umh.c b/kernel/umh.c
index cffda97d961c..69ee75ca9340 100644
--- a/kernel/umh.c
+++ b/kernel/umh.c
@@ -119,7 +119,7 @@ static int call_usermodehelper_exec_async(void *data)
umh_complete(sub_info);
if (!retval)
return 0;
- do_exit(0);
+ task_exit(0);
}
/* Handles UMH_WAIT_PROC. */
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index 3f1ed7ef0582..554ec8fe7f5a 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -64,7 +64,7 @@ static int vhost_task_fn(void *data)
mutex_unlock(&vtsk->exit_mutex);
complete(&vtsk->exited);
- do_exit(0);
+ task_exit(0);
}
/**
diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
index 99d9603a2cfd..e5de71d68ef4 100644
--- a/lib/kunit/try-catch.c
+++ b/lib/kunit/try-catch.c
@@ -18,7 +18,7 @@
void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)
{
try_catch->try_result = -EFAULT;
- do_exit(0);
+ task_exit(0);
}
EXPORT_SYMBOL_GPL(kunit_try_catch_throw);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 0beb6e22bc26..a7ca30d533e7 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -5294,7 +5294,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
* Adjust the reservation for the region that will have the
* reserve restored. Keep in mind that vma_needs_reservation() changes
* resv->adds_in_progress if it succeeds. If this is not done,
- * do_exit() will not see it, and will keep the reservation
+ * task_exit() will not see it, and will keep the reservation
* forever.
*/
if (adjust_reservation) {
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
index 8e2008863af8..e0b72661d6bf 100644
--- a/security/tomoyo/gc.c
+++ b/security/tomoyo/gc.c
@@ -640,7 +640,7 @@ static int tomoyo_gc_thread(void *unused)
}
mutex_unlock(&tomoyo_gc_mutex);
out:
- /* This acts as do_exit(0). */
+ /* This acts as task_exit(0). */
return 0;
}
diff --git a/tools/objtool/noreturns.h b/tools/objtool/noreturns.h
index 40c0b05c6726..48fc90f30769 100644
--- a/tools/objtool/noreturns.h
+++ b/tools/objtool/noreturns.h
@@ -23,7 +23,6 @@ NORETURN(bch2_trans_restart_error)
NORETURN(bch2_trans_unlocked_or_in_restart_error)
NORETURN(cpu_bringup_and_idle)
NORETURN(cpu_startup_entry)
-NORETURN(do_exit)
NORETURN(do_group_exit)
NORETURN(do_task_dead)
NORETURN(ex_handler_msr_mce)
@@ -47,6 +46,7 @@ NORETURN(rust_helper_BUG)
NORETURN(sev_es_terminate)
NORETURN(start_kernel)
NORETURN(stop_this_cpu)
+NORETURN(task_exit)
NORETURN(usercopy_abort)
NORETURN(x86_64_start_kernel)
NORETURN(x86_64_start_reservations)
diff --git a/tools/testing/selftests/bpf/prog_tests/tracing_failure.c b/tools/testing/selftests/bpf/prog_tests/tracing_failure.c
index f9f9e1cb87bf..1a97e71fd68d 100644
--- a/tools/testing/selftests/bpf/prog_tests/tracing_failure.c
+++ b/tools/testing/selftests/bpf/prog_tests/tracing_failure.c
@@ -73,7 +73,7 @@ static void test_tracing_deny(void)
static void test_fexit_noreturns(void)
{
test_tracing_fail_prog("fexit_noreturns",
- "Attaching fexit/fsession/fmod_ret to __noreturn function 'do_exit' is rejected.");
+ "Attaching fexit/fsession/fmod_ret to __noreturn function 'task_exit' is rejected.");
}
void test_tracing_failure(void)
diff --git a/tools/testing/selftests/bpf/progs/tracing_failure.c b/tools/testing/selftests/bpf/progs/tracing_failure.c
index 65e485c4468c..5144f4cc5787 100644
--- a/tools/testing/selftests/bpf/progs/tracing_failure.c
+++ b/tools/testing/selftests/bpf/progs/tracing_failure.c
@@ -25,7 +25,7 @@ int BPF_PROG(tracing_deny)
return 0;
}
-SEC("?fexit/do_exit")
+SEC("?fexit/task_exit")
int BPF_PROG(fexit_noreturns)
{
return 0;
diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc
index fee479295e2f..7e00d8ecd110 100644
--- a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc
+++ b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc
@@ -82,7 +82,7 @@ check_error 'f vfs_read arg1=^' # NO_ARG_BODY
# multiprobe errors
if grep -q "Create/append/" README && grep -q "imm-value" README; then
echo "f:fprobes/testevent $FUNCTION_FORK" > dynamic_events
-check_error '^f:fprobes/testevent do_exit%return' # DIFF_PROBE_TYPE
+check_error '^f:fprobes/testevent task_exit%return' # DIFF_PROBE_TYPE
# Explicitly use printf "%s" to not interpret \1
printf "%s" "f:fprobes/testevent $FUNCTION_FORK abcd=\\1" > dynamic_events
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc
index f0d5b7777ed7..a95e3824690a 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc
@@ -5,7 +5,7 @@
# Choose 2 symbols for target
SYM1=$FUNCTION_FORK
-SYM2=do_exit
+SYM2=task_exit
EVENT_NAME=kprobes/testevent
DEF1="p:$EVENT_NAME $SYM1"
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
index 8f1c58f0c239..b55ea3c05cfa 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
@@ -87,7 +87,7 @@ esac
# multiprobe errors
if grep -q "Create/append/" README && grep -q "imm-value" README; then
echo "p:kprobes/testevent $FUNCTION_FORK" > kprobe_events
-check_error '^r:kprobes/testevent do_exit' # DIFF_PROBE_TYPE
+check_error '^r:kprobes/testevent task_exit' # DIFF_PROBE_TYPE
# Explicitly use printf "%s" to not interpret \1
printf "%s" "p:kprobes/testevent $FUNCTION_FORK abcd=\\1" > kprobe_events
--
2.47.3
^ permalink raw reply related
* [PATCH v2 1/2] kthread: remove kthread_exit()
From: Christian Brauner @ 2026-03-10 14:56 UTC (permalink / raw)
To: Linus Torvalds
Cc: linux-kernel, linux-modules, linux-nfs, bpf, kunit-dev, linux-doc,
linux-trace-kernel, netfs, io-uring, audit, rcu, kvm,
virtualization, netdev, linux-mm, linux-security-module,
Christian Loehle, linux-fsdevel, Christian Brauner
In-Reply-To: <20260310-work-kernel-exit-v2-0-30711759d87b@kernel.org>
In 28aaa9c39945 ("kthread: consolidate kthread exit paths to prevent use-after-free")
we folded kthread_exit() into do_exit() when we fixed a nasty UAF bug.
We left kthread_exit() around as an alias to do_exit(). Remove it
completely.
Reported-by: Christian Loehle <christian.loehle@arm.com>
Link: https://lore.kernel.org/1ff1bce2-8bb4-463c-a631-16e14f4ea7e2@arm.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
---
include/linux/kthread.h | 1 -
include/linux/module.h | 2 +-
include/linux/sunrpc/svc.h | 2 +-
kernel/kthread.c | 8 ++++----
kernel/module/main.c | 2 +-
lib/kunit/try-catch.c | 2 +-
tools/objtool/noreturns.h | 1 -
7 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index a01a474719a7..37982eca94f1 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -116,7 +116,6 @@ void *kthread_probe_data(struct task_struct *k);
int kthread_park(struct task_struct *k);
void kthread_unpark(struct task_struct *k);
void kthread_parkme(void);
-#define kthread_exit(result) do_exit(result)
void kthread_complete_and_exit(struct completion *, long) __noreturn;
int kthreads_update_housekeeping(void);
void kthread_do_exit(struct kthread *, long);
diff --git a/include/linux/module.h b/include/linux/module.h
index 14f391b186c6..79ac4a700b39 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -855,7 +855,7 @@ static inline int unregister_module_notifier(struct notifier_block *nb)
return 0;
}
-#define module_put_and_kthread_exit(code) kthread_exit(code)
+#define module_put_and_kthread_exit(code) do_exit(code)
static inline void print_modules(void)
{
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 4dc14c7a711b..c86fc8a87eae 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -338,7 +338,7 @@ static inline void svc_thread_init_status(struct svc_rqst *rqstp, int err)
{
store_release_wake_up(&rqstp->rq_err, err);
if (err)
- kthread_exit(1);
+ do_exit(1);
}
struct svc_deferred_req {
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 791210daf8b4..1447c14c8540 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -323,7 +323,7 @@ void __noreturn kthread_complete_and_exit(struct completion *comp, long code)
if (comp)
complete(comp);
- kthread_exit(code);
+ do_exit(code);
}
EXPORT_SYMBOL(kthread_complete_and_exit);
@@ -395,7 +395,7 @@ static int kthread(void *_create)
if (!done) {
kfree(create->full_name);
kfree(create);
- kthread_exit(-EINTR);
+ do_exit(-EINTR);
}
self->full_name = create->full_name;
@@ -435,7 +435,7 @@ static int kthread(void *_create)
__kthread_parkme(self);
ret = threadfn(data);
}
- kthread_exit(ret);
+ do_exit(ret);
}
/* called from kernel_clone() to get node information for about to be created task */
@@ -738,7 +738,7 @@ EXPORT_SYMBOL_GPL(kthread_park);
* instead of calling wake_up_process(): the thread will exit without
* calling threadfn().
*
- * If threadfn() may call kthread_exit() itself, the caller must ensure
+ * If threadfn() may call do_exit() itself, the caller must ensure
* task_struct can't go away.
*
* Returns the result of threadfn(), or %-EINTR if wake_up_process()
diff --git a/kernel/module/main.c b/kernel/module/main.c
index c3ce106c70af..340b4dc5c692 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -228,7 +228,7 @@ static int mod_strncmp(const char *str_a, const char *str_b, size_t n)
void __noreturn __module_put_and_kthread_exit(struct module *mod, long code)
{
module_put(mod);
- kthread_exit(code);
+ do_exit(code);
}
EXPORT_SYMBOL(__module_put_and_kthread_exit);
diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
index d84a879f0a78..99d9603a2cfd 100644
--- a/lib/kunit/try-catch.c
+++ b/lib/kunit/try-catch.c
@@ -18,7 +18,7 @@
void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)
{
try_catch->try_result = -EFAULT;
- kthread_exit(0);
+ do_exit(0);
}
EXPORT_SYMBOL_GPL(kunit_try_catch_throw);
diff --git a/tools/objtool/noreturns.h b/tools/objtool/noreturns.h
index 14f8ab653449..40c0b05c6726 100644
--- a/tools/objtool/noreturns.h
+++ b/tools/objtool/noreturns.h
@@ -30,7 +30,6 @@ NORETURN(ex_handler_msr_mce)
NORETURN(hlt_play_dead)
NORETURN(hv_ghcb_terminate)
NORETURN(kthread_complete_and_exit)
-NORETURN(kthread_exit)
NORETURN(kunit_try_catch_throw)
NORETURN(machine_real_restart)
NORETURN(make_task_dead)
--
2.47.3
^ permalink raw reply related
* [PATCH v2 0/2] kthread, exit: clean up kernel thread exit paths
From: Christian Brauner @ 2026-03-10 14:56 UTC (permalink / raw)
To: Linus Torvalds
Cc: linux-kernel, linux-modules, linux-nfs, bpf, kunit-dev, linux-doc,
linux-trace-kernel, netfs, io-uring, audit, rcu, kvm,
virtualization, netdev, linux-mm, linux-security-module,
Christian Loehle, linux-fsdevel, Christian Brauner
In 28aaa9c39945 ("kthread: consolidate kthread exit paths to prevent
use-after-free") we folded kthread_exit() into do_exit() to fix a UAF
bug but left kthread_exit() around as an alias. Remove it.
While at it, rename do_exit() to task_exit() to communicate that is not
just a private api.
Signed-off-by: Christian Brauner <brauner@kernel.org>
---
Christian Brauner (2):
kthread: remove kthread_exit()
tree-wide: rename do_exit() to task_exit()
Documentation/accounting/taskstats-struct.rst | 2 +-
Documentation/locking/robust-futexes.rst | 8 ++++----
Documentation/trace/kprobes.rst | 2 +-
fs/cachefiles/namei.c | 2 +-
include/linux/kernel.h | 2 +-
include/linux/kthread.h | 1 -
include/linux/module.h | 2 +-
include/linux/sunrpc/svc.h | 2 +-
io_uring/io-wq.c | 2 +-
io_uring/sqpoll.c | 2 +-
kernel/acct.c | 2 +-
kernel/auditsc.c | 4 ++--
kernel/bpf/verifier.c | 2 +-
kernel/exit.c | 10 +++++-----
kernel/futex/futex.h | 2 +-
kernel/futex/pi.c | 2 +-
kernel/futex/syscalls.c | 2 +-
kernel/kthread.c | 8 ++++----
kernel/locking/rwsem.c | 2 +-
kernel/module/main.c | 2 +-
kernel/pid_namespace.c | 2 +-
kernel/rcu/tasks.h | 12 ++++++------
kernel/reboot.c | 6 +++---
kernel/seccomp.c | 8 ++++----
kernel/signal.c | 4 ++--
kernel/time/posix-timers.c | 2 +-
kernel/umh.c | 2 +-
kernel/vhost_task.c | 2 +-
lib/kunit/try-catch.c | 2 +-
mm/hugetlb.c | 2 +-
security/tomoyo/gc.c | 2 +-
tools/objtool/noreturns.h | 3 +--
tools/testing/selftests/bpf/prog_tests/tracing_failure.c | 2 +-
tools/testing/selftests/bpf/progs/tracing_failure.c | 2 +-
.../selftests/ftrace/test.d/dynevent/fprobe_syntax_errors.tc | 2 +-
.../selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc | 2 +-
.../selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc | 2 +-
37 files changed, 58 insertions(+), 60 deletions(-)
---
base-commit: 1f318b96cc84d7c2ab792fcc0bfd42a7ca890681
change-id: 20260306-work-kernel-exit-2e8fd9e2c2a1
^ permalink raw reply
* Re: [PATCH 17/61] module: Prefer IS_ERR_OR_NULL over manual NULL check
From: Aaron Tomlin @ 2026-03-10 14:45 UTC (permalink / raw)
To: Philipp Hahn
Cc: amd-gfx, apparmor, bpf, ceph-devel, cocci, dm-devel, dri-devel,
gfs2, intel-gfx, intel-wired-lan, iommu, kvm, linux-arm-kernel,
linux-block, linux-bluetooth, linux-btrfs, linux-cifs, linux-clk,
linux-erofs, linux-ext4, linux-fsdevel, linux-gpio, linux-hyperv,
linux-input, linux-kernel, linux-leds, linux-media, linux-mips,
linux-mm, linux-modules, linux-mtd, linux-nfs, linux-omap,
linux-phy, linux-pm, linux-rockchip, linux-s390, linux-scsi,
linux-sctp, linux-security-module, linux-sh, linux-sound,
linux-stm32, linux-trace-kernel, linux-usb, linux-wireless,
netdev, ntfs3, samba-technical, sched-ext, target-devel,
tipc-discussion, v9fs, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen
In-Reply-To: <20260310-b4-is_err_or_null-v1-17-bd63b656022d@avm.de>
[-- Attachment #1: Type: text/plain, Size: 1458 bytes --]
On Tue, Mar 10, 2026 at 12:48:43PM +0100, Philipp Hahn wrote:
> Prefer using IS_ERR_OR_NULL() over using IS_ERR() and a manual NULL
> check.
>
> Change generated with coccinelle.
>
> To: Luis Chamberlain <mcgrof@kernel.org>
> To: Petr Pavlu <petr.pavlu@suse.com>
> To: Daniel Gomez <da.gomez@kernel.org>
> To: Sami Tolvanen <samitolvanen@google.com>
> To: Aaron Tomlin <atomlin@atomlin.com>
> Cc: linux-modules@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Philipp Hahn <phahn-oss@avm.de>
> ---
> kernel/module/main.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/module/main.c b/kernel/module/main.c
> index c3ce106c70af165e2dc1a3c79f5a074a5c3e3d34..7f62f0620dcd75960e431f7af3d1cadf4cc41e4b 100644
> --- a/kernel/module/main.c
> +++ b/kernel/module/main.c
> @@ -1551,7 +1551,7 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)
> case SHN_UNDEF:
> ksym = resolve_symbol_wait(mod, info, name);
> /* Ok if resolved. */
> - if (ksym && !IS_ERR(ksym)) {
> + if (!IS_ERR_OR_NULL(ksym)) {
> sym[i].st_value = kernel_symbol_value(ksym);
> break;
> }
>
> --
> 2.43.0
>
Hi Philipp,
Thank you.
Have you considered other users of IS_ERR() in kernel/module/main.c too?
Perhaps it might be best to prepare a clean up for each applicable
subsystem in isolation.
Kind regards,
--
Aaron Tomlin
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
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