diff options
author | Joshua Bakita <jbakita@cs.unc.edu> | 2024-04-09 17:19:01 -0400 |
---|---|---|
committer | Joshua Bakita <jbakita@cs.unc.edu> | 2024-04-09 17:19:01 -0400 |
commit | 5ea953292441e31e37ae074e48d8b3b5ce1d9440 (patch) | |
tree | 9fe4d01b480fe38be09483d4b332840e7f09f0b5 | |
parent | 664251e57c998ac97b66e8fc1dca1cb1b38a0c1e (diff) |
Correctly check return code from vram2PRAMIN()
Blindly using an invalid return address was resulting in undefined
behavior due to traversal of non-page-table addresses as though they
were part of the page table.
-rw-r--r-- | mmu.c | 17 | ||||
-rw-r--r-- | nvdebug.h | 1 |
2 files changed, 12 insertions, 6 deletions
@@ -15,11 +15,12 @@ | |||
15 | 15 | ||
16 | /* Convert a physical VRAM address to an offset in the PRAMIN window | 16 | /* Convert a physical VRAM address to an offset in the PRAMIN window |
17 | @param addr VRAM address to convert | 17 | @param addr VRAM address to convert |
18 | @return 0 on error, PRAMIN offset on success | 18 | @return -errno on error, PRAMIN offset on success |
19 | 19 | ||
20 | Note: Use off2PRAMIN() instead if you want a dereferenceable address | 20 | Note: Use off2PRAMIN() instead if you want a dereferenceable address |
21 | Note: PRAMIN window is only 1MB, so returning an int is safe | ||
21 | */ | 22 | */ |
22 | uint32_t vram2PRAMIN(struct nvdebug_state *g, uint64_t addr) { | 23 | static int vram2PRAMIN(struct nvdebug_state *g, uint64_t addr) { |
23 | uint64_t pramin_base_va; | 24 | uint64_t pramin_base_va; |
24 | bar0_window_t window; | 25 | bar0_window_t window; |
25 | window.raw = nvdebug_readl(g, NV_PBUS_BAR0_WINDOW); | 26 | window.raw = nvdebug_readl(g, NV_PBUS_BAR0_WINDOW); |
@@ -27,20 +28,26 @@ uint32_t vram2PRAMIN(struct nvdebug_state *g, uint64_t addr) { | |||
27 | if (addr & ~0x0001ffffffffffff) { | 28 | if (addr & ~0x0001ffffffffffff) { |
28 | printk(KERN_ERR "[nvdebug] Invalid address %llx passed to %s!\n", | 29 | printk(KERN_ERR "[nvdebug] Invalid address %llx passed to %s!\n", |
29 | addr, __func__); | 30 | addr, __func__); |
30 | return 0; | 31 | return -EINVAL; |
31 | } | 32 | } |
32 | // For unclear (debugging?) reasons, PRAMIN can point to SYSMEM | 33 | // For unclear (debugging?) reasons, PRAMIN can point to SYSMEM |
33 | if (window.target != TARGET_VID_MEM) | 34 | if (window.target != TARGET_VID_MEM) |
34 | return 0; | 35 | return -EFAULT; |
35 | pramin_base_va = ((uint64_t)window.base) << 16; | 36 | pramin_base_va = ((uint64_t)window.base) << 16; |
36 | // Protect against out-of-bounds accesses | 37 | // Protect against out-of-bounds accesses |
37 | if (addr < pramin_base_va || addr > pramin_base_va + NV_PRAMIN_LEN) | 38 | if (addr < pramin_base_va || addr > pramin_base_va + NV_PRAMIN_LEN) |
38 | return 0; | 39 | return -ERANGE; |
39 | return addr - pramin_base_va; | 40 | return addr - pramin_base_va; |
40 | } | 41 | } |
41 | 42 | ||
42 | // Convert a GPU physical address to CPU virtual address via the PRAMIN window | 43 | // Convert a GPU physical address to CPU virtual address via the PRAMIN window |
44 | // @return A dereferencable address, or 0 (an invalid physical address) on err | ||
43 | void __iomem *phy2PRAMIN(struct nvdebug_state* g, uint64_t phy) { | 45 | void __iomem *phy2PRAMIN(struct nvdebug_state* g, uint64_t phy) { |
46 | int off = vram2PRAMIN(g, phy); | ||
47 | if (off == -ERANGE) | ||
48 | printk(KERN_ERR "[nvdebug] Page table walk off end of PRAMIN!\n"); | ||
49 | if (off < 0) | ||
50 | return 0; | ||
44 | return g->regs + NV_PRAMIN + vram2PRAMIN(g, phy); | 51 | return g->regs + NV_PRAMIN + vram2PRAMIN(g, phy); |
45 | } | 52 | } |
46 | 53 | ||
@@ -1149,7 +1149,6 @@ int preempt_tsg(struct nvdebug_state *g, uint32_t tsg_id); | |||
1149 | int preempt_runlist(struct nvdebug_state *g, uint32_t rl_id); | 1149 | int preempt_runlist(struct nvdebug_state *g, uint32_t rl_id); |
1150 | 1150 | ||
1151 | // Defined in mmu.c | 1151 | // Defined in mmu.c |
1152 | uint32_t vram2PRAMIN(struct nvdebug_state *g, uint64_t addr); | ||
1153 | void __iomem *phy2PRAMIN(struct nvdebug_state* g, uint64_t phy); | 1152 | void __iomem *phy2PRAMIN(struct nvdebug_state* g, uint64_t phy); |
1154 | uint64_t search_page_directory( | 1153 | uint64_t search_page_directory( |
1155 | struct nvdebug_state *g, | 1154 | struct nvdebug_state *g, |