From ac7349dd70e6d8612c16f282b9f42e6a2d0742a8 Mon Sep 17 00:00:00 2001 From: Rohan Sethi Date: Mon, 22 Nov 2021 14:23:30 +0530 Subject: [PATCH] msm: kgsl: Fix gpuaddr_in_range() to check upper bound Currently gpuaddr_in_range() accepts only the gpuaddr & returns true if it lies in valid range. But this does not mean that the entire buffer is within range. Modify the function to accept size as a parameter and check that both starting & ending points of buffer lie within mmu range. Change-Id: I1d722295b9a27e746bfdb6d3bf409ffe722193cb Signed-off-by: Rohan Sethi --- drivers/gpu/msm/adreno_dispatch.c | 4 ++-- drivers/gpu/msm/adreno_hwsched.c | 3 ++- drivers/gpu/msm/kgsl.c | 4 ++-- drivers/gpu/msm/kgsl_iommu.c | 8 ++++---- drivers/gpu/msm/kgsl_mmu.c | 6 +++--- drivers/gpu/msm/kgsl_mmu.h | 7 ++++--- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 5177e74acc10..823a382b56b4 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -1125,8 +1125,8 @@ static inline bool _verify_ib(struct kgsl_device_private *dev_priv, } /* Make sure that the address is in range and dword aligned */ - if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr) || - !IS_ALIGNED(ib->gpuaddr, 4)) { + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr, + ib->size) || !IS_ALIGNED(ib->gpuaddr, 4)) { pr_context(device, context, "ctxt %d invalid ib gpuaddr %llX\n", context->id, ib->gpuaddr); return false; diff --git a/drivers/gpu/msm/adreno_hwsched.c b/drivers/gpu/msm/adreno_hwsched.c index 6eb466919833..085c003e0bcd 100644 --- a/drivers/gpu/msm/adreno_hwsched.c +++ b/drivers/gpu/msm/adreno_hwsched.c @@ -657,7 +657,8 @@ static inline bool _verify_ib(struct kgsl_device_private *dev_priv, } /* Make sure that the address is mapped */ - if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr)) { + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr, + ib->size)) { pr_context(device, context, "ctxt %d invalid ib gpuaddr %llX\n", context->id, ib->gpuaddr); return false; diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index f7cafa94a50e..ba36c63776c8 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -1302,9 +1302,9 @@ kgsl_sharedmem_find(struct kgsl_process_private *private, uint64_t gpuaddr) if (!private) return NULL; - if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr) && + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr, 0) && !kgsl_mmu_gpuaddr_in_range( - private->pagetable->mmu->securepagetable, gpuaddr)) + private->pagetable->mmu->securepagetable, gpuaddr, 0)) return NULL; spin_lock(&private->mem_lock); diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 0a16898be6e2..fc75683dd210 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -2287,20 +2287,20 @@ static int kgsl_iommu_svm_range(struct kgsl_pagetable *pagetable, } static bool kgsl_iommu_addr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { struct kgsl_iommu_pt *pt = pagetable->priv; if (gpuaddr == 0) return false; - if (gpuaddr >= pt->va_start && gpuaddr < pt->va_end) + if (gpuaddr >= pt->va_start && (gpuaddr + size) < pt->va_end) return true; - if (gpuaddr >= pt->compat_va_start && gpuaddr < pt->compat_va_end) + if (gpuaddr >= pt->compat_va_start && (gpuaddr + size) < pt->compat_va_end) return true; - if (gpuaddr >= pt->svm_start && gpuaddr < pt->svm_end) + if (gpuaddr >= pt->svm_start && (gpuaddr + size) < pt->svm_end) return true; return false; diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index 090a028b3c6f..2633b72f18f7 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -529,10 +529,10 @@ enum kgsl_mmutype kgsl_mmu_get_mmutype(struct kgsl_device *device) } bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { if (PT_OP_VALID(pagetable, addr_in_range)) - return pagetable->pt_ops->addr_in_range(pagetable, gpuaddr); + return pagetable->pt_ops->addr_in_range(pagetable, gpuaddr, size); return false; } @@ -544,7 +544,7 @@ bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pagetable, */ static bool nommu_gpuaddr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { return (gpuaddr != 0) ? true : false; } diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h index c1bcba4c666f..49d16d7e5491 100644 --- a/drivers/gpu/msm/kgsl_mmu.h +++ b/drivers/gpu/msm/kgsl_mmu.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved. */ #ifndef __KGSL_MMU_H #define __KGSL_MMU_H @@ -92,7 +92,7 @@ struct kgsl_mmu_pt_ops { int (*svm_range)(struct kgsl_pagetable *pt, uint64_t *lo, uint64_t *hi, uint64_t memflags); bool (*addr_in_range)(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr); + uint64_t gpuaddr, uint64_t size); }; enum kgsl_mmu_feature { @@ -174,7 +174,8 @@ void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc); unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr); unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, u64 ttbr0, uint64_t addr); -bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr); +bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr, + uint64_t size); int kgsl_mmu_get_region(struct kgsl_pagetable *pagetable, uint64_t gpuaddr, uint64_t size);