Linux Trace Kernel
 help / color / mirror / Atom feed
* Re: [PATCH v2] bootconfig: Apply early options from embedded config
From: Masami Hiramatsu @ 2026-03-27 14:16 UTC (permalink / raw)
  To: Breno Leitao
  Cc: Jonathan Corbet, Shuah Khan, linux-kernel, linux-trace-kernel,
	linux-doc, oss, paulmck, rostedt, kernel-team
In-Reply-To: <acZX_IXQiGwMMi5e@gmail.com>

On Fri, 27 Mar 2026 03:18:31 -0700
Breno Leitao <leitao@debian.org> wrote:

> On Thu, Mar 26, 2026 at 11:30:42PM +0900, Masami Hiramatsu wrote:
> > On Wed, 25 Mar 2026 23:22:04 +0900
> > Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:
> >
> > > > +	/*
> > > > +	 * Keys that do not match any early_param() handler are silently
> > > > +	 * ignored — do_early_param() always returns 0.
> > > > +	 */
> > > > +	xbc_node_for_each_key_value(root, knode, val) {
> > >
> > > [sashiko comment]
> > > | Does this loop handle array values correctly?
> > > | xbc_node_for_each_key_value() only assigns the first value of an array to
> > > | the val pointer before advancing to the next key. It does not iterate over
> > > | the child nodes of the array.
> > > | If the bootconfig contains a multi-value key like
> > > | kernel.console = "ttyS0", "tty0", will the subsequent values in the array
> > > | be silently dropped instead of passed to the early_param handlers?
> > >
> > > Also, good catch :) we need to use xbc_node_for_each_array_value()
> > > for inner loop.
> >
> > FYI, xbc_snprint_cmdline() translates the arraied parameter as
> > multiple parameters. For example,
> >
> > foo = bar, buz;
> >
> > will be converted to
> >
> > foo=bar foo=buz
> >
> > Thus, I think we should do the same thing below;
> >
> > >
> > > > +		if (xbc_node_compose_key_after(root, knode, xbc_namebuf, XBC_KEYLEN_MAX) < 0)
> > > > +			continue;
> > > > +
> > > > +		/*
> > > > +		 * We need to copy const char *val to a char pointer,
> > > > +		 * which is what do_early_param() need, given it might
> > > > +		 * call strsep(), strtok() later.
> > > > +		 */
> > > > +		ret = strscpy(val_buf, val, sizeof(val_buf));
> > > > +		if (ret < 0) {
> > > > +			pr_warn("ignoring bootconfig value '%s', too long\n",
> > > > +				xbc_namebuf);
> > > > +			continue;
> > > > +		}
> > > > +		do_early_param(xbc_namebuf, val_buf, NULL, NULL);
> >
> > So instead of this;
> >
> > xbc_array_for_each_value(vnode, val) {
> > 	do_early_param(xbc_namebuf, val, NULL, NULL);
> > }
> >
> > Maybe it is a good timing to recondier unifying kernel cmdline and bootconfig
> > from API viewpoint.
> 
> I'm not familiar with the history on this topic. Has unifying the APIs been
> previously considered and set aside?

Previously I considered but I found some early parameters must be composed by
bootloaders, and they does not support bootconfig. Thus, I introduced
setup_boot_config() to compose kernel.* parameters into cmdline buffer.

> 
> Given all the feedback on this series, I see three types of issues to address:
> 
> 1) Minor patch improvements
> 2) Architecture-specific super early parameters being parsed before bootconfig
>    is available
> 3) Unifying kernel cmdline and bootconfig interfaces

I think we can start with 1) for embedded bootconfig for this series
with using bootconfig in parse_early_param().

For 2), I think it needs to check which parameters are expected to
be passed by bootloaders, which does not care bootconfig currently.

For 3), eventually it may be need to change how kernel handle the
parameters. I think I need to introduce CONFIG_BOOT_CONFIG_EXPOSED
option which keeps the xbc_*() API and parsed data accessible after
boot (Remove __init) and exposed to modules, so that all modules
can use xbc_* to get parameters from bootconfig directly.

Thanks,

> 
> Which of these areas would you recommend I prioritize?
> 
> Thanks for the guidance,
> --breno


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply

* Re: [PATCH next] tracing: Remove spurious default precision from show_event_trigger/filter formats
From: Steven Rostedt @ 2026-03-27 14:26 UTC (permalink / raw)
  To: Petr Mladek
  Cc: david.laight.linux, Masami Hiramatsu, Mathieu Desnoyers,
	linux-kernel, linux-trace-kernel, Aaron Tomlin, Rasmus Villemoes,
	Andy Shevchenko, Sergey Senozhatsky, Andrew Morton
In-Reply-To: <acZKpXQDTEPCU813@pathway.suse.cz>

On Fri, 27 Mar 2026 10:15:17 +0100
Petr Mladek <pmladek@suse.com> wrote:

> On Thu 2026-03-26 20:18:24, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> > 
> > Change 2d8b7f9bf8e6e ("tracing: Have show_event_trigger/filter format a bit more in columns")
> > added space padding to align the output.
> > However it used ("%*.s", len, "") which requests the default precision.
> > It doesn't matter here whether the userspace default (0) or kernel
> > default (no precision) is used, but the format should be "%*s".
> > 
> > Signed-off-by: David Laight <david.laight.linux@gmail.com>  
> 
> Makes sense. It does not change the output because it printed
> an empty string "" so the precision did not matter.

Right. I use this in user space all the time, and add "%*.s" a lot.

I tested it and it doesn't change the output so I'm happy to take it
through my tree.

-- Steve
 

> 
> Reviewed-by: Petr Mladek <pmladek@suse.com>
> 
> Best Regards,
> Petr


^ permalink raw reply

* [GIT PULL] RTLA changes for v7.1
From: Tomas Glozar @ 2026-03-27 15:02 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Costa Shulyupin, Wander Lairson Costa, LKML, linux-trace-kernel,
	Tomas Glozar

Steven,

please pull the following changes for RTLA (more info in tag description).

Thanks,
Tomas

The following changes since commit 11439c4635edd669ae435eec308f4ab8a0804808:

  Linux 7.0-rc2 (2026-03-01 15:39:31 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tglozar/linux.git tags/rtla-v7.1

for you to fetch changes up to 82374995b63d2de21414163828a32d52610dcaf2:

  Documentation/rtla: Document SIGINT behavior (2026-03-27 10:58:30 +0100)

----------------------------------------------------------------
RTLA patches for v7.1

- Simplify option parsing

Auto-generate getopt_long() optstring for short options from long options
array, avoiding the need to specify it manually and reducing the surface
for mistakes.

- Add unit tests

Implement unit tests (make unit-tests) using libcheck, next to existing
runtime tests (make check). Currently, three functions from utils.c are
tested.

- Add --stack-format option

In addition to stopping stack pointer decoding (with -s/--stack option)
on first unresolvable pointer, allow also skipping unresolvable pointers
and displaying everything, configurable with a new option.

- Unify number of CPUs into one global variable

Use one global variable, nr_cpus, to store the number of CPUs instead of
retrieving it and passing it at multiple places.

- Fix behavior in various corner cases

Make RTLA behave correctly in several corner cases: memory allocation
failure, invalid value read from kernel side, thread creation failure,
malformed time value input, and read/write failure or interruption by
signal.

- Improve string handling

Simplify several places in the code that handle strings, including
parsing of action arguments. A few new helper functions and variables
are added for that purpose.

- Get rid of magic numbers

Few places handling paths use a magic number of 1024. Replace it with
MAX_PATH and ARRAY_SIZE() macro.

- Unify threshold handling

Code that handles response to latency threshold is duplicated between
tools, which has led to bugs in the past. Unify it into a new helper
as much as possible.

- Fix segfault on SIGINT during cleanup

The SIGINT handler touches dynamically allocated memory. Detach it
before freeing it during cleanup to prevent segmentation fault and
discarding of output buffers. Also, properly document SIGINT handling
while at it.

The tag was tested (make && make check && make unit-tests) as well as
pre-tested on top of next-20260326. There are no known conflicts.

Signed-off-by: Tomas Glozar <tglozar@redhat.com>

----------------------------------------------------------------
Costa Shulyupin (7):
      tools/rtla: Generate optstring from long options
      tools/build: Add feature test for libcheck
      tools/rtla: Add unit tests for utils.c
      tools/rtla: Consolidate nr_cpus usage across all tools
      tools/rtla: Remove unneeded nr_cpus arguments
      tools/rtla: Remove unneeded nr_cpus members
      tools/rtla: Remove unneeded nr_cpus from for_each_monitored_cpu

Tomas Glozar (4):
      rtla/timerlat: Add --stack-format option
      Documentation/rtla: Document --stack-format option
      rtla: Fix segfault on multiple SIGINTs
      Documentation/rtla: Document SIGINT behavior

Wander Lairson Costa (17):
      rtla: Exit on memory allocation failures during initialization
      rtla: Use strdup() to simplify code
      rtla/actions: Simplify argument parsing
      rtla: Introduce common_threshold_handler() helper
      rtla: Replace magic number with MAX_PATH
      rtla: Simplify code by caching string lengths
      rtla/timerlat: Add bounds check for softirq vector
      rtla: Handle pthread_create() failure properly
      rtla: Add str_has_prefix() helper function
      rtla: Use str_has_prefix() for prefix checks
      rtla: Enforce exact match for time unit suffixes
      rtla: Use str_has_prefix() for option prefix check
      rtla/timerlat: Simplify RTLA_NO_BPF environment variable check
      rtla/trace: Fix write loop in trace_event_save_hist()
      rtla/trace: Fix I/O handling in save_trace_to_file()
      rtla/utils: Fix resource leak in set_comm_sched_attr()
      rtla/utils: Fix loop condition in PID validation

 Documentation/tools/rtla/common_appendix.txt       |  21 ++++
 .../tools/rtla/common_timerlat_options.txt         |  12 +++
 tools/build/Makefile.feature                       |   3 +
 tools/build/feature/Makefile                       |   4 +
 tools/build/feature/test-libcheck.c                |   8 ++
 tools/tracing/rtla/Build                           |   1 +
 tools/tracing/rtla/Makefile                        |   5 +
 tools/tracing/rtla/Makefile.config                 |   8 ++
 tools/tracing/rtla/README.txt                      |   1 +
 tools/tracing/rtla/src/actions.c                   | 103 +++++++++++-------
 tools/tracing/rtla/src/actions.h                   |   8 +-
 tools/tracing/rtla/src/common.c                    | 120 +++++++++++++++++----
 tools/tracing/rtla/src/common.h                    |  24 ++++-
 tools/tracing/rtla/src/osnoise.c                   |  26 ++---
 tools/tracing/rtla/src/osnoise_hist.c              |  51 ++++-----
 tools/tracing/rtla/src/osnoise_top.c               |  41 ++-----
 tools/tracing/rtla/src/timerlat.c                  |  16 ++-
 tools/tracing/rtla/src/timerlat.h                  |   1 +
 tools/tracing/rtla/src/timerlat_aa.c               |  51 ++++++---
 tools/tracing/rtla/src/timerlat_aa.h               |   2 +-
 tools/tracing/rtla/src/timerlat_bpf.c              |  19 ++--
 tools/tracing/rtla/src/timerlat_bpf.h              |  12 +--
 tools/tracing/rtla/src/timerlat_hist.c             | 116 +++++++++-----------
 tools/tracing/rtla/src/timerlat_top.c              | 114 +++++++++-----------
 tools/tracing/rtla/src/timerlat_u.c                |  13 ++-
 tools/tracing/rtla/src/timerlat_u.h                |   1 +
 tools/tracing/rtla/src/trace.c                     | 102 ++++++++++--------
 tools/tracing/rtla/src/trace.h                     |   4 +-
 tools/tracing/rtla/src/utils.c                     | 113 ++++++++++++++-----
 tools/tracing/rtla/src/utils.h                     |  33 ++++++
 tools/tracing/rtla/tests/unit/Build                |   2 +
 tools/tracing/rtla/tests/unit/Makefile.unit        |  17 +++
 tools/tracing/rtla/tests/unit/unit_tests.c         | 119 ++++++++++++++++++++
 33 files changed, 769 insertions(+), 402 deletions(-)
 create mode 100644 tools/build/feature/test-libcheck.c
 create mode 100644 tools/tracing/rtla/tests/unit/Build
 create mode 100644 tools/tracing/rtla/tests/unit/Makefile.unit
 create mode 100644 tools/tracing/rtla/tests/unit/unit_tests.c


^ permalink raw reply

* Re: [PATCH v2] bootconfig: Apply early options from embedded config
From: Breno Leitao @ 2026-03-27 16:11 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Jonathan Corbet, Shuah Khan, linux-kernel, linux-trace-kernel,
	linux-doc, oss, paulmck, rostedt, kernel-team
In-Reply-To: <20260327231630.2d6f4273b7d615bda4b51053@kernel.org>

On Fri, Mar 27, 2026 at 11:16:30PM +0900, Masami Hiramatsu wrote:
> > Given all the feedback on this series, I see three types of issues to address:
> >
> > 1) Minor patch improvements
> > 2) Architecture-specific super early parameters being parsed before bootconfig
> >    is available
> > 3) Unifying kernel cmdline and bootconfig interfaces
>
> I think we can start with 1) for embedded bootconfig for this series
> with using bootconfig in parse_early_param().

