From nobody Wed Sep 17 11:59:58 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 22AEAC4332F for ; Mon, 19 Dec 2022 14:01:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231980AbiLSOBo (ORCPT ); Mon, 19 Dec 2022 09:01:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51376 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231890AbiLSOBl (ORCPT ); Mon, 19 Dec 2022 09:01:41 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 77CDBDEFB for ; Mon, 19 Dec 2022 06:01:40 -0800 (PST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 2A14AFEC; Mon, 19 Dec 2022 06:02:21 -0800 (PST) Received: from e112269-lin.cambridge.arm.com (unknown [10.1.194.34]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 10BA93F71A; Mon, 19 Dec 2022 06:01:38 -0800 (PST) From: Steven Price To: Rob Herring , Tomeu Vizoso , Alyssa Rosenzweig Cc: Steven Price , Daniel Vetter , David Airlie , Rob Clark , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCH] drm/panfrost: Fix GEM handle creation ref-counting Date: Mon, 19 Dec 2022 14:01:30 +0000 Message-Id: <20221219140130.410578-1-steven.price@arm.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" panfrost_gem_create_with_handle() previously returned a BO but with the only reference being from the handle, which user space could in theory guess and release, causing a use-after-free. Additionally if the call to panfrost_gem_mapping_get() in panfrost_ioctl_create_bo() failed then a(nother) reference on the BO was dropped. The _create_with_handle() is a problematic pattern, so ditch it and instead create the handle in panfrost_ioctl_create_bo(). If the call to panfrost_gem_mapping_get() fails then this means that user space has indeed gone behind our back and freed the handle. In which case just return an error code. Reported-by: Rob Clark Fixes: f3ba91228e8e ("drm/panfrost: Add initial panfrost driver") Signed-off-by: Steven Price Reviewed-by: Rob Clark --- drivers/gpu/drm/panfrost/panfrost_drv.c | 27 ++++++++++++++++--------- drivers/gpu/drm/panfrost/panfrost_gem.c | 16 +-------------- drivers/gpu/drm/panfrost/panfrost_gem.h | 5 +---- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panf= rost/panfrost_drv.c index fa619fe72086..abb0dadd8f63 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -82,6 +82,7 @@ static int panfrost_ioctl_create_bo(struct drm_device *de= v, void *data, struct panfrost_gem_object *bo; struct drm_panfrost_create_bo *args =3D data; struct panfrost_gem_mapping *mapping; + int ret; =20 if (!args->size || args->pad || (args->flags & ~(PANFROST_BO_NOEXEC | PANFROST_BO_HEAP))) @@ -92,21 +93,29 @@ static int panfrost_ioctl_create_bo(struct drm_device *= dev, void *data, !(args->flags & PANFROST_BO_NOEXEC)) return -EINVAL; =20 - bo =3D panfrost_gem_create_with_handle(file, dev, args->size, args->flags, - &args->handle); + bo =3D panfrost_gem_create(dev, args->size, args->flags); if (IS_ERR(bo)) return PTR_ERR(bo); =20 + ret =3D drm_gem_handle_create(file, &bo->base.base, &args->handle); + if (ret) + goto out; + mapping =3D panfrost_gem_mapping_get(bo, priv); - if (!mapping) { - drm_gem_object_put(&bo->base.base); - return -EINVAL; + if (mapping) { + args->offset =3D mapping->mmnode.start << PAGE_SHIFT; + panfrost_gem_mapping_put(mapping); + } else { + /* This can only happen if the handle from + * drm_gem_handle_create() has already been guessed and freed + * by user space + */ + ret =3D -EINVAL; } =20 - args->offset =3D mapping->mmnode.start << PAGE_SHIFT; - panfrost_gem_mapping_put(mapping); - - return 0; +out: + drm_gem_object_put(&bo->base.base); + return ret; } =20 /** diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panf= rost/panfrost_gem.c index 293e799e2fe8..3c812fbd126f 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -235,12 +235,8 @@ struct drm_gem_object *panfrost_gem_create_object(stru= ct drm_device *dev, size_t } =20 struct panfrost_gem_object * -panfrost_gem_create_with_handle(struct drm_file *file_priv, - struct drm_device *dev, size_t size, - u32 flags, - uint32_t *handle) +panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags) { - int ret; struct drm_gem_shmem_object *shmem; struct panfrost_gem_object *bo; =20 @@ -256,16 +252,6 @@ panfrost_gem_create_with_handle(struct drm_file *file_= priv, bo->noexec =3D !!(flags & PANFROST_BO_NOEXEC); bo->is_heap =3D !!(flags & PANFROST_BO_HEAP); =20 - /* - * Allocate an id of idr table where the obj is registered - * and handle has the id what user can see. - */ - ret =3D drm_gem_handle_create(file_priv, &shmem->base, handle); - /* drop reference from allocate - handle holds it now. */ - drm_gem_object_put(&shmem->base); - if (ret) - return ERR_PTR(ret); - return bo; } =20 diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.h b/drivers/gpu/drm/panf= rost/panfrost_gem.h index 8088d5fd8480..ad2877eeeccd 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.h +++ b/drivers/gpu/drm/panfrost/panfrost_gem.h @@ -69,10 +69,7 @@ panfrost_gem_prime_import_sg_table(struct drm_device *de= v, struct sg_table *sgt); =20 struct panfrost_gem_object * -panfrost_gem_create_with_handle(struct drm_file *file_priv, - struct drm_device *dev, size_t size, - u32 flags, - uint32_t *handle); +panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags); =20 int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_pr= iv); void panfrost_gem_close(struct drm_gem_object *obj, --=20 2.34.1