From nobody Tue Jun 30 03:34:12 2026 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 894FBC433F5 for ; Thu, 27 Jan 2022 18:09:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245094AbiA0SJh (ORCPT ); Thu, 27 Jan 2022 13:09:37 -0500 Received: from ams.source.kernel.org ([145.40.68.75]:58670 "EHLO ams.source.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234646AbiA0SJR (ORCPT ); Thu, 27 Jan 2022 13:09:17 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id B3FFAB820C4; Thu, 27 Jan 2022 18:09:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C8457C340E4; Thu, 27 Jan 2022 18:09:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1643306954; bh=3l5jVY4LoNQVrXUWco9W8SiC2E6sUDrQ4Xhb9Ba0SC8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a11it+U2sE4LuLNOEET/gOpupi5CRo3aIj73GP1X7PUgHdl2hVn0InL/wZCww+HFj 9gteZ+L7yFw+f0sflQbXjlkbQuYUlTxlqIdxHxkUfNT/My4Sg+4ZR4qjdRhAMgXTBU zpxmhnPJ8QGPzqm/AjVTRj/ZvaDlkPr5Rml5E8aU= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Tvrtko Ursulin , Sushma Venkatesh Reddy , Daniel Vetter , Dave Airlie , Jon Bloomfield , Joonas Lahtinen , Jani Nikula , Linus Torvalds Subject: [PATCH 4.14 1/2] drm/i915: Flush TLBs before releasing backing store Date: Thu, 27 Jan 2022 19:08:56 +0100 Message-Id: <20220127180256.811271517@linuxfoundation.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220127180256.764665162@linuxfoundation.org> References: <20220127180256.764665162@linuxfoundation.org> User-Agent: quilt/0.66 X-stable: review X-Patchwork-Hint: ignore 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" From: Tvrtko Ursulin commit 7938d61591d33394a21bdd7797a245b65428f44c upstream. We need to flush TLBs before releasing backing store otherwise userspace is able to encounter stale entries if a) it is not declaring access to certain buffers and b) it races with the backing store release from a such undeclared execution already executing on the GPU in parallel. The approach taken is to mark any buffer objects which were ever bound to the GPU and to trigger a serialized TLB flush when their backing store is released. Alternatively the flushing could be done on VMA unbind, at which point we would be able to ascertain whether there is potential a parallel GPU execution (which could race), but essentially it boils down to paying the cost of TLB flushes potentially needlessly at VMA unbind time (when the backing store is not known to be going away so not needed for safety), versus potentially needlessly at backing store relase time (since we at that point cannot tell whether there is anything executing on the GPU which uses that object). Thereforce simplicity of implementation has been chosen for now with scope to benchmark and refine later as required. Signed-off-by: Tvrtko Ursulin Reported-by: Sushma Venkatesh Reddy Reviewed-by: Daniel Vetter Acked-by: Dave Airlie Cc: Daniel Vetter Cc: Jon Bloomfield Cc: Joonas Lahtinen Cc: Jani Nikula Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Tested-by: Guenter Roeck Tested-by: Linux Kernel Functional Testing --- drivers/gpu/drm/i915/i915_drv.h | 2=20 drivers/gpu/drm/i915/i915_gem.c | 84 ++++++++++++++++++++++++++++= ++++- drivers/gpu/drm/i915/i915_gem_object.h | 1=20 drivers/gpu/drm/i915/i915_reg.h | 6 ++ drivers/gpu/drm/i915/i915_vma.c | 4 + 5 files changed, 96 insertions(+), 1 deletion(-) --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2166,6 +2166,8 @@ struct drm_i915_private { =20 struct intel_uncore uncore; =20 + struct mutex tlb_invalidate_lock; + struct i915_virtual_gpu vgpu; =20 struct intel_gvt *gvt; --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2220,6 +2220,76 @@ static void __i915_gem_object_reset_page rcu_read_unlock(); } =20 +struct reg_and_bit { + i915_reg_t reg; + u32 bit; +}; + +static struct reg_and_bit +get_reg_and_bit(const struct intel_engine_cs *engine, + const i915_reg_t *regs, const unsigned int num) +{ + const unsigned int class =3D engine->class; + struct reg_and_bit rb =3D { .bit =3D 1 }; + + if (WARN_ON_ONCE(class >=3D num || !regs[class].reg)) + return rb; + + rb.reg =3D regs[class]; + if (class =3D=3D VIDEO_DECODE_CLASS) + rb.reg.reg +=3D 4 * engine->instance; /* GEN8_M2TCR */ + + return rb; +} + +static void invalidate_tlbs(struct drm_i915_private *dev_priv) +{ + static const i915_reg_t gen8_regs[] =3D { + [RENDER_CLASS] =3D GEN8_RTCR, + [VIDEO_DECODE_CLASS] =3D GEN8_M1TCR, /* , GEN8_M2TCR */ + [VIDEO_ENHANCEMENT_CLASS] =3D GEN8_VTCR, + [COPY_ENGINE_CLASS] =3D GEN8_BTCR, + }; + const unsigned int num =3D ARRAY_SIZE(gen8_regs); + const i915_reg_t *regs =3D gen8_regs; + struct intel_engine_cs *engine; + enum intel_engine_id id; + + if (INTEL_GEN(dev_priv) < 8) + return; + + assert_rpm_wakelock_held(dev_priv); + + mutex_lock(&dev_priv->tlb_invalidate_lock); + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + + for_each_engine(engine, dev_priv, id) { + /* + * HW architecture suggest typical invalidation time at 40us, + * with pessimistic cases up to 100us and a recommendation to + * cap at 1ms. We go a bit higher just in case. + */ + const unsigned int timeout_us =3D 100; + const unsigned int timeout_ms =3D 4; + struct reg_and_bit rb; + + rb =3D get_reg_and_bit(engine, regs, num); + if (!i915_mmio_reg_offset(rb.reg)) + continue; + + I915_WRITE_FW(rb.reg, rb.bit); + if (__intel_wait_for_register_fw(dev_priv, + rb.reg, rb.bit, 0, + timeout_us, timeout_ms, + NULL)) + DRM_ERROR_RATELIMITED("%s TLB invalidation did not complete in %ums!\n", + engine->name, timeout_ms); + } + + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + mutex_unlock(&dev_priv->tlb_invalidate_lock); +} + void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj, enum i915_mm_subclass subclass) { @@ -2257,8 +2327,18 @@ void __i915_gem_object_put_pages(struct =20 __i915_gem_object_reset_page_iter(obj); =20 - if (!IS_ERR(pages)) + if (!IS_ERR(pages)) { + if (test_and_clear_bit(I915_BO_WAS_BOUND_BIT, &obj->flags)) { + struct drm_i915_private *i915 =3D to_i915(obj->base.dev); + + if (intel_runtime_pm_get_if_in_use(i915)) { + invalidate_tlbs(i915); + intel_runtime_pm_put(i915); + } + } + obj->ops->put_pages(obj, pages); + } =20 unlock: mutex_unlock(&obj->mm.lock); @@ -4972,6 +5052,8 @@ i915_gem_load_init(struct drm_i915_priva =20 spin_lock_init(&dev_priv->fb_tracking.lock); =20 + mutex_init(&dev_priv->tlb_invalidate_lock); + return 0; =20 err_priorities: --- a/drivers/gpu/drm/i915/i915_gem_object.h +++ b/drivers/gpu/drm/i915/i915_gem_object.h @@ -135,6 +135,7 @@ struct drm_i915_gem_object { * activity? */ #define I915_BO_ACTIVE_REF 0 +#define I915_BO_WAS_BOUND_BIT 1 =20 /* * Is the object to be mapped as read-only to the GPU --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2380,6 +2380,12 @@ enum i915_power_well_id { #define GAMT_CHKN_BIT_REG _MMIO(0x4ab8) #define GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING (1<<28) =20 +#define GEN8_RTCR _MMIO(0x4260) +#define GEN8_M1TCR _MMIO(0x4264) +#define GEN8_M2TCR _MMIO(0x4268) +#define GEN8_BTCR _MMIO(0x426c) +#define GEN8_VTCR _MMIO(0x4270) + #if 0 #define PRB0_TAIL _MMIO(0x2030) #define PRB0_HEAD _MMIO(0x2034) --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -272,6 +272,10 @@ int i915_vma_bind(struct i915_vma *vma, return ret; =20 vma->flags |=3D bind_flags; + + if (vma->obj) + set_bit(I915_BO_WAS_BOUND_BIT, &vma->obj->flags); + return 0; } =20 From nobody Tue Jun 30 03:34:12 2026 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 4DC8EC433EF for ; Thu, 27 Jan 2022 18:09:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245144AbiA0SJx (ORCPT ); Thu, 27 Jan 2022 13:09:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45226 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244954AbiA0SJV (ORCPT ); Thu, 27 Jan 2022 13:09:21 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B1159C061749; Thu, 27 Jan 2022 10:09:21 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 5022361CCC; Thu, 27 Jan 2022 18:09:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 20C97C340E4; Thu, 27 Jan 2022 18:09:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1643306960; bh=VuaJ6H6GECXK5poI6DDZmDBQRVosGj++isu1R4XXBLY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=wj/925qmaLtKpQ8zBXeijw+usSuRp/Z9vec6uxOOLABw59iSygOrqlmjlThICrcrp h8+dvSIXynKVXYXgaPS+OnqDd1qpNcVVs8CqRXApM5WpuwrLHTor+60ymWWJZadZc3 umHip1YtqvnP/1TQk5YJStGukTeWPw8OuOkcGxAI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, syzbot+5ca851459ed04c778d1d@syzkaller.appspotmail.com, Ziyang Xuan , Oliver Hartkopp Subject: [PATCH 4.14 2/2] can: bcm: fix UAF of bcm op Date: Thu, 27 Jan 2022 19:08:57 +0100 Message-Id: <20220127180256.840826051@linuxfoundation.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220127180256.764665162@linuxfoundation.org> References: <20220127180256.764665162@linuxfoundation.org> User-Agent: quilt/0.66 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" From: Ziyang Xuan Stopping tasklet and hrtimer rely on the active state of tasklet and hrtimer sequentially in bcm_remove_op(), the op object will be freed if they are all unactive. Assume the hrtimer timeout is short, the hrtimer cb has been excuted after tasklet conditional judgment which must be false after last round tasklet_kill() and before condition hrtimer_active(), it is false when execute to hrtimer_active(). Bug is triggerd, because the stopping action is end and the op object will be freed, but the tasklet is scheduled. The resources of the op object will occur UAF bug. Move hrtimer_cancel() behind tasklet_kill() and switch 'while () {...}' to 'do {...} while ()' to fix the op UAF problem. Fixes: a06393ed0316 ("can: bcm: fix hrtimer/tasklet termination in bcm op r= emoval") Reported-by: syzbot+5ca851459ed04c778d1d@syzkaller.appspotmail.com Cc: stable@vger.kernel.org Signed-off-by: Ziyang Xuan Acked-by: Oliver Hartkopp Signed-off-by: Greg Kroah-Hartman Tested-by: Guenter Roeck Tested-by: Linux Kernel Functional Testing --- net/can/bcm.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -762,21 +762,21 @@ static struct bcm_op *bcm_find_op(struct static void bcm_remove_op(struct bcm_op *op) { if (op->tsklet.func) { - while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) || - test_bit(TASKLET_STATE_RUN, &op->tsklet.state) || - hrtimer_active(&op->timer)) { - hrtimer_cancel(&op->timer); + do { tasklet_kill(&op->tsklet); - } + hrtimer_cancel(&op->timer); + } while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) || + test_bit(TASKLET_STATE_RUN, &op->tsklet.state) || + hrtimer_active(&op->timer)); } =20 if (op->thrtsklet.func) { - while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) || - test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) || - hrtimer_active(&op->thrtimer)) { - hrtimer_cancel(&op->thrtimer); + do { tasklet_kill(&op->thrtsklet); - } + hrtimer_cancel(&op->thrtimer); + } while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) || + test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) || + hrtimer_active(&op->thrtimer)); } =20 if ((op->frames) && (op->frames !=3D &op->sframe))