]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: fix NULL+offset dereference in cpuinfo_parse_cache()
authorrawrmonster17 <rawrmonster17@users.noreply.github.com>
Fri, 19 Jun 2026 05:17:45 +0000 (00:17 -0500)
committerrawrmonster17 <rawrmonster17@users.noreply.github.com>
Fri, 19 Jun 2026 05:17:45 +0000 (00:17 -0500)
strstr() returns NULL when the needle is absent.  In two places the
return value had a constant offset added before the NULL guard:

  p = strstr(data, "scope=") + 6;
  if (!p ...)                       /* dead: p is (char*)6 if absent */

  p = strstr(data, "type=") + 5;
  if (!p || !*p)                    /* same: p is (char*)5 if absent */

When the field is missing from the cpuinfo cache line, p becomes a
low non-NULL address (CWE-476 / CWE-823).  The !p guard is dead, so
strncmp() or the *p dereference immediately faults.

Fix by moving the arithmetic after the NULL check, matching the
correct pattern already used for "level=", "size=", "line_size=", and
"associativity=" in the same function.

sys-utils/lscpu-cputype.c

index 9b43f0e3f4ea6ae8848ef62e7fc72ec2d4bdec22..435209fc1ebfd1f370bb1c213a6ceca54acd06a7 100644 (file)
@@ -530,16 +530,17 @@ static int cpuinfo_parse_cache(struct lscpu_cxt *cxt, int keynum, char *data)
 
        DBG_OBJ(GATHER, cxt, ul_debug(" parse cpuinfo cache '%s'", data));
 
-       p = strstr(data, "scope=") + 6;
+       p = strstr(data, "scope=");
        /* Skip private caches, also present in sysfs */
-       if (!p || strncmp(p, "Private", 7) == 0)
+       if (!p || strncmp(p + 6, "Private", 7) == 0)
                return 0;
        p = strstr(data, "level=");
        if (!p || sscanf(p, "level=%d", &level) != 1)
                return 0;
-       p = strstr(data, "type=") + 5;
-       if (!p || !*p)
+       p = strstr(data, "type=");
+       if (!p || !*(p + 5))
                return 0;
+       p += 5;
        type = 0;
        if (strncmp(p, "Data", 4) == 0)
                type = 'd';