]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
accel/amdxdna: Fix potential NULL pointer dereference of abo->client
authorLizhi Hou <lizhi.hou@amd.com>
Tue, 7 Jul 2026 20:15:56 +0000 (13:15 -0700)
committerLizhi Hou <lizhi.hou@amd.com>
Wed, 8 Jul 2026 03:49:28 +0000 (20:49 -0700)
Closing a BO handle clears abo->client, while the underlying GEM object
may remain alive due to internal kernel references. As a result, code
executed after the BO handle is closed may dereference a NULL abo->client
pointer.

Remove accesses to abo->client from code paths that may execute after the
BO handle has been closed.

Fixes: d76856beb4a4 ("accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval")
Reviewed-by: Max Zhen <max.zhen@amd.com>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://patch.msgid.link/20260707201556.562191-1-lizhi.hou@amd.com
drivers/accel/amdxdna/aie2_message.c
drivers/accel/amdxdna/amdxdna_gem.c
drivers/accel/amdxdna/amdxdna_gem.h

index c4b364801cc0456a153e15e26ef413e7f0f39303..dfe0fbdf066d2c6b00c6d4e01e54706c32d4af97 100644 (file)
@@ -840,7 +840,7 @@ static struct aie2_exec_msg_ops npu_exec_message_ops = {
 static int aie2_init_exec_req(void *req, struct amdxdna_gem_obj *cmd_abo,
                              size_t *size, u32 *msg_op)
 {
-       struct amdxdna_dev *xdna = cmd_abo->client->xdna;
+       struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
        int ret;
        u32 op;
 
@@ -874,7 +874,7 @@ static int
 aie2_cmdlist_fill_slot(void *slot, struct amdxdna_gem_obj *cmd_abo,
                       size_t *size, u32 *cmd_op)
 {
-       struct amdxdna_dev *xdna = cmd_abo->client->xdna;
+       struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
        int ret;
        u32 op;
 
index 1275f91ca7050866afa514a418c6427c3c95c9da..4628a27872656fae56241d889d3074bda0a51a44 100644 (file)
@@ -198,6 +198,7 @@ amdxdna_gem_destroy_obj(struct amdxdna_gem_obj *abo)
  */
 void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
 {
+       struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
        struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
        int ret;
 
@@ -210,7 +211,7 @@ void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
        if (!abo->mem.kva) {
                ret = drm_gem_vmap(to_gobj(abo), &map);
                if (ret)
-                       XDNA_ERR(abo->client->xdna, "Vmap bo failed, ret %d", ret);
+                       XDNA_ERR(xdna, "Vmap bo failed, ret %d", ret);
                else
                        abo->mem.kva = map.vaddr;
        }
@@ -354,7 +355,13 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
        unsigned long nr_pages;
        int ret;
 
-       if (!amdxdna_pasid_on(abo->client)) {
+       /*
+        * When PASID is off, amdxdna_gem_obj_open() called amdxdna_dma_map_bo()
+        * and mem.dma_addr is valid; use the DMA address directly and skip HMM.
+        * Avoid dereferencing abo->client which may be NULL (cleared in close())
+        * while internal kernel references are still held.
+        */
+       if (abo->mem.dma_addr != AMDXDNA_INVALID_ADDR) {
                /* Need to set uva for heap uva validation */
                abo->mem.uva = addr;
                return 0;
index a35d2f15d32c79ad07960d970007cb6602a96459..1e90e32bf3cd79d952c035fd44a83d84779ea2d0 100644 (file)
@@ -88,12 +88,19 @@ u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo);
 
 static inline u64 amdxdna_dev_bo_offset(struct amdxdna_gem_obj *abo)
 {
-       return amdxdna_gem_dev_addr(abo) - abo->client->xdna->dev_info->dev_mem_base;
+       return amdxdna_gem_dev_addr(abo) - to_xdna_dev(to_gobj(abo)->dev)->dev_info->dev_mem_base;
 }
 
 static inline u64 amdxdna_obj_dma_addr(struct amdxdna_gem_obj *abo)
 {
-       return amdxdna_pasid_on(abo->client) ? amdxdna_gem_uva(abo) : abo->mem.dma_addr;
+       /*
+        * amdxdna_gem_obj_open() calls amdxdna_dma_map_bo() only when PASID is
+        * off, leaving mem.dma_addr at AMDXDNA_INVALID_ADDR when PASID is on.
+        * Avoid dereferencing abo->client, which is cleared to NULL by
+        * amdxdna_gem_obj_close() while internal kernel references remain.
+        */
+       return (abo->mem.dma_addr != AMDXDNA_INVALID_ADDR) ?
+               abo->mem.dma_addr : amdxdna_gem_uva(abo);
 }
 
 void amdxdna_umap_put(struct amdxdna_umap *mapp);