Thanks for the clear direction.

I'll work on integrating bootconfig into parse_early_param() to see
what can be achieved and identify any potential blockers.

I should be back soon with more fun.

Thanks so far,
--breno

^ permalink raw reply

* Re: Warning from free_reserved_area() in next-20260325+
From: Mike Rapoport @ 2026-03-27 17:12 UTC (permalink / raw)
  To: Bert Karwatzki
  Cc: linux-kernel, Liam.Howlett, akpm, andreas, ardb, bp, brauner,
	catalin.marinas, chleroy, dave.hansen, davem, david, devicetree,
	dvyukov, elver, glider, hannes, hpa, ilias.apalodimas, iommu,
	jack, jackmanb, kasan-dev, linux-arm-kernel, linux-efi,
	linux-fsdevel, linux-mm, linux-trace-kernel, linuxppc-dev,
	lorenzo.stoakes, m.szyprowski, maddy, mhiramat, mhocko, mingo,
	mpe, npiggin, robh, robin.murphy, saravanak, sparclinux, surenb,
	tglx, vbabka, viro, will, x86, ziy
In-Reply-To: <20260327140109.7561-1-spasswolf@web.de>

Hi Bert,

On Fri, Mar 27, 2026 at 03:01:08PM +0100, Bert Karwatzki wrote:
> Starting with linux next-20260325 I see the following warning early in the
> boot process of a machine running debian stable (trixie) (except for the kernel):

Thanks for the report!

> [    0.027118] [      T0] ------------[ cut here ]------------
> [    0.027118] [      T0] Cannot free reserved memory because of deferred initialization of the memory map
> [    0.027119] [      T0] WARNING: mm/memblock.c:904 at __free_reserved_area+0xa9/0xc0, CPU#0: swapper/0/0
> [    0.027122] [      T0] Modules linked in:
> [    0.027123] [      T0] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.0.0-rc5-next-20260326-master #385 PREEMPT_RT 
> [    0.027125] [      T0] Hardware name: ASUS System Product Name/ROG STRIX B850-F GAMING WIFI, BIOS 1627 02/05/2026
> [    0.027125] [      T0] RIP: 0010:__free_reserved_area+0xa9/0xc0
> [    0.027126] [      T0] Code: 48 89 df 48 89 ee e8 06 fe ff ff 48 89 c3 48 39 e8 72 a0 5b 4c 89 e8 5d 41 5c 41 5d 41 5e c3 cc cc cc cc 48 8d 3d 97 c2 c6 00 <67> 48 0f b9 3a 45 31 ed eb df 66 66 2e 0f 1f 84 00 00 00 00 00 66
> [    0.027127] [      T0] RSP: 0000:ffffffff9b203e98 EFLAGS: 00010202
> [    0.027128] [      T0] RAX: 0000000e91c00001 RBX: ffffffff9b100c0f RCX: 0000000080000001
> [    0.027128] [      T0] RDX: 00000000000000cc RSI: 0000000e2d42d000 RDI: ffffffff9b32ef60
> [    0.027128] [      T0] RBP: ffff9eeafdd6fbc0 R08: 0000000000000000 R09: 0000000000000001
> [    0.027129] [      T0] R10: 0000000000001000 R11: 8000000000000163 R12: 000000000000006f
> [    0.027129] [      T0] R13: 0000000000000000 R14: 0000000000000045 R15: 000000005c8a1000
> [    0.027129] [      T0] FS:  0000000000000000(0000) GS:ffff9eeb21c05000(0000) knlGS:0000000000000000
> [    0.027130] [      T0] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [    0.027130] [      T0] CR2: ffff9ee8ad801000 CR3: 0000000e2ce1e000 CR4: 0000000000f50ef0
> [    0.027131] [      T0] PKRU: 55555554
> [    0.027131] [      T0] Call Trace:
> [    0.027132] [      T0]  <TASK>
> [    0.027132] [      T0]  free_reserved_area+0x89/0xd0
> [    0.027133] [      T0]  alternative_instructions+0xee/0x110
> [    0.027136] [      T0]  arch_cpu_finalize_init+0x10f/0x160
> [    0.027138] [      T0]  start_kernel+0x686/0x710
> [    0.027140] [      T0]  x86_64_start_reservations+0x24/0x30
> [    0.027141] [      T0]  x86_64_start_kernel+0xd4/0xe0
> [    0.027142] [      T0]  common_startup_64+0x13e/0x141
> [    0.027143] [      T0]  </TASK>
> [    0.027144] [      T0] ---[ end trace 0000000000000000 ]---

Does this patch fix it for you?

diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index e87da25d1236..62936a3bde19 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -2448,19 +2448,31 @@ void __init alternative_instructions(void)
 					    __smp_locks, __smp_locks_end,
 					    _text, _etext);
 	}
+#endif
 
+	restart_nmi();
+	alternatives_patched = 1;
+
+	alt_reloc_selftest();
+}
+
+#ifdef CONFIG_SMP
+/*
+ * With CONFIG_DEFERRED_STRUCT_PAGE_INIT enabled we can free_init_pages() only
+ * after the deferred initialization of the memory map is complete.
+ */
+static int __init free_smp_locks(void)
+{
 	if (!uniproc_patched || num_possible_cpus() == 1) {
 		free_init_pages("SMP alternatives",
 				(unsigned long)__smp_locks,
 				(unsigned long)__smp_locks_end);
 	}
-#endif
 
-	restart_nmi();
-	alternatives_patched = 1;
-
-	alt_reloc_selftest();
+	return 0;
 }
