In case linux banner can not be found in vmlinux for some reason.
The fallback checking of "Linux version" failed for kernel 7.x with
below error msg:
WARNING: kernel version inconsistency between vmlinux and dumpfile
crash: incompatible arguments: vmlinux is not SMP -- vmcore is SMP
Jiri's case is OpenSUSE uses separate vmlinux.debug file, details see
https://github.com/crash-utility/crash/issues/232
But update the kernel version number in kernel sanity checking code
does workaround the issue. Let's fix this separately.
A few improvements to the sanity checking including:
- Replace hardcoded version checks (2.x through 6.x) with a unified
kernel_version_str_sanity_check() function
- Extend support to Linux 7.x kernels
- Add proper bounds checking and null pointer validation
- Ensure minor version number is numeric for stricter validation
- Reduce code duplication in verify_namelist() and debug_kernel_version()
Reported-by: Jiri Slaby <jirislaby(a)gmail.com>
Signed-off-by: Dave Young <yangrr.2009(a)tsinghua.org.cn>
---
[V1->V2]: refactore the code; address comments from Mukesh
kernel.c | 39 +++++++++++++++++++++++++++++----------
1 file changed, 29 insertions(+), 10 deletions(-)
Index: crash/kernel.c
===================================================================
--- crash.orig/kernel.c 2026-08-14 11:21:39.972971968 +0800
+++ crash/kernel.c 2026-08-14 11:21:42.371976057 +0800
@@ -29,6 +29,9 @@
#endif
#include "bfd.h"
+#define KERNEL_VERSION_MIN '2'
+#define KERNEL_VERSION_MAX '7' /* latest linux mainline kernel major number */
+
static void do_module_cmd(ulong, char *, ulong, char *, char *);
static void show_module_taint(void);
static char *find_module_objfile(char *, char *, char *);
@@ -104,6 +107,30 @@
static int is_pvops_xen(void);
static int get_linux_banner_from_vmlinux(char *, size_t);
+static bool kernel_version_str_sanity_check(char *buf)
+{
+ int n;
+ char *p;
+
+ if (!buf)
+ return FALSE;
+
+ p = strstr(buf, "Linux version ");
+ if (!p)
+ return FALSE;
+
+ n = strlen(p);
+
+ if (n < 17) /* "Linux version " (14) + "x.y" (3) = 17 */
+ return FALSE;
+
+ if (p[14] >= KERNEL_VERSION_MIN && p[14] <= KERNEL_VERSION_MAX
+ && p[15] == '.' && p[16] >= '0' && p[16]
<= '9')
+ return TRUE;
+
+ return FALSE;
+}
+
/*
* popuplate the global kernel table (kt) with kernel version
* information parsed from UTSNAME/OSRELEASE string
@@ -1396,11 +1423,7 @@
found = FALSE;
sprintf(buffer3, "(unknown)");
while (fgets(buffer, (BUFSIZE/2)-1, pipe)) {
- if (!strstr(buffer, "Linux version 2.") &&
- !strstr(buffer, "Linux version 3.") &&
- !strstr(buffer, "Linux version 4.") &&
- !strstr(buffer, "Linux version 5.") &&
- !strstr(buffer, "Linux version 6."))
+ if (!kernel_version_str_sanity_check(buffer))
continue;
if (strstr(buffer, kt->proc_version)) {
@@ -5987,11 +6010,7 @@
argc = 0;
while (fgets(buf, BUFSIZE-1, pipe)) {
- if (!strstr(buf, "Linux version 2.") &&
- !strstr(buf, "Linux version 3.") &&
- !strstr(buf, "Linux version 4.") &&
- !strstr(buf, "Linux version 5.") &&
- !strstr(buf, "Linux version 6."))
+ if (!kernel_version_str_sanity_check(buf))
continue;
argc = parse_line(buf, arglist);