From 8f26c4460d4e6f2476366f9ff771559d507dae06 Mon Sep 17 00:00:00 2001 From: Mohammed Mirza Mandayappurath Manzoor Date: Thu, 14 Sep 2023 18:04:52 +0530 Subject: msm: kgsl: Prevent wrap around during user address mapping When setting svm region during the gpuobj import ioctl call for a usermem address, there is a possibility of a very large input size causing the region's 64-bit end address to wrap around. This can cause the region to incorrectly be considered valid, ultimately allowing a use after free scenario. To prevent this, detect the occurrence of a wrap and reject the import. Change-Id: I4a88f56c58b830d4342e47dc1d1f6290c78ab6b4 Signed-off-by: Mohammed Mirza Mandayappurath Manzoor --- drivers/gpu/msm/kgsl_iommu.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 2017810a3c7d..a80e60d9d4b6 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -1,5 +1,5 @@ /* Copyright (c) 2011-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2396,14 +2396,18 @@ static uint64_t kgsl_iommu_find_svm_region(struct kgsl_pagetable *pagetable, static bool iommu_addr_in_svm_ranges(struct kgsl_iommu_pt *pt, u64 gpuaddr, u64 size) { + u64 end = gpuaddr + size; + + /* Make sure size is not zero and we don't wrap around */ + if (end <= gpuaddr) + return false; + if ((gpuaddr >= pt->compat_va_start && gpuaddr < pt->compat_va_end) && - ((gpuaddr + size) > pt->compat_va_start && - (gpuaddr + size) <= pt->compat_va_end)) + (end > pt->compat_va_start && end <= pt->compat_va_end)) return true; if ((gpuaddr >= pt->svm_start && gpuaddr < pt->svm_end) && - ((gpuaddr + size) > pt->svm_start && - (gpuaddr + size) <= pt->svm_end)) + (end > pt->svm_start && end <= pt->svm_end)) return true; return false; -- cgit v1.2.3