+arch_initcall(free_smp_locks);
+#endif
 
 /**
  * text_poke_early - Update instructions on a live kernel at boot time
 
> Bert Karwatzki

-- 
Sincerely yours,
Mike.

^ permalink raw reply related

* Re: [PATCH v4 2/2] tracing: Drain deferred trigger frees if kthread creation fails
From: Steven Rostedt @ 2026-03-27 19:06 UTC (permalink / raw)
  To: Wesley Atwell
  Cc: linux-trace-kernel, linux-kernel, mhiramat, mark.rutland,
	mathieu.desnoyers, tom.zanussi
In-Reply-To: <20260324221326.1395799-3-atwellwea@gmail.com>

On Tue, 24 Mar 2026 16:13:26 -0600
Wesley Atwell <atwellwea@gmail.com> wrote:

> Boot-time trigger registration can fail before the trigger-data cleanup
> kthread exists. Deferring those frees until late init is fine, but the
> post-boot fallback must still drain the deferred list if kthread
> creation never succeeds.
> 
> Otherwise, boot-deferred nodes can accumulate on
> trigger_data_free_list, later frees fall back to synchronously freeing
> only the current object, and the older queued entries are leaked
> forever.
> 
> Keep the deferred boot-time behavior, but when kthread creation fails,
> drain the whole queued list synchronously. Do the same in the late-init
> drain path so queued entries are not stranded there either.
> 
> Fixes: 61d445af0a7c ("tracing: Add bulk garbage collection of freeing event_trigger_data")
> Signed-off-by: Wesley Atwell <atwellwea@gmail.com>
> ---

Do you have a test case (kernel command line) that will make
trigger_data_free() get called at boot up?

-- Steve

^ permalink raw reply

* Re: Warning from free_reserved_area() in next-20260325+
From: Bert Karwatzki @ 2026-03-27 19:54 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: linux-kernel, spasswolf, Liam.Howlett, akpm, andreas, ardb, bp,
	brauner, catalin.marinas, chleroy, dave.hansen, davem, david,
	devicetree, dvyukov, elver, glider, hannes, hpa, ilias.apalodimas,
	iommu, jack, jackmanb, kasan-dev, linux-arm-kernel, linux-efi,
	linux-fsdevel, linux-mm, linux-trace-kernel, linuxppc-dev,
	lorenzo.stoakes, m.szyprowski, maddy, mhiramat, mhocko, mingo,
	mpe, npiggin, robh, robin.murphy, saravanak, sparclinux, surenb,
	tglx, vbabka, viro, will, x86, ziy
In-Reply-To: <aca6blFFWskxAcAr@kernel.org>

Am Freitag, dem 27.03.2026 um 20:12 +0300 schrieb Mike Rapoport:
> Hi Bert,
> 
> On Fri, Mar 27, 2026 at 03:01:08PM +0100, Bert Karwatzki wrote:
> > Starting with linux next-20260325 I see the following warning early in the
> > boot process of a machine running debian stable (trixie) (except for the kernel):
> 
> Thanks for the report!
> 
> > [    0.027118] [      T0] ------------[ cut here ]------------
> > [    0.027118] [      T0] Cannot free reserved memory because of deferred initialization of the memory map
> > [    0.027119] [      T0] WARNING: mm/memblock.c:904 at __free_reserved_area+0xa9/0xc0, CPU#0: swapper/0/0
> > [    0.027122] [      T0] Modules linked in:
> > [    0.027123] [      T0] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.0.0-rc5-next-20260326-master #385 PREEMPT_RT 
> > [    0.027125] [      T0] Hardware name: ASUS System Product Name/ROG STRIX B850-F GAMING WIFI, BIOS 1627 02/05/2026
> > [    0.027125] [      T0] RIP: 0010:__free_reserved_area+0xa9/0xc0
> > [    0.027126] [      T0] Code: 48 89 df 48 89 ee e8 06 fe ff ff 48 89 c3 48 39 e8 72 a0 5b 4c 89 e8 5d 41 5c 41 5d 41 5e c3 cc cc cc cc 48 8d 3d 97 c2 c6 00 <67> 48 0f b9 3a 45 31 ed eb df 66 66 2e 0f 1f 84 00 00 00 00 00 66
> > [    0.027127] [      T0] RSP: 0000:ffffffff9b203e98 EFLAGS: 00010202
> > [    0.027128] [      T0] RAX: 0000000e91c00001 RBX: ffffffff9b100c0f RCX: 0000000080000001
> > [    0.027128] [      T0] RDX: 00000000000000cc RSI: 0000000e2d42d000 RDI: ffffffff9b32ef60
> > [    0.027128] [      T0] RBP: ffff9eeafdd6fbc0 R08: 0000000000000000 R09: 0000000000000001
> > [    0.027129] [      T0] R10: 0000000000001000 R11: 8000000000000163 R12: 000000000000006f
> > [    0.027129] [      T0] R13: 0000000000000000 R14: 0000000000000045 R15: 000000005c8a1000
> > [    0.027129] [      T0] FS:  0000000000000000(0000) GS:ffff9eeb21c05000(0000) knlGS:0000000000000000
> > [    0.027130] [      T0] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > [    0.027130] [      T0] CR2: ffff9ee8ad801000 CR3: 0000000e2ce1e000 CR4: 0000000000f50ef0
> > [    0.027131] [      T0] PKRU: 55555554
> > [    0.027131] [      T0] Call Trace:
> > [    0.027132] [      T0]  <TASK>
> > [    0.027132] [      T0]  free_reserved_area+0x89/0xd0
> > [    0.027133] [      T0]  alternative_instructions+0xee/0x110
> > [    0.027136] [      T0]  arch_cpu_finalize_init+0x10f/0x160
> > [    0.027138] [      T0]  start_kernel+0x686/0x710
> > [    0.027140] [      T0]  x86_64_start_reservations+0x24/0x30
> > [    0.027141] [      T0]  x86_64_start_kernel+0xd4/0xe0
> > [    0.027142] [      T0]  common_startup_64+0x13e/0x141
> > [    0.027143] [      T0]  </TASK>
> > [    0.027144] [      T0] ---[ end trace 0000000000000000 ]---
> 
> Does this patch fix it for you?
> 
> diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
> index e87da25d1236..62936a3bde19 100644
> --- a/arch/x86/kernel/alternative.c
> +++ b/arch/x86/kernel/alternative.c
> @@ -2448,19 +2448,31 @@ void __init alternative_instructions(void)
>  					    __smp_locks, __smp_locks_end,
>  					    _text, _etext);
>  	}
> +#endif
>  
> +	restart_nmi();
> +	alternatives_patched = 1;
> +
> +	alt_reloc_selftest();
> +}
> +
> +#ifdef CONFIG_SMP
> +/*
> + * With CONFIG_DEFERRED_STRUCT_PAGE_INIT enabled we can free_init_pages() only
> + * after the deferred initialization of the memory map is complete.
> + */
> +static int __init free_smp_locks(void)
> +{
>  	if (!uniproc_patched || num_possible_cpus() == 1) {
>  		free_init_pages("SMP alternatives",
>  				(unsigned long)__smp_locks,
>  				(unsigned long)__smp_locks_end);
>  	}
> -#endif
>  
> -	restart_nmi();
> -	alternatives_patched = 1;
> -
> -	alt_reloc_selftest();
> +	return 0;
>  }
> +arch_initcall(free_smp_locks);
> +#endif
>  
>  /**
>   * text_poke_early - Update instructions on a live kernel at boot time
>  
> > Bert Karwatzki

Yes, your patch fixes the issue in next-20260326.

Tested-By: Bert Karwatzki <spasswolf@web.de>

Bert Karwatzki

^ permalink raw reply

* Re: [PATCH v13 4/4] ring-buffer: Add persistent ring buffer selftest
From: Steven Rostedt @ 2026-03-27 20:25 UTC (permalink / raw)
  To: Masami Hiramatsu (Google)
  Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel, Ian Rogers
In-Reply-To: <177440552560.1529621.1405976992959650354.stgit@mhiramat.tok.corp.google.com>

On Wed, 25 Mar 2026 11:25:25 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:

> From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> 
> Add a self-destractive test for the persistent ring buffer. This
> will invalidate some sub-buffer pages in the persistent ring buffer
> when kernel gets panic, and check whether the number of detected
> invalid pages and the total entry_bytes are the same as record
> after reboot.
> 
> This can ensure the kernel correctly recover partially corrupted
> persistent ring buffer when boot.
> 
> The test only runs on the persistent ring buffer whose name is
> "ptracingtest". And user has to fill it up with events before
> kernel panics.
> 
> To run the test, enable CONFIG_RING_BUFFER_PERSISTENT_SELFTEST

I think a more appropriate config name would be:

  CONFIG_PERSISTENT_RING_BUFFER_ERROR_INJECT

as that's what it is doing as it is only testing error injection and not
the persistent ring buffer.

> and you have to setup the kernel cmdline;
> 
>  reserve_mem=20M:2M:trace trace_instance=ptracingtest^traceoff@trace
>  panic=1
> 
> And run following commands after the 1st boot;
> 
>  cd /sys/kernel/tracing/instances/ptracingtest
>  echo 1 > tracing_on
>  echo 1 > events/enable
>  sleep 3
>  echo c > /proc/sysrq-trigger

These instructions should probably be in the CONFIG help message.

> 
> After panic message, the kernel will reboot and run the verification
> on the persistent ring buffer, e.g.
> 
>  Ring buffer meta [2] invalid buffer page detected
>  Ring buffer meta [2] is from previous boot! (318 pages discarded)
>  Ring buffer testing [2] invalid pages: PASSED (318/318)
>  Ring buffer testing [2] entry_bytes: PASSED (1300476/1300476)

BTW, when I tested this, I got the above on the first boot, but if I
rebooted normally without re-enabling the persistent ring buffer, I would
get on the next boot:


[    0.966510] Ring buffer meta [2] is from previous boot! (0 pages discarded)
[    0.971338]  #2
[    1.003431] Ring buffer meta [3] is from previous boot! (0 pages discarded)
[    1.007737]  #3
[    1.039091] Ring buffer meta [4] is from previous boot! (0 pages discarded)
[    1.043181] Ring buffer testing [4] invalid pages: FAILED (0/1597)
[    1.044660] Ring buffer testing [4] entry_bytes: PASSED (6512464/6512464)
[    1.047829]  #4
[    1.079811] Ring buffer meta [5] is from previous boot! (0 pages discarded)
[    1.083728]  #5
[    1.116764] Ring buffer meta [6] is from previous boot! (0 pages discarded)
[    1.120846]  #6
[    1.156502] Ring buffer meta [7] is from previous boot! (0 pages discarded)
[    1.160857]  #7

I'll start testing the previous 3 patches and may add them to next.

Also, I noticed that there's nothing that reads the RB_MISSING as I thought
it might. I'll have to look into how to pass that info to the trace output.

-- Steve

^ permalink raw reply

* Re: [PATCH v13 4/4] ring-buffer: Add persistent ring buffer selftest
From: Steven Rostedt @ 2026-03-27 20:47 UTC (permalink / raw)
  To: Masami Hiramatsu (Google)
  Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel, Ian Rogers
In-Reply-To: <20260327162508.6cac690c@gandalf.local.home>

On Fri, 27 Mar 2026 16:25:08 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:

> Also, I noticed that there's nothing that reads the RB_MISSING as I thought
> it might. I'll have to look into how to pass that info to the trace output.

And when I cat /sys/kernel/tracing/instances/ptracingtest/per_cpu/cpuX/trace_pipe

   (where X is the failed buffer)

It triggered an infinite loop of:

[  206.549217] ------------[ cut here ]------------
[  206.550907] WARNING: kernel/trace/ring_buffer.c:5751 at __rb_get_reader_page+0xa6b/0x1040, CPU#2: cat/1197
[  206.554111] Modules linked in:
[  206.555331] CPU: 2 UID: 0 PID: 1197 Comm: cat Tainted: G        W           7.0.0-rc4-test-00028-g7b37f48b2c57-dirty #276 PREEMPT(full) 
[  206.559048] Tainted: [W]=WARN
[  206.560244] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
[  206.563212] RIP: 0010:__rb_get_reader_page+0xa6b/0x1040
[  206.564964] Code: ff df 48 c1 ea 03 80 3c 02 00 0f 85 4a 05 00 00 48 8b 43 10 be 04 00 00 00 4c 8d 60 08 4c 89 e7 e8 9a 2d 63 00 f0 41 ff 04 24 <0f> 0b e9 36 fb ff ff e8 29 39 05 00 fb 0f 1f 44 00 00 4d 85 f6 0f
[  206.572295] RSP: 0018:ffff888112a77938 EFLAGS: 00010006
[  206.574095] RAX: 0000000000000001 RBX: ffff888100d6e000 RCX: 0000000000000001
[  206.576458] RDX: 0000000000000001 RSI: 0000000000000004 RDI: ffff88810027b808
[  206.578749] RBP: 1ffff1102254ef34 R08: ffffffff909a1556 R09: ffffed102004f701
[  206.581020] R10: ffffed102004f702 R11: ffff88823443a000 R12: ffff88810027b808
[  206.583312] R13: ffff888100f65f00 R14: ffff888100f65f00 R15: dffffc0000000000
[  206.585647] FS:  00007f98e4d80780(0000) GS:ffff88829e3c2000(0000) knlGS:0000000000000000
[  206.588246] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  206.590179] CR2: 00007f98e4d3e000 CR3: 000000012272e006 CR4: 0000000000172ef0
[  206.592444] Call Trace:
[  206.593518]  <TASK>
[  206.594436]  ? __pfx___rb_get_reader_page+0x10/0x10
[  206.596148]  ? lock_acquire+0x1b2/0x340
[  206.597599]  rb_buffer_peek+0x37e/0x520
[  206.598954]  ring_buffer_peek+0xe9/0x310
[  206.601956]  peek_next_entry+0x15a/0x280
[  206.603420]  __find_next_entry+0x39f/0x530
[  206.604918]  ? __pfx___mutex_lock+0x10/0x10
[  206.606474]  ? rcu_is_watching+0x15/0xb0
[  206.616049]  ? __pfx___find_next_entry+0x10/0x10
[  206.617741]  ? preempt_count_sub+0x10c/0x1c0
[  206.619242]  ? __pfx_down_read+0x10/0x10
[  206.620687]  trace_find_next_entry_inc+0x2f/0x240
[  206.622351]  tracing_read_pipe+0x4e7/0xc60
[  206.623852]  ? rw_verify_area+0x353/0x5f0
[  206.625325]  vfs_read+0x171/0xb20
[  206.626592]  ? __lock_acquire+0x487/0x2220
[  206.628135]  ? __pfx___handle_mm_fault+0x10/0x10
[  206.629784]  ? __pfx_vfs_read+0x10/0x10
[  206.632696]  ? __pfx_css_rstat_updated+0x10/0x10
[  206.634351]  ? rcu_is_watching+0x15/0xb0
[  206.635835]  ? trace_preempt_on+0x126/0x160
[  206.637362]  ? preempt_count_sub+0x10c/0x1c0
[  206.638880]  ? count_memcg_events+0x10a/0x4b0
[  206.640455]  ? find_held_lock+0x2b/0x80
[  206.641908]  ? rcu_read_unlock+0x17/0x60
[  206.643340]  ? lock_release+0x1ab/0x320
[  206.644812]  ksys_read+0xff/0x200
[  206.646127]  ? __pfx_ksys_read+0x10/0x10
[  206.647651]  do_syscall_64+0x117/0x16c0
[  206.649035]  ? irqentry_exit+0xd9/0x690
[  206.650548]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[  206.652331] RIP: 0033:0x7f98e4e14eb2
[  206.653743] Code: 18 41 8b 93 08 03 00 00 59 5e 48 83 f8 fc 75 1a 83 e2 39 83 fa 08 75 12 e8 2b ff ff ff 0f 1f 00 49 89 ca 48 8b 44 24 20 0f 05 <48> 83 c4 18 c3 66 0f 1f 84 00 00 00 00 00 48 83 ec 10 ff 74 24 18
[  206.659364] RSP: 002b:00007ffdc0a8d930 EFLAGS: 00000202 ORIG_RAX: 0000000000000000
[  206.663251] RAX: ffffffffffffffda RBX: 0000000000040000 RCX: 00007f98e4e14eb2
[  206.665614] RDX: 0000000000040000 RSI: 00007f98e4d3f000 RDI: 0000000000000003
[  206.668022] RBP: 0000000000040000 R08: 0000000000000000 R09: 0000000000000000
[  206.670306] R10: 0000000000000000 R11: 0000000000000202 R12: 00007f98e4d3f000
[  206.672624] R13: 0000000000000003 R14: 0000000000000000 R15: 0000000000040000
[  206.674941]  </TASK>
[  206.675927] irq event stamp: 7898
[  206.677154] hardirqs last  enabled at (7897): [<ffffffff90991f6f>] ring_buffer_empty_cpu+0x19f/0x2f0
[  206.680088] hardirqs last disabled at (7898): [<ffffffff909a277d>] ring_buffer_peek+0x17d/0x310
[  206.682881] softirqs last  enabled at (7888): [<ffffffff9056cffc>] handle_softirqs+0x5bc/0x7c0
[  206.685710] softirqs last disabled at (7879): [<ffffffff9056d322>] __irq_exit_rcu+0x112/0x230
[  206.688483] ---[ end trace 0000000000000000 ]---

OK, that RB_MISSED_EVENTS is causing an issue. Something else we need to
look into. The warning is that __rb_get_reader_page() is trying more than 3
times. Thus I think it's constantly swapping the head page and the reader
page. Something to investigate.

So, I'm holding off pulling in these patches. I may take the first one
though.

-- Steve

^ permalink raw reply

* Re: [PATCH v4 2/2] tracing: Drain deferred trigger frees if kthread creation fails
From: Wesley Atwell @ 2026-03-27 22:41 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-trace-kernel, linux-kernel, mhiramat, mark.rutland,
	mathieu.desnoyers, tom.zanussi
In-Reply-To: <20260327150634.5df3cf4f@gandalf.local.home>

Yes,

This kernel command line reliably reaches trigger_data_free() during boot:

trace_event=sched:sched_switch
trace_trigger=sched_switch.traceon,sched_switch.traceon

On an unpatched tree, that crashes during early boot before userspace.
The call trace goes through:

trigger_data_free()
__kthread_create_on_node()
try_to_wake_up()

The stack also shows the boot-time trigger registration path:

event_trigger_parse()
trigger_process_regex()
__trace_early_add_events()

With v4 applied, the same command line boots successfully. The guest log shows:

Failed to register trigger 'traceon' on event sched_switch

And /sys/kernel/tracing/events/sched/sched_switch/trigger contains:

traceon:unlimited

I also verified patch 1 with repeated trace_trigger= parameters:
before the patch, only the last parameter was preserved; after the
patch, both triggers were installed.

Thanks,
Wesley Atwell

^ permalink raw reply

* Re: [PATCH v4 2/2] tracing: Drain deferred trigger frees if kthread creation fails
From: Steven Rostedt @ 2026-03-28  2:30 UTC (permalink / raw)
  To: Wesley Atwell
  Cc: linux-trace-kernel, linux-kernel, mhiramat, mark.rutland,
	mathieu.desnoyers, tom.zanussi
In-Reply-To: <CAN=sVvzFMC1m2aGT23aRpPpoddBVP59mQBmEsQyEPKBYm3J_Vw@mail.gmail.com>

On Fri, 27 Mar 2026 16:41:52 -0600
Wesley Atwell <atwellwea@gmail.com> wrote:

> Yes,
> 
> This kernel command line reliably reaches trigger_data_free() during boot:
> 
> trace_event=sched:sched_switch
> trace_trigger=sched_switch.traceon,sched_switch.traceon
> 
> On an unpatched tree, that crashes during early boot before userspace.
> The call trace goes through:
> 
> trigger_data_free()
> __kthread_create_on_node()
> try_to_wake_up()
> 
> The stack also shows the boot-time trigger registration path:
> 
> event_trigger_parse()
> trigger_process_regex()
> __trace_early_add_events()

Thanks for this. I can reproduce the crash. I'm also going to add this
to the change log as it is useful (I'll even add it to one of my
regression tests). I'll take this patch separately (this didn't need to
be a patch series, as the two patches do not depend on each other).

-- Steve

^ permalink raw reply

* Re: [PATCH v4 2/2] tracing: Drain deferred trigger frees if kthread creation fails
From: Wesley Atwell @ 2026-03-28  4:56 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-trace-kernel, linux-kernel, mhiramat, mark.rutland,
	mathieu.desnoyers, tom.zanussi
In-Reply-To: <20260327223022.167defcc@robin>

Hi Steve,

I'm glad the test case was helpful. I'll include similar testing
details in future commit messages and avoid grouping unrelated
patches.

Thanks,
Wesley Atwell

^ permalink raw reply

* [PATCH] tracing: Remove tracing_alloc_snapshot() when snapshot isn't defined
From: Steven Rostedt @ 2026-03-28 14:19 UTC (permalink / raw)
  To: LKML, Linux trace kernel; +Cc: Masami Hiramatsu, Mathieu Desnoyers, Mark Brown

From: Steven Rostedt <rostedt@goodmis.org>

The function tracing_alloc_snapshot() is only used between trace.c and
trace_snapshot.c. When snapshot isn't configured, it's not used at all.
The stub function was defined as a global with no users and no prototype
causing build issues.

Remove the function when snapshot isn't configured as nothing is calling
it.

Also remove the EXPORT_SYMBOL_GPL() that was associated with it as it's
not used outside of the tracing subsystem which also includes any modules.

Reported-by: Mark Brown <broonie@kernel.org>
Closes: https://lore.kernel.org/all/acb-IuZ4vDkwwQLW@sirena.co.uk/
Fixes: bade44fe546212 (tracing: Move snapshot code out of trace.c and into trace_snapshot.c)
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 kernel/trace/trace.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index ec2b926436a7..7f2fbf9c36df 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -810,19 +810,12 @@ int tracing_alloc_snapshot(void)
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(tracing_alloc_snapshot);
 #else
 void tracing_snapshot(void)
 {
 	WARN_ONCE(1, "Snapshot feature not enabled, but internal snapshot used");
 }
 EXPORT_SYMBOL_GPL(tracing_snapshot);
-int tracing_alloc_snapshot(void)
-{
-	WARN_ONCE(1, "Snapshot feature not enabled, but snapshot allocation used");
-	return -ENODEV;
-}
-EXPORT_SYMBOL_GPL(tracing_alloc_snapshot);
 void tracing_snapshot_alloc(void)
 {
 	/* Give warning */
