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. Signed-off-by: Motomasa Suzuki <[email protected]> --- defs.h | 1 + kernel.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/defs.h b/defs.h index ab4aee8..b459d4d 100644 --- a/defs.h +++ b/defs.h @@ -2280,6 +2280,7 @@ struct offset_table { /* stash of commonly-used offsets */ long bpf_ringbuf_map_rb; long bpf_ringbuf_consumer_pos; long bpf_ringbuf_nr_pages; + long klp_patch_list; }; struct size_table { /* stash of commonly-used sizes */ diff --git a/kernel.c b/kernel.c index 13f3374..1ca18e4 100644 --- a/kernel.c +++ b/kernel.c @@ -461,7 +461,10 @@ kernel_init() error(WARNING, "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"); @@ -5681,6 +5684,48 @@ is_livepatch(void) return FALSE; } +#define KLP_PATCH_ITER_LIMIT 1024 + +static int +is_livepatch_transition(void) +{ + struct kernel_list_head head; + struct kernel_list_head node; + ulong transition_patch; + ulong list_addr; + ulong current; + ulong patch_addr; + int loops; + + if (!try_get_symbol_data("klp_transition_patch", sizeof(ulong), + &transition_patch) || !transition_patch) + return FALSE; + + if (!kernel_symbol_exists("klp_patches") || !VALID_MEMBER(klp_patch_list)) + return FALSE; + + list_addr = symbol_value("klp_patches"); + if (!readmem(list_addr, KVADDR, &head, sizeof(head), "klp_patches", + RETURN_ON_ERROR | QUIET)) + return FALSE; + + for (current = (ulong)head.next, loops = 0; + current && current != list_addr && loops < KLP_PATCH_ITER_LIMIT; + current = (ulong)node.next, loops++) { + + if (!readmem(list_addr, KVADDR, &head, sizeof(head), + "klp_patch list entry", RETURN_ON_ERROR | QUIET)) + return FALSE; + + patch_addr = current - (ulong)OFFSET(klp_patch_list); + + if (patch_addr == transition_patch) + return TRUE; + } + + return FALSE; +} + /* * Display system stats at init-time or for the sys command. */ @@ -5724,17 +5769,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
