git: e99c0c8b79b0 - main - xen: Prevent buffer overflow in privcmd ioctl

From: Roger Pau Monné <royger_at_FreeBSD.org>
Date: Fri, 06 May 2022 08:09:38 UTC
The branch main has been updated by royger:

URL: https://cgit.FreeBSD.org/src/commit/?id=e99c0c8b79b030e6c63e4f7149154d926a360664

commit e99c0c8b79b030e6c63e4f7149154d926a360664
Author:     Dan Carpenter <dan.carpenter@oracle.com>
AuthorDate: 2019-04-04 15:12:17 +0000
Commit:     Roger Pau Monné <royger@FreeBSD.org>
CommitDate: 2022-05-06 07:31:32 +0000

    xen: Prevent buffer overflow in privcmd ioctl
    
    The "call" variable comes from the user in privcmd_ioctl_hypercall().
    It's an offset into the hypercall_page[] which has (PAGE_SIZE / 32)
    elements.  We need to put an upper bound on it to prevent an out of
    bounds access.
    
    Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
    Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
    Signed-off-by: Juergen Gross <jgross@suse.com>
    
    Obtained from: Linux
    Linux commit: 42d8644bd77dd2d747e004e367cb0c895a606f39
    Fixes: bf7313e3b79 ("xen: implement the privcmd user-space device")
    Submitted by: Elliott Mitchell <ehem+freebsd@m5p.com>
    Reviewed by: royger
---
 sys/amd64/include/xen/hypercall.h | 3 +++
 sys/i386/include/xen/hypercall.h  | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/sys/amd64/include/xen/hypercall.h b/sys/amd64/include/xen/hypercall.h
index 6d00d4a6ebd8..60da390ef4c6 100644
--- a/sys/amd64/include/xen/hypercall.h
+++ b/sys/amd64/include/xen/hypercall.h
@@ -145,6 +145,9 @@ privcmd_hypercall(long op, long a1, long a2, long a3, long a4, long a5)
 	register long __arg5 __asm__("r8") = (long)(a5);
 	long __call = (long)&hypercall_page + (op * 32);
 
+	if (op >= PAGE_SIZE / 32)
+		return -EINVAL;
+
 	__asm__ volatile (
 		"call *%[call]"
 		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),
diff --git a/sys/i386/include/xen/hypercall.h b/sys/i386/include/xen/hypercall.h
index 4002aac58d84..f1757e8becaf 100644
--- a/sys/i386/include/xen/hypercall.h
+++ b/sys/i386/include/xen/hypercall.h
@@ -122,6 +122,9 @@ privcmd_hypercall(long op, long a1, long a2, long a3, long a4, long a5)
 {
 	long __res, __ign1, __ign2, __ign3, __ign4, __ign5, __call;
 
+	if (op >= PAGE_SIZE / 32)
+		return -EINVAL;
+
 	__call = (long)&hypercall_page + (op * 32);
 	__asm__ volatile (
 		"call *%[call]"