-- 
2.51.0


^ permalink raw reply related

* Re: [PATCH v4 1/2] tracing: Preserve repeated boot-time tracing parameters
From: Steven Rostedt @ 2026-03-28 17:53 UTC (permalink / raw)
  To: Wesley Atwell
  Cc: linux-trace-kernel, linux-kernel, mhiramat, mark.rutland,
	mathieu.desnoyers, tom.zanussi
In-Reply-To: <20260324221326.1395799-2-atwellwea@gmail.com>

On Tue, 24 Mar 2026 16:13:25 -0600
Wesley Atwell <atwellwea@gmail.com> wrote:

> +++ b/kernel/trace/trace.c
> @@ -228,6 +228,34 @@ static int boot_instance_index;
>  static char boot_snapshot_info[COMMAND_LINE_SIZE] __initdata;
>  static int boot_snapshot_index;
>  
> +/*
> + * Repeated boot parameters, including Bootconfig array expansions, need
> + * to stay in the delimiter form that the existing parser consumes.
> + */
> +void __init trace_append_boot_param(char *buf, const char *str, char sep,
> +				    size_t size)
> +{
> +	size_t len, str_len;

Why use the "size_t" type? Just use int. Then you don't need to play games
about unsigned types in the if statements below. The boot cmdline will
never come close to being 2GB in size.

> +
> +	if (!buf[0]) {

Should we check for size here? Perhaps just remove this part (see below)

> +		strscpy(buf, str, size);
> +		return;
> +	}
> +
> +	str_len = strlen(str);
> +	if (!str_len)
> +		return;
> +
> +	len = strlen(buf);


> +	if (len >= size - 1)
> +		return;
> +	if (str_len >= size - len - 1)
> +		return;

Instead of the above, have:

	/* Plus 2 for ",\0" */
	if (str_len + len + 2 > size)
		return;

> +
> +	buf[len] = sep;

If we remove the first check, here we can have:

	if (len)
		buf[len++] = sep;

By adding one to length, it makes the strscpy() a bit more readable.

	strscpy(buf + len, str, size - len);

> +	strscpy(buf + len + 1, str, size - len - 1);

> +}
> +

-- Steve

^ permalink raw reply

* [PATCH v5] tracing: Preserve repeated boot-time tracing parameters
From: Wesley Atwell @ 2026-03-28 20:18 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mark Rutland, Mathieu Desnoyers, linux-kernel, linux-trace-kernel,
	Wesley Atwell
In-Reply-To: <20260324221326.1395799-2-atwellwea@gmail.com>

Some tracing boot parameters already accept delimited value lists, but
their __setup() handlers keep only the last instance seen at boot.
Make repeated instances append to the same boot-time buffer in the
format each parser already consumes.

Use a shared trace_append_boot_param() helper for the ftrace filters,
trace_options, and kprobe_event boot parameters. trace_trigger=
tokenizes its backing storage in place, so keep a running offset and
only parse the newly appended chunk into bootup_triggers[].

This also lets Bootconfig array values work naturally when they expand
to repeated param=value entries.

Validated by booting with repeated ftrace_filter=, ftrace_notrace=,
ftrace_graph_filter=, ftrace_graph_notrace=, trace_options=,
kprobe_event=, and trace_trigger= parameters and confirming that the
resulting tracefs state preserved every requested entry. Before this
change, only the last instance from each repeated parameter survived
boot.

Signed-off-by: Wesley Atwell <atwellwea@gmail.com>
---
v5:
- use int sizes in the shared append helper and trace_trigger bookkeeping
- keep a single bounded append path that only inserts the separator after
  the first entry
- only advance the trace_trigger buffer offset after a successful append

 kernel/trace/ftrace.c       | 12 ++++++++----
 kernel/trace/trace.c        | 29 ++++++++++++++++++++++++++++-
 kernel/trace/trace.h        |  2 ++
 kernel/trace/trace_events.c | 23 ++++++++++++++++++++---
 kernel/trace/trace_kprobe.c |  3 ++-
 5 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 413310912609..8bd3dd1d549c 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -6841,7 +6841,8 @@ bool ftrace_filter_param __initdata;
 static int __init set_ftrace_notrace(char *str)
 {
 	ftrace_filter_param = true;
-	strscpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);
+	trace_append_boot_param(ftrace_notrace_buf, str, ',',
+				FTRACE_FILTER_SIZE);
 	return 1;
 }
 __setup("ftrace_notrace=", set_ftrace_notrace);
