From patchwork Thu Jan 2 19:44:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 13924908 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EE362E7719B for ; Thu, 2 Jan 2025 19:44:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6A99210E7A9; Thu, 2 Jan 2025 19:44:36 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=igalia.com header.i=@igalia.com header.b="LO1x9qPk"; dkim-atps=neutral Received: from fanzine2.igalia.com (fanzine.igalia.com [178.60.130.6]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5389510E7A6 for ; Thu, 2 Jan 2025 19:44:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=5f6D1vv/u9l+w15jx30lwYkeuaE8ITnALXkWRGgl4q8=; b=LO1x9qPkFdovgvyFUxqG+f46iT 5+ukpRwQlRgmEm0hOOZ2pU0uppB28QjGB+oPie8BhFrwNlEy0WboxbUJdCCcc+R+Zgqax2Nhgb4RT yOfxQbmPC72sob7RL2dF6nVYt0UC1/8GKLjPgOGt/fQs7u6haQkTtPEoHSYn9jyYjrnqSVxluvmhu CpynEQiXbjrOzQtU3jzQF8ighGet9ecAXzhv/W+tcOr4JF15FRXEFGO+XD5rDeUev/7w/+1z0s69w 7qhRQJkI7zYjR6v+WujfLY3OucL/GellYNectnZcwJHG9kmQ7xKGtg/9OZIf/GEzT5EpiXcsm03JQ tg+9TNZw==; Received: from [90.241.98.187] (helo=localhost) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1tTR7R-00Au7j-LH; Thu, 02 Jan 2025 20:44:33 +0100 From: Tvrtko Ursulin To: dri-devel@lists.freedesktop.org Cc: kernel-dev@igalia.com, Tvrtko Ursulin Subject: [PATCH 6/6] drm/syncobj: Avoid temporary allocation in drm_syncobj_timeline_signal_ioctl Date: Thu, 2 Jan 2025 19:44:17 +0000 Message-ID: <20250102194418.70383-7-tursulin@igalia.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250102194418.70383-1-tursulin@igalia.com> References: <20250102194418.70383-1-tursulin@igalia.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Tvrtko Ursulin We can avoid one of the two temporary allocations if we read the userspace supplied timeline points as we go along. The only new complication is to unwind unused fence chains on the error path, but even that code was already present in the function. Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/drm_syncobj.c | 46 +++++++++++++++-------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index d8756763f517..b358fd1d3df3 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -1555,10 +1555,10 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private) { struct drm_syncobj_timeline_array *args = data; + uint64_t __user *points = u64_to_user_ptr(args->points); + uint32_t i, j, count = args->count_handles; struct drm_syncobj **syncobjs; struct dma_fence_chain **chains; - uint64_t *points; - uint32_t i, j; int ret; if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) @@ -1570,33 +1570,22 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, if (args->count_handles == 0) return -EINVAL; + if (!access_ok(points, count * sizeof(*points))) + return -EFAULT; + ret = drm_syncobj_array_find(file_private, u64_to_user_ptr(args->handles), - args->count_handles, + count, &syncobjs); if (ret < 0) return ret; - points = kmalloc_array(args->count_handles, sizeof(*points), - GFP_KERNEL); - if (!points) { - ret = -ENOMEM; - goto out; - } - if (!u64_to_user_ptr(args->points)) { - memset(points, 0, args->count_handles * sizeof(uint64_t)); - } else if (copy_from_user(points, u64_to_user_ptr(args->points), - sizeof(uint64_t) * args->count_handles)) { - ret = -EFAULT; - goto err_points; - } - - chains = kmalloc_array(args->count_handles, sizeof(void *), GFP_KERNEL); + chains = kmalloc_array(count, sizeof(void *), GFP_KERNEL); if (!chains) { ret = -ENOMEM; - goto err_points; + goto out; } - for (i = 0; i < args->count_handles; i++) { + for (i = 0; i < count; i++) { chains[i] = dma_fence_chain_alloc(); if (!chains[i]) { for (j = 0; j < i; j++) @@ -1606,19 +1595,24 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, } } - for (i = 0; i < args->count_handles; i++) { + for (i = 0; i < count; i++) { struct dma_fence *fence = dma_fence_get_stub(); + u64 point = 0; - drm_syncobj_add_point(syncobjs[i], chains[i], - fence, points[i]); + if (points && get_user(point, points++)) { + ret = -EFAULT; + for (j = i; j < count; j++) + dma_fence_chain_free(chains[j]); + goto err_chains; + } + + drm_syncobj_add_point(syncobjs[i], chains[i], fence, point); dma_fence_put(fence); } err_chains: kfree(chains); -err_points: - kfree(points); out: - drm_syncobj_array_free(syncobjs, args->count_handles); + drm_syncobj_array_free(syncobjs, count); return ret; }