]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Buffer overflow in drivers/xen/sys-hypervisor.c
authorJuergen Gross <jgross@suse.com>
Fri, 27 Mar 2026 13:13:38 +0000 (14:13 +0100)
committerJuergen Gross <jgross@suse.com>
Thu, 23 Apr 2026 13:32:51 +0000 (15:32 +0200)
The build id returned by HYPERVISOR_xen_version(XENVER_build_id) is
neither NUL terminated nor a string.

The first causes a buffer overflow as sprintf in buildid_show will
read and copy till it finds a NUL.

00000000  f4 91 51 f4 dd 38 9e 9d  65 47 52 eb 10 71 db 50  |..Q..8..eGR..q.P|
00000010  b9 a8 01 42 6f 2e 32                              |...Bo.2|
00000017

So use a memcpy instead of sprintf to have the correct value:

00000000  f4 91 51 f4 dd 00 9e 9d  65 47 52 eb 10 71 db 50  |..Q.....eGR..q.P|
00000010  b9 a8 01 42                                       |...B|
00000014

(the above have a hack to embed a zero inside and check it's
returned correctly).

This is XSA-485 / CVE-2026-31786

Fixes: 84b7625728ea ("xen: add sysfs node for hypervisor build id")
Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
drivers/xen/sys-hypervisor.c

index b1bb01ba82f880d7cbd51fc21a1b2d38bb45e8cf..91923242a5ae71d6314e69d7d18a08a03932e3ef 100644 (file)
@@ -366,6 +366,8 @@ static ssize_t buildid_show(struct hyp_sysfs_attr *attr, char *buffer)
                        ret = sprintf(buffer, "<denied>");
                return ret;
        }
+       if (ret > PAGE_SIZE)
+               return -ENOSPC;
 
        buildid = kmalloc(sizeof(*buildid) + ret, GFP_KERNEL);
        if (!buildid)
@@ -373,8 +375,10 @@ static ssize_t buildid_show(struct hyp_sysfs_attr *attr, char *buffer)
 
        buildid->len = ret;
        ret = HYPERVISOR_xen_version(XENVER_build_id, buildid);
-       if (ret > 0)
-               ret = sprintf(buffer, "%s", buildid->buf);
+       if (ret > 0) {
+               /* Build id is binary, not a string. */
+               memcpy(buffer, buildid->buf, ret);
+       }
        kfree(buildid);
 
        return ret;