On Tue, Dec 23, 2025 at 6:51 PM Motomasa Suzuki <[email protected]> wrote: > > This commit enhances the 'sys' command to show if a kernel livepatch is > currently in a transition phase, directly within the KERNEL output line. > > Currently, diagnosing system state during or immediately after livepatch > operations can be ambiguous. While 'livepatch' is indicated by > '[LIVEPATCH]', there's no direct indicator within 'crash' itself to > show if a livepatch is actively applying, reverting, or in some other > transient state. This lack of immediate visibility can complicate crash > analysis, as the system might be in an inconsistent state due to an > ongoing patch application/reversion. > > This change introduces a new '[TRANSITION]' flag which appears next to > '[LIVEPATCH]' and '[TAINTED]' in the 'sys' command output. This > flag is set if the livepatch subsystem indicates an in-progress > transition > (e.g., as exposed via '/sys/kernel/livepatch/<patch_name>/transition'). > > Example 'sys' output with this change: > KERNEL: /usr/lib/debug/lib/modules/<version_name>/vmlinux [LIVEPATCH] > [TRANSITION] [TAINTED] > > This enhancement provides critical, at-a-glance information for > developers and administrators, allowing them to quickly ascertain if > ongoing livepatch activity might be influencing a system's behavior > during crash investigations. It directly leverages existing kernel > livepatch status infrastructure to enrich the crash utility's diagnostic > capabilities. > > > Changes v1 -> v2: > - Reworked klp_patches list traversal to use the crash utility’s > do_list() helper instead of manual list handling.
The v2 LGTM, so ack. Thanks, Tao Liu > > Signed-off-by: Motomasa Suzuki <[email protected]> > --- > defs.h | 1 + > kernel.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- > 2 files changed, 74 insertions(+), 2 deletions(-) > > diff --git a/defs.h b/defs.h > index ceed3a9..cfdfa08 100644 > --- a/defs.h > +++ b/defs.h > @@ -2289,6 +2289,7 @@ struct offset_table { /* stash of > commonly-used offsets */ > long bpf_ringbuf_consumer_pos; > long bpf_ringbuf_nr_pages; > long hrtimer_clock_base_index; > + long klp_patch_list; > }; > > struct size_table { /* stash of commonly-used sizes */ > diff --git a/kernel.c b/kernel.c > index bb148d0..ccc4b3d 100644 > --- a/kernel.c > +++ b/kernel.c > @@ -464,6 +464,11 @@ kernel_init() > "list_head.next offset: %ld: list command may fail\n", > OFFSET(list_head_next)); > > + if (STRUCT_EXISTS("klp_patch")) { > + if (MEMBER_EXISTS("klp_patch", "list")) > + MEMBER_OFFSET_INIT(klp_patch_list, "klp_patch", > "list"); > + } > + > MEMBER_OFFSET_INIT(hlist_node_next, "hlist_node", "next"); > MEMBER_OFFSET_INIT(hlist_node_pprev, "hlist_node", "pprev"); > STRUCT_SIZE_INIT(hlist_head, "hlist_head"); > @@ -5689,6 +5694,70 @@ is_livepatch(void) > return FALSE; > } > > +struct klp_transition_ctx { > + ulong transition_patch; > + int found; > +}; > + > +static int > +klp_transition_match(void *entry, void *data) > +{ > + struct klp_transition_ctx *ctx = data; > + > + if ((ulong)entry == ctx->transition_patch) { > + ctx->found = TRUE; > + return TRUE; > + } > + > + return FALSE; > +} > + > +static int > +is_livepatch_transition(void) > +{ > + struct kernel_list_head head; > + struct list_data ld; > + struct klp_transition_ctx ctx; > + ulong transition_patch; > + ulong list_addr; > + int ret; > + > + if (!try_get_symbol_data("klp_transition_patch", > + sizeof(ulong), &transition_patch) || !transition_patch) > + return FALSE; > + > + if (!STRUCT_EXISTS("klp_patch") || !VALID_MEMBER(klp_patch_list) || > + !kernel_symbol_exists("klp_patches")) > + return TRUE; > + > + list_addr = symbol_value("klp_patches"); > + if (!readmem(list_addr, KVADDR, &head, sizeof(head), "klp_patches", > + RETURN_ON_ERROR | QUIET)) > + return TRUE; > + > + if (!head.next || head.next == (void *)list_addr) > + return TRUE; > + > + BZERO(&ctx, sizeof(ctx)); > + ctx.transition_patch = transition_patch; > + > + BZERO(&ld, sizeof(ld)); > + ld.flags = LIST_CALLBACK|CALLBACK_RETURN|RETURN_ON_LIST_ERROR| > + RETURN_ON_DUPLICATE|LIST_ALLOCATE; > + ld.start = (ulong)head.next; > + ld.end = list_addr; > + ld.member_offset = OFFSET(list_head_next); > + ld.list_head_offset = OFFSET(klp_patch_list); > + ld.callback_func = klp_transition_match; > + ld.callback_data = &ctx; > + > + ret = do_list(&ld); > + if (ret < 0) > + return FALSE; > + > + return ctx.found; > +} > + > /* > * Display system stats at init-time or for the sys command. > */ > @@ -5732,17 +5801,19 @@ display_sys_stats(void) > } > } else { > if (pc->system_map) { > - fprintf(fp, " SYSTEM MAP: %s%s%s\n", pc->system_map, > + fprintf(fp, " SYSTEM MAP: %s%s%s%s\n", > pc->system_map, > is_livepatch() ? " [LIVEPATCH]" : "", > + is_livepatch_transition() ? " [TRANSITION]" > : "", > is_kernel_tainted() ? " [TAINTED]" : ""); > fprintf(fp, "DEBUG KERNEL: %s %s\n", > pc->namelist_orig ? > pc->namelist_orig : pc->namelist, > debug_kernel_version(pc->namelist)); > } else > - fprintf(fp, " KERNEL: %s%s%s\n", > pc->namelist_orig ? > + fprintf(fp, " KERNEL: %s%s%s%s\n", > pc->namelist_orig ? > pc->namelist_orig : pc->namelist, > is_livepatch() ? " [LIVEPATCH]" : "", > + is_livepatch_transition() ? " [TRANSITION]" > : "", > is_kernel_tainted() ? " [TAINTED]" : ""); > } > > -- > 2.47.3 > -- Crash-utility mailing list -- [email protected] To unsubscribe send an email to [email protected] https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/ Contribution Guidelines: https://github.com/crash-utility/crash/wiki
