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, |