@@ -6849,7 +6850,8 @@ __setup("ftrace_notrace=", set_ftrace_notrace);
 static int __init set_ftrace_filter(char *str)
 {
 	ftrace_filter_param = true;
-	strscpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);
+	trace_append_boot_param(ftrace_filter_buf, str, ',',
+				FTRACE_FILTER_SIZE);
 	return 1;
 }
 __setup("ftrace_filter=", set_ftrace_filter);
@@ -6861,14 +6863,16 @@ static int ftrace_graph_set_hash(struct ftrace_hash *hash, char *buffer);
 
 static int __init set_graph_function(char *str)
 {
-	strscpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
+	trace_append_boot_param(ftrace_graph_buf, str, ',',
+				FTRACE_FILTER_SIZE);
 	return 1;
 }
 __setup("ftrace_graph_filter=", set_graph_function);
 
 static int __init set_graph_notrace_function(char *str)
 {
-	strscpy(ftrace_graph_notrace_buf, str, FTRACE_FILTER_SIZE);
+	trace_append_boot_param(ftrace_graph_notrace_buf, str, ',',
+				FTRACE_FILTER_SIZE);
 	return 1;
 }
 __setup("ftrace_graph_notrace=", set_graph_notrace_function);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index a626211ceb9a..c8cf45dc4152 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -228,6 +228,32 @@ static int boot_instance_index;
 static char boot_snapshot_info[COMMAND_LINE_SIZE] __initdata;
 static int boot_snapshot_index;
 
