Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp3342387pxj; Sun, 20 Jun 2021 18:14:33 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwuy2//EoPrTpe8xteMdsZiZ57a/L9ugx9Bou0XROFrQtgdKb3+Nr3qmjpHgC+0vRN52PRi X-Received: by 2002:a17:906:1c84:: with SMTP id g4mr21118606ejh.99.1624238073158; Sun, 20 Jun 2021 18:14:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1624238073; cv=none; d=google.com; s=arc-20160816; b=Cj18n8r3K2aprHmUlgTVsdlfMc519/4URYsTBqjCwqJnycBbOAZPPIKilhi3RXsKGV 6Oi1rnT7+hL8j4og/glJFkm+Y59P7uvOtOgHrOfIe9gRidXy5+cqXoEs16Wrz9ArUxQm rJUXQnPK773VIWqIeg+Y3EUJenojeNGHIS+v/miyx37qz7M5PVpiM/1cmggM8QFTb1Mk 8f36mFSenNWtMQnB/zAntkNW143BLVeIv5xFYAqfl1hH4gmo4aVta+V6JD9AY7kEdI5S K0oK3bEk0D7WAM2qkbyNU8YHCg60qWPjLeETpn9s9bTtkqIY9XVZSM2UCXn7opLCm63C Hb2g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:subject:cc:to:from; bh=9OaTNwl68a3MwSSHedmScXMyzb75cSHIRJPONpqj29Q=; b=JJiMiCIRqTEkRAcwqtaK4yztINUkY6DGWKb4Ws4EdUvxAPeathLRTlbXgzdk3RI6NH rf4ZvK98I343z/a2bhjdjh6UgK/EzeYRg72BU3R1XK2enMt6ASO03JaTI2nLkJ33U7Xi iPgiF+BtzbGXnMULN7SEUHb9jTNsV8b8DhM9RI5h2K5ZT7GO8hkATXgojW0ZpsAWOJQE VqPSETP0ye+RKzy3GU/SvpW3xMEsb0dVk5CB7Mob7udmqaEyoQ0uzu9RJ2cRACB6oyh7 3kRDsdfjd96q7CdNdC1E5+jqBdvN8c7PKS6whcrJJ+QeXVwFnUcuzDSqIfuMdZHZ4jVP YyEg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id h18si14388745edb.287.2021.06.20.18.13.56; Sun, 20 Jun 2021 18:14:33 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229946AbhFUBMt (ORCPT + 99 others); Sun, 20 Jun 2021 21:12:49 -0400 Received: from yyz.mikelr.com ([170.75.163.43]:34190 "EHLO yyz.mikelr.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229872AbhFUBMt (ORCPT ); Sun, 20 Jun 2021 21:12:49 -0400 X-Greylist: delayed 597 seconds by postgrey-1.27 at vger.kernel.org; Sun, 20 Jun 2021 21:12:49 EDT Received: from glidewell.ykf.mikelr.com (198-84-194-208.cpe.teksavvy.com [198.84.194.208]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client did not present a certificate) by yyz.mikelr.com (Postfix) with ESMTPSA id D6AD84F834; Sun, 20 Jun 2021 21:00:38 -0400 (EDT) From: Mikel Rychliski To: Alex Deucher , =?UTF-8?q?Christian=20K=C3=B6nig?= , "Pan, Xinhui" , David Airlie , Daniel Vetter , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Cc: Mikel Rychliski Subject: [PATCH] drm/radeon: Fix NULL dereference when updating memory stats Date: Sun, 20 Jun 2021 20:59:50 -0400 Message-Id: <20210621005950.24734-1-mikel@mikelr.com> X-Mailer: git-send-email 2.13.7 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org radeon_ttm_bo_destroy() is attempting to access the resource object to update memory counters. However, the resource object is already freed when ttm calls this function via the destroy callback. This causes an oops when a bo is freed: BUG: kernel NULL pointer dereference, address: 0000000000000010 RIP: 0010:radeon_ttm_bo_destroy+0x2c/0x100 [radeon] Call Trace: radeon_bo_unref+0x1a/0x30 [radeon] radeon_gem_object_free+0x33/0x50 [radeon] drm_gem_object_release_handle+0x69/0x70 [drm] drm_gem_handle_delete+0x62/0xa0 [drm] ? drm_mode_destroy_dumb+0x40/0x40 [drm] drm_ioctl_kernel+0xb2/0xf0 [drm] drm_ioctl+0x30a/0x3c0 [drm] ? drm_mode_destroy_dumb+0x40/0x40 [drm] radeon_drm_ioctl+0x49/0x80 [radeon] __x64_sys_ioctl+0x8e/0xd0 Avoid the issue by updating the counters in the delete_mem_notify callback instead. Also, fix memory statistic updating in radeon_bo_move() to identify the source type correctly. The source type needs to be saved before the move, because the moved from object may be altered by the move. Fixes: bfa3357ef9ab ("drm/ttm: allocate resource object instead of embedding it v2") Signed-off-by: Mikel Rychliski --- drivers/gpu/drm/radeon/radeon_object.c | 23 +++-------------------- drivers/gpu/drm/radeon/radeon_object.h | 7 ++++--- drivers/gpu/drm/radeon/radeon_ttm.c | 20 +++++++++++++++++--- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index bfaaa3c969a3..ea34c0661710 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -49,8 +49,8 @@ static void radeon_bo_clear_surface_reg(struct radeon_bo *bo); * function are calling it. */ -static void radeon_update_memory_usage(struct radeon_bo *bo, - unsigned mem_type, int sign) +void radeon_update_memory_usage(struct radeon_bo *bo, + unsigned int mem_type, int sign) { struct radeon_device *rdev = bo->rdev; @@ -76,8 +76,6 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) bo = container_of(tbo, struct radeon_bo, tbo); - radeon_update_memory_usage(bo, bo->tbo.resource->mem_type, -1); - mutex_lock(&bo->rdev->gem.mutex); list_del_init(&bo->list); mutex_unlock(&bo->rdev->gem.mutex); @@ -726,25 +724,10 @@ int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, return radeon_bo_get_surface_reg(bo); } -void radeon_bo_move_notify(struct ttm_buffer_object *bo, - bool evict, - struct ttm_resource *new_mem) +void radeon_bo_move_notify(struct radeon_bo *rbo) { - struct radeon_bo *rbo; - - if (!radeon_ttm_bo_is_radeon_bo(bo)) - return; - - rbo = container_of(bo, struct radeon_bo, tbo); radeon_bo_check_tiling(rbo, 0, 1); radeon_vm_bo_invalidate(rbo->rdev, rbo); - - /* update statistics */ - if (!new_mem) - return; - - radeon_update_memory_usage(rbo, bo->resource->mem_type, -1); - radeon_update_memory_usage(rbo, new_mem->mem_type, 1); } vm_fault_t radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 1739c6a142cd..f97a17cce28b 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -133,6 +133,9 @@ static inline u64 radeon_bo_mmap_offset(struct radeon_bo *bo) return drm_vma_node_offset_addr(&bo->tbo.base.vma_node); } +extern void radeon_update_memory_usage(struct radeon_bo *bo, + unsigned int mem_type, int sign); + extern int radeon_bo_create(struct radeon_device *rdev, unsigned long size, int byte_align, bool kernel, u32 domain, u32 flags, @@ -160,9 +163,7 @@ extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo, u32 *tiling_flags, u32 *pitch); extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, bool force_drop); -extern void radeon_bo_move_notify(struct ttm_buffer_object *bo, - bool evict, - struct ttm_resource *new_mem); +extern void radeon_bo_move_notify(struct radeon_bo *rbo); extern vm_fault_t radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); extern int radeon_bo_get_surface_reg(struct radeon_bo *bo); extern void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence, diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index ad2a5a791bba..c318a80853e5 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -199,7 +199,7 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, struct ttm_resource *old_mem = bo->resource; struct radeon_device *rdev; struct radeon_bo *rbo; - int r; + int r, old_type; if (new_mem->mem_type == TTM_PL_TT) { r = radeon_ttm_tt_bind(bo->bdev, bo->ttm, new_mem); @@ -216,6 +216,9 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, if (WARN_ON_ONCE(rbo->tbo.pin_count > 0)) return -EINVAL; + /* Save old type for statistics update */ + old_type = old_mem->mem_type; + rdev = radeon_get_rdev(bo->bdev); if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { ttm_bo_move_null(bo, new_mem); @@ -261,7 +264,9 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, out: /* update statistics */ atomic64_add(bo->base.size, &rdev->num_bytes_moved); - radeon_bo_move_notify(bo, evict, new_mem); + radeon_update_memory_usage(rbo, old_type, -1); + radeon_update_memory_usage(rbo, new_mem->mem_type, 1); + radeon_bo_move_notify(rbo); return 0; } @@ -682,7 +687,16 @@ bool radeon_ttm_tt_is_readonly(struct radeon_device *rdev, static void radeon_bo_delete_mem_notify(struct ttm_buffer_object *bo) { - radeon_bo_move_notify(bo, false, NULL); + struct radeon_bo *rbo; + + if (!radeon_ttm_bo_is_radeon_bo(bo)) + return; + + rbo = container_of(bo, struct radeon_bo, tbo); + + if (bo->resource) + radeon_update_memory_usage(rbo, bo->resource->mem_type, -1); + radeon_bo_move_notify(rbo); } static struct ttm_device_funcs radeon_bo_driver = { -- 2.13.7