diff options
| author | Michael S. Tsirkin <mst@redhat.com> | 2016-08-01 23:20:53 +0300 |
|---|---|---|
| committer | Alistair Strachan <astrachan@google.com> | 2019-01-15 17:08:35 -0800 |
| commit | a2a85e6807dc3f9b34000cd0f23968d29260af0c (patch) | |
| tree | a07d602cfe4f431f6e6afcc1eff375cde1bbff0f | |
| parent | e177c82ed1fa522e4634ef30162211d43e5b642e (diff) | |
UPSTREAM: vhost: detect 32 bit integer wrap around
Detect and fail early if long wrap around is triggered.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit ec33d031a14b3c5dd516627139c9550350dbba3e)
Bug: 121166534
Test: Ran cuttlefish with android-4.4 + VSOCKETS, VMWARE_VMCI_VSOCKETS
Signed-off-by: Alistair Strachan <astrachan@google.com>
Change-Id: Id71c1ea0355ce3e403bb5865dc3056d197fe218b
| -rw-r--r-- | drivers/vhost/vhost.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index bd3428ce6b9b..154a566f7b97 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -657,6 +657,12 @@ static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz) (sz + VHOST_PAGE_SIZE * 8 - 1) / VHOST_PAGE_SIZE / 8); } +static bool vhost_overflow(u64 uaddr, u64 size) +{ + /* Make sure 64 bit math will not overflow. */ + return uaddr > ULONG_MAX || size > ULONG_MAX || uaddr > ULONG_MAX - size; +} + /* Caller should have vq mutex and device mutex. */ static int vq_memory_access_ok(void __user *log_base, struct vhost_umem *umem, int log_all) @@ -669,9 +675,11 @@ static int vq_memory_access_ok(void __user *log_base, struct vhost_umem *umem, list_for_each_entry(node, &umem->umem_list, link) { unsigned long a = node->userspace_addr; - if (node->size > ULONG_MAX) + if (vhost_overflow(node->userspace_addr, node->size)) return 0; - else if (!access_ok(VERIFY_WRITE, (void __user *)a, + + + if (!access_ok(VERIFY_WRITE, (void __user *)a, node->size)) return 0; else if (log_all && !log_access_ok(log_base, @@ -913,6 +921,10 @@ static int umem_access_ok(u64 uaddr, u64 size, int access) { unsigned long a = uaddr; + /* Make sure 64 bit math will not overflow. */ + if (vhost_overflow(uaddr, size)) + return -EFAULT; + if ((access & VHOST_ACCESS_RO) && !access_ok(VERIFY_READ, (void __user *)a, size)) return -EFAULT; |
