From b1af9a0347b29ed7cbdb67ab4305e154945b483e Mon Sep 17 00:00:00 2001 From: Surbhi Singh Date: Fri, 6 Dec 2024 09:36:34 +0000 Subject: [PATCH] video: tegra: nvmap: Add checks for addition overflow Add check for overflow when two unsigned integers are added and return error in case of overflow condition. CID 13772217 CID 13772356 CID 13772469 CID 13772634 CID 13772882 CID 13772995 JIRA: TMM-5724 Bug 4479044 Change-Id: Iaa04cc45bfe11a0cfb2e8124d9423e3a66e39f73 Signed-off-by: Surbhi Singh Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3270465 Reviewed-by: Ajay Nandakumar Mannargudi Reviewed-by: Sachin Nikam GVS: buildbot_gerritrpt --- drivers/video/tegra/nvmap/nvmap_core.c | 7 +++-- drivers/video/tegra/nvmap/nvmap_debug.c | 40 +++++++++++++++++++------ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/drivers/video/tegra/nvmap/nvmap_core.c b/drivers/video/tegra/nvmap/nvmap_core.c index 4d555f04..a24ae13a 100644 --- a/drivers/video/tegra/nvmap/nvmap_core.c +++ b/drivers/video/tegra/nvmap/nvmap_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * SPDX-FileCopyrightText: Copyright (c) 2009-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-FileCopyrightText: Copyright (c) 2009-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * * Memory manager for Tegra GPU */ @@ -96,7 +96,9 @@ void *__nvmap_mmap(struct nvmap_handle *h) /* carveout - explicitly map the pfns into a vmalloc area */ adj_size = nvmap_get_heap_block_base(h->carveout) & ~PAGE_MASK; - adj_size += h->size; + if (check_add_overflow(adj_size, h->size, &adj_size)) + goto dec_kmaps; + adj_size = PAGE_ALIGN(adj_size); if (pfn_valid(__phys_to_pfn(nvmap_get_heap_block_base(h->carveout) & PAGE_MASK))) { @@ -149,6 +151,7 @@ void *__nvmap_mmap(struct nvmap_handle *h) out: if (pages) vfree(pages); +dec_kmaps: nvmap_kmaps_dec(h); put_handle: nvmap_handle_put(h); diff --git a/drivers/video/tegra/nvmap/nvmap_debug.c b/drivers/video/tegra/nvmap/nvmap_debug.c index 5defd115..94d0c97d 100644 --- a/drivers/video/tegra/nvmap/nvmap_debug.c +++ b/drivers/video/tegra/nvmap/nvmap_debug.c @@ -297,7 +297,7 @@ static int nvmap_page_mapcount(struct page *page) } #define PSS_SHIFT 12 -static void nvmap_get_total_mss(u64 *pss, u64 *total, u32 heap_type, int numa_id) +static int nvmap_get_total_mss(u64 *pss, u64 *total, u32 heap_type, int numa_id) { int i; struct rb_node *n; @@ -307,7 +307,7 @@ static void nvmap_get_total_mss(u64 *pss, u64 *total, u32 heap_type, int numa_id if (pss) *pss = 0; if (dev == NULL) - return; + return 0; spin_lock(&dev->handle_lock); n = rb_first(&dev->handles); for (; n != NULL; n = rb_next(n)) { @@ -322,18 +322,28 @@ static void nvmap_get_total_mss(u64 *pss, u64 *total, u32 heap_type, int numa_id numa_id)) continue; - *total += h->size; + if (check_add_overflow(*total, (u64)h->size, &*total)) { + spin_unlock(&dev->handle_lock); + return -EOVERFLOW; + } + if (!pss) continue; for (i = 0; i < h->size >> PAGE_SHIFT; i++) { struct page *page = nvmap_to_page(h->pgalloc.pages[i]); - if (nvmap_page_mapcount(page) > 0) - *pss += PAGE_SIZE; + if (nvmap_page_mapcount(page) > 0) { + if (check_add_overflow(*pss, (u64)PAGE_SIZE, &*pss)) { + spin_unlock(&dev->handle_lock); + return -EOVERFLOW; + } + + } } } spin_unlock(&dev->handle_lock); + return 0; } static int nvmap_debug_allocations_show(struct seq_file *s, void *unused) @@ -365,7 +375,10 @@ static int nvmap_debug_allocations_show(struct seq_file *s, void *unused) seq_puts(s, "\n"); } mutex_unlock(&nvmap_dev->clients_lock); - nvmap_get_total_mss(NULL, &total, heap_type, numa_id); + err = nvmap_get_total_mss(NULL, &total, heap_type, numa_id); + if (err != 0) + return err; + seq_printf(s, "%-18s %-18s %8s %10lluK\n", "total", "", "", K(total)); return 0; } @@ -581,7 +594,10 @@ static int nvmap_debug_maps_show(struct seq_file *s, void *unused) } mutex_unlock(&nvmap_dev->clients_lock); - nvmap_get_total_mss(NULL, &total, heap_type, numa_id); + err = nvmap_get_total_mss(NULL, &total, heap_type, numa_id); + if (err != 0) + return err; + seq_printf(s, "%-18s %-18s %8s %10lluK\n", "total", "", "", K(total)); return 0; } @@ -612,7 +628,10 @@ static int nvmap_debug_clients_show(struct seq_file *s, void *unused) seq_printf(s, " %10lluK\n", K(client_total)); } mutex_unlock(&nvmap_dev->clients_lock); - nvmap_get_total_mss(NULL, &total, heap_type, numa_id); + err = nvmap_get_total_mss(NULL, &total, heap_type, numa_id); + if (err != 0) + return err; + seq_printf(s, "%-18s %18s %8s %10lluK\n", "total", "", "", K(total)); return 0; } @@ -833,7 +852,10 @@ static int nvmap_debug_iovmm_procrank_show(struct seq_file *s, void *unused) } mutex_unlock(&dev->clients_lock); - nvmap_get_total_mss(&total_pss, &total_memory, NVMAP_HEAP_IOVMM, NUMA_NO_NODE); + err = nvmap_get_total_mss(&total_pss, &total_memory, NVMAP_HEAP_IOVMM, NUMA_NO_NODE); + if (err != 0) + return err; + seq_printf(s, "%-18s %18s %8s %10lluK %10lluK\n", "total", "", "", K(total_pss), K(total_memory)); return 0;