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 <surbhis@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3270465
Reviewed-by: Ajay Nandakumar Mannargudi <anandakumarm@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Surbhi Singh
2024-12-06 09:36:34 +00:00
committed by Jon Hunter
parent bb80a707cd
commit b1af9a0347
2 changed files with 36 additions and 11 deletions

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 * 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 */ /* carveout - explicitly map the pfns into a vmalloc area */
adj_size = nvmap_get_heap_block_base(h->carveout) & ~PAGE_MASK; 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); adj_size = PAGE_ALIGN(adj_size);
if (pfn_valid(__phys_to_pfn(nvmap_get_heap_block_base(h->carveout) & PAGE_MASK))) { 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: out:
if (pages) if (pages)
vfree(pages); vfree(pages);
dec_kmaps:
nvmap_kmaps_dec(h); nvmap_kmaps_dec(h);
put_handle: put_handle:
nvmap_handle_put(h); nvmap_handle_put(h);

View File

@@ -297,7 +297,7 @@ static int nvmap_page_mapcount(struct page *page)
} }
#define PSS_SHIFT 12 #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; int i;
struct rb_node *n; 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) if (pss)
*pss = 0; *pss = 0;
if (dev == NULL) if (dev == NULL)
return; return 0;
spin_lock(&dev->handle_lock); spin_lock(&dev->handle_lock);
n = rb_first(&dev->handles); n = rb_first(&dev->handles);
for (; n != NULL; n = rb_next(n)) { 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)) numa_id))
continue; continue;
*total += h->size; if (check_add_overflow(*total, (u64)h->size, &*total)) {
spin_unlock(&dev->handle_lock);
return -EOVERFLOW;
}
if (!pss) if (!pss)
continue; continue;
for (i = 0; i < h->size >> PAGE_SHIFT; i++) { for (i = 0; i < h->size >> PAGE_SHIFT; i++) {
struct page *page = nvmap_to_page(h->pgalloc.pages[i]); struct page *page = nvmap_to_page(h->pgalloc.pages[i]);
if (nvmap_page_mapcount(page) > 0) if (nvmap_page_mapcount(page) > 0) {
*pss += PAGE_SIZE; if (check_add_overflow(*pss, (u64)PAGE_SIZE, &*pss)) {
spin_unlock(&dev->handle_lock);
return -EOVERFLOW;
}
}
} }
} }
spin_unlock(&dev->handle_lock); spin_unlock(&dev->handle_lock);
return 0;
} }
static int nvmap_debug_allocations_show(struct seq_file *s, void *unused) 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"); seq_puts(s, "\n");
} }
mutex_unlock(&nvmap_dev->clients_lock); 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)); seq_printf(s, "%-18s %-18s %8s %10lluK\n", "total", "", "", K(total));
return 0; return 0;
} }
@@ -581,7 +594,10 @@ static int nvmap_debug_maps_show(struct seq_file *s, void *unused)
} }
mutex_unlock(&nvmap_dev->clients_lock); 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)); seq_printf(s, "%-18s %-18s %8s %10lluK\n", "total", "", "", K(total));
return 0; 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)); seq_printf(s, " %10lluK\n", K(client_total));
} }
mutex_unlock(&nvmap_dev->clients_lock); 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)); seq_printf(s, "%-18s %18s %8s %10lluK\n", "total", "", "", K(total));
return 0; return 0;
} }
@@ -833,7 +852,10 @@ static int nvmap_debug_iovmm_procrank_show(struct seq_file *s, void *unused)
} }
mutex_unlock(&dev->clients_lock); 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", seq_printf(s, "%-18s %18s %8s %10lluK %10lluK\n",
"total", "", "", K(total_pss), K(total_memory)); "total", "", "", K(total_pss), K(total_memory));
return 0; return 0;