+/*
+ * Repeated boot parameters, including Bootconfig array expansions, need
+ * to stay in the delimiter form that the existing parser consumes.
+ */
+void __init trace_append_boot_param(char *buf, const char *str, char sep,
+				    int size)
+{
+	int len, needed, str_len;
+
+	if (!*str)
+		return;
+
+	len = strlen(buf);
+	str_len = strlen(str);
+	needed = len + str_len + 1;
+	if (len)
+		needed++;
+	if (needed > size)
+		return;
+
+	if (len)
+		buf[len++] = sep;
+
+	strscpy(buf + len, str, size - len);
+}
+
 static int __init set_cmdline_ftrace(char *str)
 {
 	strscpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
@@ -329,7 +355,8 @@ static char trace_boot_options_buf[MAX_TRACER_SIZE] __initdata;
 
 static int __init set_trace_boot_options(char *str)
 {
-	strscpy(trace_boot_options_buf, str, MAX_TRACER_SIZE);
+	trace_append_boot_param(trace_boot_options_buf, str, ',',
+				MAX_TRACER_SIZE);
 	return 1;
 }
 __setup("trace_options=", set_trace_boot_options);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index b8f3804586a0..237a0417de1c 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -863,6 +863,8 @@ extern int DYN_FTRACE_TEST_NAME(void);
 extern int DYN_FTRACE_TEST_NAME2(void);
 
 extern void trace_set_ring_buffer_expanded(struct trace_array *tr);
+void __init trace_append_boot_param(char *buf, const char *str,
+				    char sep, int size);
 extern bool tracing_selftest_disabled;
 
 #ifdef CONFIG_FTRACE_STARTUP_TEST
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 249d1cba72c0..7f0bec4622f6 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -3679,20 +3679,37 @@ static struct boot_triggers {
 } bootup_triggers[MAX_BOOT_TRIGGERS];
 
 static char bootup_trigger_buf[COMMAND_LINE_SIZE];
+static int bootup_trigger_buf_len;
 static int nr_boot_triggers;
 
 static __init int setup_trace_triggers(char *str)
 {
+	char *slot;
 	char *trigger;
 	char *buf;
 	int i;
 
-	strscpy(bootup_trigger_buf, str, COMMAND_LINE_SIZE);
+	if (bootup_trigger_buf_len >= COMMAND_LINE_SIZE)
+		return 1;
+
+	slot = bootup_trigger_buf + bootup_trigger_buf_len;
+
+	/*
+	 * trace_trigger= parsing tokenizes the backing storage in place.
+	 * Copy each repeated parameter into fresh space and only parse that
+	 * newly copied chunk here.
+	 */
+	trace_append_boot_param(slot, str, '\0',
+				COMMAND_LINE_SIZE - bootup_trigger_buf_len);
+	if (!*slot)
+		return 1;
+
+	bootup_trigger_buf_len += strlen(slot) + 1;
 	trace_set_ring_buffer_expanded(NULL);
 	disable_tracing_selftest("running event triggers");
 
-	buf = bootup_trigger_buf;
-	for (i = 0; i < MAX_BOOT_TRIGGERS; i++) {
+	buf = slot;
+	for (i = nr_boot_triggers; i < MAX_BOOT_TRIGGERS; i++) {
 		trigger = strsep(&buf, ",");
 		if (!trigger)
 			break;
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index a5dbb72528e0..e9f1c55aea64 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -31,7 +31,8 @@ static char kprobe_boot_events_buf[COMMAND_LINE_SIZE] __initdata;
 
 static int __init set_kprobe_boot_events(char *str)
 {
-	strscpy(kprobe_boot_events_buf, str, COMMAND_LINE_SIZE);
+	trace_append_boot_param(kprobe_boot_events_buf, str, ';',
+				COMMAND_LINE_SIZE);
 	disable_tracing_selftest("running kprobe events");
 
 	return 1;
-- 
2.43.0

^ permalink raw reply related

* [PATCH 1/2] tracing/hist: bound full field-name construction
From: Pengpeng Hou @ 2026-03-29  3:09 UTC (permalink / raw)
  To: rostedt, mhiramat, mathieu.desnoyers, tom.zanussi
  Cc: linux-kernel, linux-trace-kernel, pengpeng

hist_field_name() builds a fully qualified synthetic field name in a
fixed MAX_FILTER_STR_VAL buffer using repeated strcat() calls. Long
system, event, and field names can therefore overflow the static staging
buffer.

Build the qualified name with snprintf() and fall back to the plain
field name if it does not fit.

Fixes: 067fe038e70f ("tracing: Add variable reference handling to hist triggers")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
 kernel/trace/trace_events_hist.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 73ea180cad55..4a27da628a71 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -1362,12 +1362,12 @@ static const char *hist_field_name(struct hist_field *field,
 		if (field->system) {
 			static char full_name[MAX_FILTER_STR_VAL];
 
-			strcat(full_name, field->system);
-			strcat(full_name, ".");
-			strcat(full_name, field->event_name);
-			strcat(full_name, ".");
-			strcat(full_name, field->name);
-			field_name = full_name;
+			if (snprintf(full_name, sizeof(full_name), "%s.%s.%s",
+				     field->system, field->event_name,
+				     field->name) < sizeof(full_name))
+				field_name = full_name;
+			else
+				field_name = field->name;
 		} else
 			field_name = field->name;
 	} else if (field->flags & HIST_FIELD_FL_TIMESTAMP)
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply related

* [PATCH 2/2] tracing/hist: allocate synthetic-field command buffers to fit
From: Pengpeng Hou @ 2026-03-29  3:09 UTC (permalink / raw)
  To: rostedt, mhiramat, mathieu.desnoyers, tom.zanussi
  Cc: linux-kernel, linux-trace-kernel, pengpeng

The synthetic field helpers currently build temporary names and trigger
commands in fixed MAX_FILTER_STR_VAL buffers with strcpy() and strcat().
Long field names, key lists, or saved filters can therefore overrun
those staging buffers while constructing the synthetic histogram
command.

Allocate the synthetic name and command buffers to the exact size
required by the current histogram instead of relying on fixed-size
scratch storage.

Fixes: 02205a6752f2 ("tracing: Add support for 'field variables'")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
 kernel/trace/trace_events_hist.c | 46 +++++++++++++++++++-------------
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 4a27da628a71..1883bd6d9b95 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -2964,13 +2964,10 @@ find_synthetic_field_var(struct hist_trigger_data *target_hist_data,
 	struct hist_field *event_var;
 	char *synthetic_name;
 
-	synthetic_name = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
+	synthetic_name = kasprintf(GFP_KERNEL, "synthetic_%s", field_name);
 	if (!synthetic_name)
 		return ERR_PTR(-ENOMEM);
 
-	strcpy(synthetic_name, "synthetic_");
-	strcat(synthetic_name, field_name);
-
 	event_var = find_event_var(target_hist_data, system, event_name, synthetic_name);
 
 	kfree(synthetic_name);
@@ -3016,6 +3013,8 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
 	struct hist_field *event_var;
 	char *saved_filter;
 	char *cmd;
+	size_t cmdlen;
+	size_t off;
 	int ret;
 
 	if (target_hist_data->n_field_var_hists >= SYNTH_FIELDS_MAX) {
@@ -3053,35 +3052,46 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
 	if (!var_hist)
 		return ERR_PTR(-ENOMEM);
 
-	cmd = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
+	saved_filter = find_trigger_filter(hist_data, file);
+
+	cmdlen = strlen("keys=") + strlen(":synthetic_") +
+		 strlen(field_name) + strlen("=") + strlen(field_name) + 1;
+	first = true;
+	for_each_hist_key_field(i, hist_data) {
+		key_field = hist_data->fields[i];
+		if (!first)
+			cmdlen++;
+		cmdlen += strlen(key_field->field->name);
+		first = false;
+	}
+
+	if (saved_filter)
+		cmdlen += strlen(" if ") + strlen(saved_filter);
+
+	cmd = kzalloc(cmdlen, GFP_KERNEL);
 	if (!cmd) {
 		kfree(var_hist);
 		return ERR_PTR(-ENOMEM);
 	}
 
 	/* Use the same keys as the compatible histogram */
-	strcat(cmd, "keys=");
+	off = scnprintf(cmd, cmdlen, "keys=");
+	first = true;
 
 	for_each_hist_key_field(i, hist_data) {
 		key_field = hist_data->fields[i];
-		if (!first)
-			strcat(cmd, ",");
-		strcat(cmd, key_field->field->name);
+		off += scnprintf(cmd + off, cmdlen - off, "%s%s",
+				 first ? "" : ",", key_field->field->name);
 		first = false;
 	}
 
 	/* Create the synthetic field variable specification */
-	strcat(cmd, ":synthetic_");
-	strcat(cmd, field_name);
-	strcat(cmd, "=");
-	strcat(cmd, field_name);
+	off += scnprintf(cmd + off, cmdlen - off, ":synthetic_%s=%s",
+			 field_name, field_name);
 
 	/* Use the same filter as the compatible histogram */
-	saved_filter = find_trigger_filter(hist_data, file);
-	if (saved_filter) {
-		strcat(cmd, " if ");
-		strcat(cmd, saved_filter);
-	}
+	if (saved_filter)
+		scnprintf(cmd + off, cmdlen - off, " if %s", saved_filter);
 
 	var_hist->cmd = kstrdup(cmd, GFP_KERNEL);
 	if (!var_hist->cmd) {
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply related

* Re: [PATCH v5] tracing: Preserve repeated boot-time tracing parameters
From: Steven Rostedt @ 2026-03-29 15:49 UTC (permalink / raw)
  To: Wesley Atwell
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, linux-kernel,
	linux-trace-kernel
In-Reply-To: <20260328201842.1782806-1-atwellwea@gmail.com>

On Sat, 28 Mar 2026 14:18:42 -0600
Wesley Atwell <atwellwea@gmail.com> wrote:

> Some tracing boot parameters already accept delimited value lists, but
> their __setup() handlers keep only the last instance seen at boot.
> Make repeated instances append to the same boot-time buffer in the
> format each parser already consumes.
> 
> Use a shared trace_append_boot_param() helper for the ftrace filters,
> trace_options, and kprobe_event boot parameters. trace_trigger=
> tokenizes its backing storage in place, so keep a running offset and
> only parse the newly appended chunk into bootup_triggers[].
> 
> This also lets Bootconfig array values work naturally when they expand
> to repeated param=value entries.
> 
> Validated by booting with repeated ftrace_filter=, ftrace_notrace=,
> ftrace_graph_filter=, ftrace_graph_notrace=, trace_options=,
> kprobe_event=, and trace_trigger= parameters and confirming that the
> resulting tracefs state preserved every requested entry. Before this
> change, only the last instance from each repeated parameter survived
> boot.
> 
> Signed-off-by: Wesley Atwell <atwellwea@gmail.com>
> ---
> v5:

FYI, it's nice to have a daisy chain connection of previous versions. I
suggest instead of just saying "v5:" use:

Changes since v4: https://lore.kernel.org/all/20260324221326.1395799-2-atwellwea@gmail.com/

> - use int sizes in the shared append helper and trace_trigger bookkeeping
> - keep a single bounded append path that only inserts the separator after
>   the first entry
> - only advance the trace_trigger buffer offset after a successful append
> 
>  kernel/trace/ftrace.c       | 12 ++++++++----
>  kernel/trace/trace.c        | 29 ++++++++++++++++++++++++++++-
>  kernel/trace/trace.h        |  2 ++
>  kernel/trace/trace_events.c | 23 ++++++++++++++++++++---
>  kernel/trace/trace_kprobe.c |  3 ++-
>  5 files changed, 60 insertions(+), 9 deletions(-)
> 

> +/*
> + * Repeated boot parameters, including Bootconfig array expansions, need
> + * to stay in the delimiter form that the existing parser consumes.
> + */
> +void __init trace_append_boot_param(char *buf, const char *str, char sep,
> +				    int size)
> +{

This is much better.

> +	int len, needed, str_len;
> +
> +	if (!*str)
> +		return;
> +
> +	len = strlen(buf);
> +	str_len = strlen(str);
> +	needed = len + str_len + 1;

Perhaps add a comment:

	/* For continuation, account for separator */
> +	if (len)
> +		needed++;
> +	if (needed > size)
> +		return;
> +
> +	if (len)
> +		buf[len++] = sep;
> +
> +	strscpy(buf + len, str, size - len);
> +}
> +
>  static int __init set_cmdline_ftrace(char *str)
>  {
>  	strscpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);


> --- a/kernel/trace/trace_events.c
> +++ b/kernel/trace/trace_events.c
> @@ -3679,20 +3679,37 @@ static struct boot_triggers {
>  } bootup_triggers[MAX_BOOT_TRIGGERS];
>  
>  static char bootup_trigger_buf[COMMAND_LINE_SIZE];
> +static int bootup_trigger_buf_len;
>  static int nr_boot_triggers;
>  
>  static __init int setup_trace_triggers(char *str)
>  {
> +	char *slot;
>  	char *trigger;
>  	char *buf;
>  	int i;
>  
> -	strscpy(bootup_trigger_buf, str, COMMAND_LINE_SIZE);
> +	if (bootup_trigger_buf_len >= COMMAND_LINE_SIZE)
> +		return 1;
> +
> +	slot = bootup_trigger_buf + bootup_trigger_buf_len;

The bootup_trigger_buf is a temporary buffer for this function only. It
works fine as is. There's no reason to modify this function.

-- Steve

> +
> +	/*
> +	 * trace_trigger= parsing tokenizes the backing storage in place.
> +	 * Copy each repeated parameter into fresh space and only parse that
> +	 * newly copied chunk here.
> +	 */
> +	trace_append_boot_param(slot, str, '\0',
> +				COMMAND_LINE_SIZE - bootup_trigger_buf_len);
> +	if (!*slot)
> +		return 1;
> +
> +	bootup_trigger_buf_len += strlen(slot) + 1;
>  	trace_set_ring_buffer_expanded(NULL);
>  	disable_tracing_selftest("running event triggers");
>  
> -	buf = bootup_trigger_buf;
> -	for (i = 0; i < MAX_BOOT_TRIGGERS; i++) {
> +	buf = slot;
> +	for (i = nr_boot_triggers; i < MAX_BOOT_TRIGGERS; i++) {
>  		trigger = strsep(&buf, ",");
>  		if (!trigger)
>  			break;

^ permalink raw reply

* Re: [GIT PULL] RTLA changes for v7.1
From: Steven Rostedt @ 2026-03-29 16:22 UTC (permalink / raw)
  To: Tomas Glozar
  Cc: Costa Shulyupin, Wander Lairson Costa, LKML, linux-trace-kernel
In-Reply-To: <20260327150237.405973-1-tglozar@redhat.com>

On Fri, 27 Mar 2026 16:02:37 +0100
Tomas Glozar <tglozar@redhat.com> wrote:

> Steven,
> 
> please pull the following changes for RTLA (more info in tag description).

I can pull this but I just noticed that starting with 7.0-rc1, it fails
to build without libbpf:

Auto-detecting system features:
...                           libtraceevent: [ on  ]
...                              libtracefs: [ on  ]
...                             libcpupower: [ OFF ]
...                                  libbpf: [ OFF ]
...                         clang-bpf-co-re: [ on  ]
...                       bpftool-skeletons: [ OFF ]

libcpupower is missing, building without --deepest-idle-state support.
Please install libcpupower-dev/kernel-tools-libs-devel
libbpf is missing, building without BPF skeleton support.
Please install libbpf-dev/libbpf-devel
bpftool is missing or not supporting skeletons, building without BPF skeleton support.
Please install bpftool
make -f /work/git/linux-trace.git/tools/build/Makefile.build dir=. obj=rtla
make[1]: Entering directory '/work/git/linux-trace.git/tools/tracing/rtla'
make[2]: Entering directory '/work/git/linux-trace.git/tools/tracing/rtla'
  CC      /work/git/linux-trace.git/tools/tracing/rtla/src/trace.o
  CC      /work/git/linux-trace.git/tools/tracing/rtla/src/utils.o
  CC      /work/git/linux-trace.git/tools/tracing/rtla/src/actions.o
  CC      /work/git/linux-trace.git/tools/tracing/rtla/src/common.o
  CC      /work/git/linux-trace.git/tools/tracing/rtla/src/osnoise.o
  CC      /work/git/linux-trace.git/tools/tracing/rtla/src/osnoise_top.o
  CC      /work/git/linux-trace.git/tools/tracing/rtla/src/osnoise_hist.o
  CC      /work/git/linux-trace.git/tools/tracing/rtla/src/timerlat.o
In file included from src/timerlat.c:18:
src/timerlat_bpf.h:15:10: fatal error: bpf/libbpf.h: No such file or directory
   15 | #include <bpf/libbpf.h>
      |          ^~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [/work/git/linux-trace.git/tools/build/Makefile.build:94: /work/git/linux-trace.git/tools/tracing/rtla/src/timerlat.o] Error 1
make[2]: Leaving directory '/work/git/linux-trace.git/tools/tracing/rtla'
make[1]: *** [/work/git/linux-trace.git/tools/build/Makefile.build:156: src] Error 2
make[1]: Leaving directory '/work/git/linux-trace.git/tools/tracing/rtla'
make: *** [Makefile:104: /work/git/linux-trace.git/tools/tracing/rtla/rtla-in.o] Error 2

That should probably be fixed on top of v7.0-rcX so that it is not
broken in 7.0.

-- Steve


> 
> Thanks,
> Tomas
> 
> The following changes since commit 11439c4635edd669ae435eec308f4ab8a0804808:
> 
>   Linux 7.0-rc2 (2026-03-01 15:39:31 -0800)
> 
> are available in the Git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/tglozar/linux.git tags/rtla-v7.1
> 
> for you to fetch changes up to 82374995b63d2de21414163828a32d52610dcaf2:
> 
>   Documentation/rtla: Document SIGINT behavior (2026-03-27 10:58:30 +0100)


^ permalink raw reply

* Re: [PATCH 1/2] tracing/hist: bound full field-name construction
From: Steven Rostedt @ 2026-03-29 18:39 UTC (permalink / raw)
  To: Pengpeng Hou
  Cc: mhiramat, mathieu.desnoyers, tom.zanussi, linux-kernel,
	linux-trace-kernel
In-Reply-To: <20260329030950.32503-1-pengpeng@iscas.ac.cn>

On Sun, 29 Mar 2026 11:09:49 +0800
Pengpeng Hou <pengpeng@iscas.ac.cn> wrote:

> hist_field_name() builds a fully qualified synthetic field name in a
> fixed MAX_FILTER_STR_VAL buffer using repeated strcat() calls. Long
> system, event, and field names can therefore overflow the static staging
> buffer.
> 
> Build the qualified name with snprintf() and fall back to the plain
> field name if it does not fit.

The fallback breaks 
> 
> Fixes: 067fe038e70f ("tracing: Add variable reference handling to hist triggers")

Do you have any examples where it actually does overflow or is this just theoretical?

If it's just theoretical, it does not get a "Fixes" tag.

Hmm, but actually I don't see it resetting full_name to a '\0' so I can see
this concatenating on top of a previous value. THAT would need fixing and
require a fixes tag. An example of triggering the overflow would also be
required.

> Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
> ---
>  kernel/trace/trace_events_hist.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
> index 73ea180cad55..4a27da628a71 100644
> --- a/kernel/trace/trace_events_hist.c
> +++ b/kernel/trace/trace_events_hist.c
> @@ -1362,12 +1362,12 @@ static const char *hist_field_name(struct hist_field *field,
>  		if (field->system) {
>  			static char full_name[MAX_FILTER_STR_VAL];
>  
> -			strcat(full_name, field->system);
> -			strcat(full_name, ".");
> -			strcat(full_name, field->event_name);
> -			strcat(full_name, ".");
> -			strcat(full_name, field->name);
> -			field_name = full_name;
> +			if (snprintf(full_name, sizeof(full_name), "%s.%s.%s",
> +				     field->system, field->event_name,
> +				     field->name) < sizeof(full_name))

Ug, please do not use a horribly looking if conditional. And it should most
definitely error on overflow: Break it up:

		if (field->system) {
  			static char full_name[MAX_FILTER_STR_VAL];
			int len;

			len = snprintf(full_name, sizeof(full_name), "%s.%s.%s",
				       field->system, field->event_name,
				       field->name);

			if (len >= size(full_name))
				return NULL;

			field_name = full_name;

> +				field_name = full_name;
> +			else
> +				field_name = field->name;
>  		} else
>  			field_name = field->name;
>  	} else if (field->flags & HIST_FIELD_FL_TIMESTAMP)

-- Steve

^ permalink raw reply

* [PATCH v6] tracing: Preserve repeated boot-time tracing parameters
From: Wesley Atwell @ 2026-03-29 18:42 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mark Rutland, Mathieu Desnoyers, linux-kernel, linux-trace-kernel,
	Wesley Atwell
In-Reply-To: <20260328201842.1782806-1-atwellwea@gmail.com>

Some tracing boot parameters already accept delimited value lists, but
their __setup() handlers keep only the last instance seen at boot.
Make repeated instances append to the same boot-time buffer in the
format each parser already consumes.

Use a shared trace_append_boot_param() helper for the ftrace filters,
trace_options, and kprobe_event boot parameters. trace_trigger=
still tokenizes a temporary parse buffer in place, but now copies each
parsed event/trigger pair into boot-time storage so repeated instances
do not overwrite earlier ones.

This also lets Bootconfig array values work naturally when they expand
to repeated param=value entries.

Before this change, only the last instance from each repeated
parameter survived boot.

Signed-off-by: Wesley Atwell <atwellwea@gmail.com>
---
Changes since v5: https://lore.kernel.org/all/20260328201842.1782806-1-atwellwea@gmail.com/
- add the separator accounting comment in trace_append_boot_param()
- keep the existing trace_trigger= temporary buffer and copy each
  parsed event/trigger pair into boot-time storage instead of tracking
  a running offset inside that buffer

 kernel/trace/ftrace.c       | 12 ++++++++----
 kernel/trace/trace.c        | 30 +++++++++++++++++++++++++++++-
 kernel/trace/trace.h        |  2 ++
 kernel/trace/trace_events.c | 24 +++++++++++++++++++++---
 kernel/trace/trace_kprobe.c |  3 ++-
 5 files changed, 62 insertions(+), 9 deletions(-)

diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 413310912609..8bd3dd1d549c 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -6841,7 +6841,8 @@ bool ftrace_filter_param __initdata;
 static int __init set_ftrace_notrace(char *str)
 {
 	ftrace_filter_param = true;
-	strscpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);
+	trace_append_boot_param(ftrace_notrace_buf, str, ',',
+				FTRACE_FILTER_SIZE);
 	return 1;
 }
 __setup("ftrace_notrace=", set_ftrace_notrace);
@@ -6849,7 +6850,8 @@ __setup("ftrace_notrace=", set_ftrace_notrace);
 static int __init set_ftrace_filter(char *str)
 {
 	ftrace_filter_param = true;
-	strscpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);
+	trace_append_boot_param(ftrace_filter_buf, str, ',',
+				FTRACE_FILTER_SIZE);
 	return 1;
 }
 __setup("ftrace_filter=", set_ftrace_filter);
@@ -6861,14 +6863,16 @@ static int ftrace_graph_set_hash(struct ftrace_hash *hash, char *buffer);
 
 static int __init set_graph_function(char *str)
 {
-	strscpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
+	trace_append_boot_param(ftrace_graph_buf, str, ',',
+				FTRACE_FILTER_SIZE);
 	return 1;
 }
 __setup("ftrace_graph_filter=", set_graph_function);
 
 static int __init set_graph_notrace_function(char *str)
 {
-	strscpy(ftrace_graph_notrace_buf, str, FTRACE_FILTER_SIZE);
+	trace_append_boot_param(ftrace_graph_notrace_buf, str, ',',
+				FTRACE_FILTER_SIZE);
 	return 1;
 }
 __setup("ftrace_graph_notrace=", set_graph_notrace_function);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index a626211ceb9a..2fbfcb506b24 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -228,6 +228,33 @@ static int boot_instance_index;
 static char boot_snapshot_info[COMMAND_LINE_SIZE] __initdata;
 static int boot_snapshot_index;
 
+/*
+ * Repeated boot parameters, including Bootconfig array expansions, need
+ * to stay in the delimiter form that the existing parser consumes.
+ */
+void __init trace_append_boot_param(char *buf, const char *str, char sep,
+				    int size)
+{
+	int len, needed, str_len;
+
+	if (!*str)
+		return;
+
+	len = strlen(buf);
+	str_len = strlen(str);
+	needed = len + str_len + 1;
+	/* For continuation, account for the separator. */
+	if (len)
+		needed++;
+	if (needed > size)
+		return;
+
+	if (len)
+		buf[len++] = sep;
+
+	strscpy(buf + len, str, size - len);
+}
+
 static int __init set_cmdline_ftrace(char *str)
 {
 	strscpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
@@ -329,7 +356,8 @@ static char trace_boot_options_buf[MAX_TRACER_SIZE] __initdata;
 
 static int __init set_trace_boot_options(char *str)
 {
-	strscpy(trace_boot_options_buf, str, MAX_TRACER_SIZE);
+	trace_append_boot_param(trace_boot_options_buf, str, ',',
+				MAX_TRACER_SIZE);
 	return 1;
 }
 __setup("trace_options=", set_trace_boot_options);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index b8f3804586a0..237a0417de1c 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -863,6 +863,8 @@ extern int DYN_FTRACE_TEST_NAME(void);
 extern int DYN_FTRACE_TEST_NAME2(void);
 
 extern void trace_set_ring_buffer_expanded(struct trace_array *tr);
+void __init trace_append_boot_param(char *buf, const char *str,
+				    char sep, int size);
 extern bool tracing_selftest_disabled;
 
 #ifdef CONFIG_FTRACE_STARTUP_TEST
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 249d1cba72c0..1c4a4a46169e 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -17,6 +17,7 @@
 #include <linux/kthread.h>
 #include <linux/tracefs.h>
 #include <linux/uaccess.h>
+#include <linux/memblock.h>
 #include <linux/module.h>
 #include <linux/ctype.h>
 #include <linux/sort.h>
@@ -3674,7 +3675,7 @@ trace_create_new_event(struct trace_event_call *call,
 #define MAX_BOOT_TRIGGERS 32
 
 static struct boot_triggers {
-	const char		*event;
+	char			*event;
 	char			*trigger;
 } bootup_triggers[MAX_BOOT_TRIGGERS];
 
@@ -3683,6 +3684,7 @@ static int nr_boot_triggers;
 
 static __init int setup_trace_triggers(char *str)
 {
+	char *event;
 	char *trigger;
 	char *buf;
 	int i;
@@ -3692,14 +3694,30 @@ static __init int setup_trace_triggers(char *str)
 	disable_tracing_selftest("running event triggers");
 
 	buf = bootup_trigger_buf;
-	for (i = 0; i < MAX_BOOT_TRIGGERS; i++) {
+	for (i = nr_boot_triggers; i < MAX_BOOT_TRIGGERS; i++) {
 		trigger = strsep(&buf, ",");
 		if (!trigger)
 			break;
-		bootup_triggers[i].event = strsep(&trigger, ".");
+		event = strsep(&trigger, ".");
 		bootup_triggers[i].trigger = trigger;
 		if (!bootup_triggers[i].trigger)
 			break;
+
+		/*
+		 * Keep each parsed trigger outside the temporary setup
+		 * buffer so repeated trace_trigger= entries do not
+		 * overwrite earlier ones.
+		 */
+		bootup_triggers[i].event =
+			memblock_alloc_or_panic(strlen(event) + 1,
+						SMP_CACHE_BYTES);
+		strscpy(bootup_triggers[i].event, event,
+			strlen(event) + 1);
+		bootup_triggers[i].trigger =
+			memblock_alloc_or_panic(strlen(trigger) + 1,
+						SMP_CACHE_BYTES);
+		strscpy(bootup_triggers[i].trigger, trigger,
+			strlen(trigger) + 1);
 	}
 
 	nr_boot_triggers = i;
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index a5dbb72528e0..e9f1c55aea64 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -31,7 +31,8 @@ static char kprobe_boot_events_buf[COMMAND_LINE_SIZE] __initdata;
 
 static int __init set_kprobe_boot_events(char *str)
 {
-	strscpy(kprobe_boot_events_buf, str, COMMAND_LINE_SIZE);
+	trace_append_boot_param(kprobe_boot_events_buf, str, ';',
+				COMMAND_LINE_SIZE);
 	disable_tracing_selftest("running kprobe events");
 
 	return 1;
-- 
2.43.0

^ permalink raw reply related

* Re: [PATCH 2/2] tracing/hist: allocate synthetic-field command buffers to fit
From: Steven Rostedt @ 2026-03-29 18:49 UTC (permalink / raw)
  To: Pengpeng Hou
  Cc: mhiramat, mathieu.desnoyers, tom.zanussi, linux-kernel,
	linux-trace-kernel
In-Reply-To: <20260329030950.32503-2-pengpeng@iscas.ac.cn>

On Sun, 29 Mar 2026 11:09:50 +0800
Pengpeng Hou <pengpeng@iscas.ac.cn> wrote:

> The synthetic field helpers currently build temporary names and trigger
> commands in fixed MAX_FILTER_STR_VAL buffers with strcpy() and strcat().
> Long field names, key lists, or saved filters can therefore overrun
> those staging buffers while constructing the synthetic histogram
> command.
> 
> Allocate the synthetic name and command buffers to the exact size
> required by the current histogram instead of relying on fixed-size
> scratch storage.

No, the names should never be greater than the max value defined. If they
are, then it should error out.

> 
> Fixes: 02205a6752f2 ("tracing: Add support for 'field variables'")
> Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
> ---
>  kernel/trace/trace_events_hist.c | 46 +++++++++++++++++++-------------
>  1 file changed, 28 insertions(+), 18 deletions(-)
> 
> diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
> index 4a27da628a71..1883bd6d9b95 100644
> --- a/kernel/trace/trace_events_hist.c
> +++ b/kernel/trace/trace_events_hist.c
> @@ -2964,13 +2964,10 @@ find_synthetic_field_var(struct hist_trigger_data *target_hist_data,
>  	struct hist_field *event_var;
>  	char *synthetic_name;
>  

Should be preceded with:

	if (strlen("synthetic_") + strlen(field_name) >= MAX_FILTER_STR_VAL)
		return ERR_PTR(-E2BIG);


> -	synthetic_name = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
> +	synthetic_name = kasprintf(GFP_KERNEL, "synthetic_%s", field_name);
>  	if (!synthetic_name)
>  		return ERR_PTR(-ENOMEM);
>  
> -	strcpy(synthetic_name, "synthetic_");
> -	strcat(synthetic_name, field_name);
> -
>  	event_var = find_event_var(target_hist_data, system, event_name, synthetic_name);
>  
>  	kfree(synthetic_name);
> @@ -3016,6 +3013,8 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
>  	struct hist_field *event_var;
>  	char *saved_filter;
>  	char *cmd;
> +	size_t cmdlen;
> +	size_t off;
>  	int ret;
>  
>  	if (target_hist_data->n_field_var_hists >= SYNTH_FIELDS_MAX) {
> @@ -3053,35 +3052,46 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
>  	if (!var_hist)
>  		return ERR_PTR(-ENOMEM);
>  
> -	cmd = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
> +	saved_filter = find_trigger_filter(hist_data, file);
> +
> +	cmdlen = strlen("keys=") + strlen(":synthetic_") +
> +		 strlen(field_name) + strlen("=") + strlen(field_name) + 1;
> +	first = true;
> +	for_each_hist_key_field(i, hist_data) {
> +		key_field = hist_data->fields[i];
> +		if (!first)
> +			cmdlen++;
> +		cmdlen += strlen(key_field->field->name);
> +		first = false;
> +	}
> +
> +	if (saved_filter)
> +		cmdlen += strlen(" if ") + strlen(saved_filter);
> +

Length should be checked. There shouldn't be huge strings for filters.
Perhaps in the future we may make them bigger but for now, 256 bytes should
be the limit.

-- Steve


> +	cmd = kzalloc(cmdlen, GFP_KERNEL);
>  	if (!cmd) {
>  		kfree(var_hist);
>  		return ERR_PTR(-ENOMEM);
>  	}
>  
>  	/* Use the same keys as the compatible histogram */
> -	strcat(cmd, "keys=");
> +	off = scnprintf(cmd, cmdlen, "keys=");
> +	first = true;
>  
>  	for_each_hist_key_field(i, hist_data) {
>  		key_field = hist_data->fields[i];
> -		if (!first)
> -			strcat(cmd, ",");
> -		strcat(cmd, key_field->field->name);
> +		off += scnprintf(cmd + off, cmdlen - off, "%s%s",
> +				 first ? "" : ",",
> key_field->field->name); first = false;
>  	}
>  
>  	/* Create the synthetic field variable specification */
> -	strcat(cmd, ":synthetic_");
> -	strcat(cmd, field_name);
> -	strcat(cmd, "=");
> -	strcat(cmd, field_name);
> +	off += scnprintf(cmd + off, cmdlen - off, ":synthetic_%s=%s",
> +			 field_name, field_name);
>  
>  	/* Use the same filter as the compatible histogram */
> -	saved_filter = find_trigger_filter(hist_data, file);
> -	if (saved_filter) {
> -		strcat(cmd, " if ");
> -		strcat(cmd, saved_filter);
> -	}
> +	if (saved_filter)
> +		scnprintf(cmd + off, cmdlen - off, " if %s",
> saved_filter); 
>  	var_hist->cmd = kstrdup(cmd, GFP_KERNEL);
>  	if (!var_hist->cmd) {


^ permalink raw reply

* Re: [PATCH v13 4/4] ring-buffer: Add persistent ring buffer selftest
From: Masami Hiramatsu @ 2026-03-30  1:42 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel, Ian Rogers
In-Reply-To: <20260327162508.6cac690c@gandalf.local.home>

On Fri, 27 Mar 2026 16:25:08 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:

> On Wed, 25 Mar 2026 11:25:25 +0900
> "Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:
> 
> > From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> > 
> > Add a self-destractive test for the persistent ring buffer. This
> > will invalidate some sub-buffer pages in the persistent ring buffer
> > when kernel gets panic, and check whether the number of detected
> > invalid pages and the total entry_bytes are the same as record
> > after reboot.
> > 
> > This can ensure the kernel correctly recover partially corrupted
> > persistent ring buffer when boot.
> > 
> > The test only runs on the persistent ring buffer whose name is
> > "ptracingtest". And user has to fill it up with events before
> > kernel panics.
> > 
> > To run the test, enable CONFIG_RING_BUFFER_PERSISTENT_SELFTEST
> 
> I think a more appropriate config name would be:
> 
>   CONFIG_PERSISTENT_RING_BUFFER_ERROR_INJECT
> 
> as that's what it is doing as it is only testing error injection and not
> the persistent ring buffer.

OK, selftest will be another implementation.

(preparing buffer with test data and check recovery process?)

> 
> > and you have to setup the kernel cmdline;
> > 
> >  reserve_mem=20M:2M:trace trace_instance=ptracingtest^traceoff@trace
> >  panic=1
> > 
> > And run following commands after the 1st boot;
> > 
> >  cd /sys/kernel/tracing/instances/ptracingtest
> >  echo 1 > tracing_on
> >  echo 1 > events/enable
> >  sleep 3
> >  echo c > /proc/sysrq-trigger
> 
> These instructions should probably be in the CONFIG help message.

OK. I'll add it.

> 
> > 
> > After panic message, the kernel will reboot and run the verification
> > on the persistent ring buffer, e.g.
> > 
> >  Ring buffer meta [2] invalid buffer page detected
> >  Ring buffer meta [2] is from previous boot! (318 pages discarded)
> >  Ring buffer testing [2] invalid pages: PASSED (318/318)
> >  Ring buffer testing [2] entry_bytes: PASSED (1300476/1300476)
> 
> BTW, when I tested this, I got the above on the first boot, but if I
> rebooted normally without re-enabling the persistent ring buffer, I would
> get on the next boot:

Hmm, since it is already recovered (rewound) the 2nd rewound process
may not work correctly. Let me fix it.
> 
> 
> [    0.966510] Ring buffer meta [2] is from previous boot! (0 pages discarded)
> [    0.971338]  #2
> [    1.003431] Ring buffer meta [3] is from previous boot! (0 pages discarded)
> [    1.007737]  #3
> [    1.039091] Ring buffer meta [4] is from previous boot! (0 pages discarded)
> [    1.043181] Ring buffer testing [4] invalid pages: FAILED (0/1597)
> [    1.044660] Ring buffer testing [4] entry_bytes: PASSED (6512464/6512464)
> [    1.047829]  #4
> [    1.079811] Ring buffer meta [5] is from previous boot! (0 pages discarded)
> [    1.083728]  #5
> [    1.116764] Ring buffer meta [6] is from previous boot! (0 pages discarded)
> [    1.120846]  #6
> [    1.156502] Ring buffer meta [7] is from previous boot! (0 pages discarded)
> [    1.160857]  #7
> 
> I'll start testing the previous 3 patches and may add them to next.

Thanks,

> 
> Also, I noticed that there's nothing that reads the RB_MISSING as I thought
> it might. I'll have to look into how to pass that info to the trace output.
> 
> -- Steve
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply

* [PATCH v2 2/2] tracing/hist: reject synthetic-field strings that exceed MAX_FILTER_STR_VAL
From: Pengpeng Hou @ 2026-03-30  2:46 UTC (permalink / raw)
  To: rostedt, mhiramat, mathieu.desnoyers, tom.zanussi
  Cc: linux-kernel, linux-trace-kernel, pengpeng
In-Reply-To: <20260329030950.32503-2-pengpeng@iscas.ac.cn>

The synthetic field helpers build a prefixed synthetic field name and a
hist trigger command in fixed MAX_FILTER_STR_VAL staging buffers. Even
when each individual field or filter string stays within that limit, the
combined "keys=...:synthetic_...=... if ..." command can exceed 256
bytes and overrun the scratch buffer.

Keep MAX_FILTER_STR_VAL as the tracing-side limit and reject synthetic
field names or generated commands that do not fit in that bound before
formatting them into the fixed buffers.

Fixes: 02205a6752f2 ("tracing: Add support for 'field variables'")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
v2:
- keep MAX_FILTER_STR_VAL as the fixed tracing-side limit
- reject overlong synthetic names and generated commands with -E2BIG
- drop the previous dynamic-allocation approach

 kernel/trace/trace_events_hist.c | 57 +++++++++++++++++++++++---------
 1 file changed, 41 insertions(+), 16 deletions(-)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index f9c8a4f078ea..4172c91605af 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -2966,12 +2966,16 @@ find_synthetic_field_var(struct hist_trigger_data *target_hist_data,
 	struct hist_field *event_var;
 	char *synthetic_name;
 
+	if ((sizeof("synthetic_") - 1) + strlen(field_name) >=
+	    MAX_FILTER_STR_VAL)
+		return ERR_PTR(-E2BIG);
+
 	synthetic_name = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
 	if (!synthetic_name)
 		return ERR_PTR(-ENOMEM);
 
-	strcpy(synthetic_name, "synthetic_");
-	strcat(synthetic_name, field_name);
+	scnprintf(synthetic_name, MAX_FILTER_STR_VAL, "synthetic_%s",
+		  field_name);
 
 	event_var = find_event_var(target_hist_data, system, event_name, synthetic_name);
 
@@ -3018,6 +3022,8 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
 	struct hist_field *event_var;
 	char *saved_filter;
 	char *cmd;
+	size_t cmdlen;
+	size_t off;
 	int ret;
 
 	if (target_hist_data->n_field_var_hists >= SYNTH_FIELDS_MAX) {
@@ -3048,13 +3054,36 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
 	/* See if a synthetic field variable has already been created */
 	event_var = find_synthetic_field_var(target_hist_data, subsys_name,
 					     event_name, field_name);
-	if (!IS_ERR_OR_NULL(event_var))
+	if (IS_ERR(event_var))
+		return event_var;
+	if (event_var)
 		return event_var;
 
 	var_hist = kzalloc_obj(*var_hist);
 	if (!var_hist)
 		return ERR_PTR(-ENOMEM);
 
+	saved_filter = find_trigger_filter(hist_data, file);
+
+	cmdlen = strlen("keys=") + strlen(":synthetic_") +
+		 strlen(field_name) + strlen("=") + strlen(field_name);
+	first = true;
+	for_each_hist_key_field(i, hist_data) {
+		key_field = hist_data->fields[i];
+		if (!first)
+			cmdlen++;
+		cmdlen += strlen(key_field->field->name);
+		first = false;
+	}
+
+	if (saved_filter)
+		cmdlen += strlen(" if ") + strlen(saved_filter);
+
+	if (cmdlen >= MAX_FILTER_STR_VAL) {
+		kfree(var_hist);
+		return ERR_PTR(-E2BIG);
+	}
+
 	cmd = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
 	if (!cmd) {
 		kfree(var_hist);
@@ -3062,28 +3091,24 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
 	}
 
 	/* Use the same keys as the compatible histogram */
-	strcat(cmd, "keys=");
+	off = scnprintf(cmd, MAX_FILTER_STR_VAL, "keys=");
+	first = true;
 
 	for_each_hist_key_field(i, hist_data) {
 		key_field = hist_data->fields[i];
-		if (!first)
-			strcat(cmd, ",");
-		strcat(cmd, key_field->field->name);
+		off += scnprintf(cmd + off, MAX_FILTER_STR_VAL - off, "%s%s",
+				 first ? "" : ",", key_field->field->name);
 		first = false;
 	}
 
 	/* Create the synthetic field variable specification */
-	strcat(cmd, ":synthetic_");
-	strcat(cmd, field_name);
-	strcat(cmd, "=");
-	strcat(cmd, field_name);
+	off += scnprintf(cmd + off, MAX_FILTER_STR_VAL - off,
+			 ":synthetic_%s=%s", field_name, field_name);
 
 	/* Use the same filter as the compatible histogram */
-	saved_filter = find_trigger_filter(hist_data, file);
-	if (saved_filter) {
-		strcat(cmd, " if ");
-		strcat(cmd, saved_filter);
-	}
+	if (saved_filter)
+		scnprintf(cmd + off, MAX_FILTER_STR_VAL - off, " if %s",
+			  saved_filter);
 
 	var_hist->cmd = kstrdup(cmd, GFP_KERNEL);
 	if (!var_hist->cmd) {
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply related

* [PATCH v2 1/2] tracing/hist: rebuild full_name on each hist_field_name() call
From: Pengpeng Hou @ 2026-03-30  2:46 UTC (permalink / raw)
  To: rostedt, mhiramat, mathieu.desnoyers, tom.zanussi
  Cc: linux-kernel, linux-trace-kernel, pengpeng
In-Reply-To: <20260329030950.32503-1-pengpeng@iscas.ac.cn>

hist_field_name() uses a static MAX_FILTER_STR_VAL buffer for fully
qualified variable-reference names, but it currently appends into that
buffer with strcat() without rebuilding it first. As a result, repeated
calls append a new "system.event.field" name onto the previous one,
which can eventually run past the end of full_name.

Build the name with snprintf() on each call and return NULL if the fully
qualified name does not fit in MAX_FILTER_STR_VAL.

Fixes: 067fe038e70f ("tracing: Add variable reference handling to hist triggers")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
v2:
- rebuild full_name on each call instead of falling back to field->name
- return NULL on overflow as suggested
- split out the snprintf() length check instead of using an inline if

 kernel/trace/trace_events_hist.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 73ea180cad55..f9c8a4f078ea 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -1361,12 +1361,14 @@ static const char *hist_field_name(struct hist_field *field,
 		 field->flags & HIST_FIELD_FL_VAR_REF) {
 		if (field->system) {
 			static char full_name[MAX_FILTER_STR_VAL];
+			int len;
+
+			len = snprintf(full_name, sizeof(full_name), "%s.%s.%s",
+				       field->system, field->event_name,
+				       field->name);
+			if (len >= sizeof(full_name))
+				return NULL;
 
-			strcat(full_name, field->system);
-			strcat(full_name, ".");
-			strcat(full_name, field->event_name);
-			strcat(full_name, ".");
-			strcat(full_name, field->name);
 			field_name = full_name;
 		} else
 			field_name = field->name;
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox