Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp889206pxb; Wed, 3 Mar 2021 19:51:36 -0800 (PST) X-Google-Smtp-Source: ABdhPJwLw4Dkg+BSvNCoqTCRSN3wyRmYMP6a4xpAhIGudxqTbyJJ/Cvg+xXsczVTfpMUCIeWDXjU X-Received: by 2002:a17:906:5d05:: with SMTP id g5mr1933366ejt.489.1614829896149; Wed, 03 Mar 2021 19:51:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1614829896; cv=none; d=google.com; s=arc-20160816; b=FTu9QvkW2qKYRzdS0LfmsVH+ltz3+9QMqnEtTbgu5sP/oYeHcNAT4godHQVtiptPHw w8yvv6kXXUZ4Ln8nMLoJdVNAKfCsu5IHhIzdAeAtLzxf1Fo0GG8AkXI/8xsJkhcFJRVr a5DgkchHmsERcp+6exPlTjouvMjiy/JpHSYbjMM+/VddixxoLePqaqTFJWIRzxZFqcXd s6/A8egu11DYqOuxUiJqRBb7rJalWOu3DXkatTiOMnoI2Dq2kBtSs87OI64MXecbIcr3 A1tbLWQT6MkDjzVLH0F91LZVNZTm4bfeiPXC8bC+c1n8IHzNc+HU8HWJrCK3SdFRVsHM pADA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Ybp2uh8pzyybOxI1warA3h8AdzQzZENyA1cq4soPGI4=; b=JVQ9krbAvB2WdR0M18U9Di6aLczuB6WkKTzNIFxgOBz6c182cOYoidXPJZpMCnOakl uZ7HAcpY6PvFDF6RK/mQsLDRsojjaik2gPWzlA4bvLhSeMsD0YPRy0R8KhpTV8+cFI/v gBlKwHUTn7D2r0kcgDvcFWooazo97VeaH24Zb3mSMU+i+RfleWAaIxsWVBzxiwmhx8Qk fRWOdheeCe6DHkSjCJHKnpyEZofxp7Q7QD4+bAKelNdvFR5aZObYwNeE8ZQZ7DnP/iCt W2yIPswi4TF3b5TIvTBBX3qeRGgSMIcMqtGFjMsYr2P+73oxKhYyBI6+KvdSuxgY9b9U o5Ug== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=P9GkkEVL; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z13si3834468eje.437.2021.03.03.19.51.14; Wed, 03 Mar 2021 19:51:36 -0800 (PST) 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; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=P9GkkEVL; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1380262AbhCBBtk (ORCPT + 99 others); Mon, 1 Mar 2021 20:49:40 -0500 Received: from mail.kernel.org ([198.145.29.99]:48614 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241532AbhCAT0p (ORCPT ); Mon, 1 Mar 2021 14:26:45 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id F347F64D9C; Mon, 1 Mar 2021 17:08:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1614618492; bh=XQr8aqBc77OR1K8JXKZAdE36XIhKdlILPehCZUiCqfQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=P9GkkEVLUVVTibaZCw3zjhyRxOgXU75Pd+0OtJrTDGzclAgmYNnmQe4XB03NMZ3OY tol+8Rvt/1PpsvR50Q24Dl5zzKUDNtfw8JXkH8R+uDedLGNZCFn83W6vUF03OCPw85 9m+KOkACXKNL5AtsgH9Y+C0NwWnxtPZXVL9gyhag= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Maxim Mikityanskiy , Tariq Toukan , Saeed Mahameed , Sasha Levin Subject: [PATCH 5.10 107/663] net/mlx5e: kTLS, Use refcounts to free kTLS RX priv context Date: Mon, 1 Mar 2021 17:05:55 +0100 Message-Id: <20210301161147.030048873@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210301161141.760350206@linuxfoundation.org> References: <20210301161141.760350206@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Maxim Mikityanskiy [ Upstream commit b850bbff965129c34f50962638c0a66c82563536 ] wait_for_resync is unreliable - if it timeouts, priv_rx will be freed anyway. However, mlx5e_ktls_handle_get_psv_completion will be called sooner or later, leading to use-after-free. For example, it can happen if a CQ error happened, and ICOSQ stopped, but later on the queues are destroyed, and ICOSQ is flushed with mlx5e_free_icosq_descs. This patch converts the lifecycle of priv_rx to fully refcount-based, so that the struct won't be freed before the refcount goes to zero. Fixes: 0419d8c9d8f8 ("net/mlx5e: kTLS, Add kTLS RX resync support") Signed-off-by: Maxim Mikityanskiy Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: Sasha Levin --- .../mellanox/mlx5/core/en_accel/ktls_rx.c | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c index 0f13b661f7f98..d06532d0baa43 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c @@ -57,6 +57,20 @@ struct mlx5e_ktls_offload_context_rx { struct mlx5e_ktls_rx_resync_ctx resync; }; +static bool mlx5e_ktls_priv_rx_put(struct mlx5e_ktls_offload_context_rx *priv_rx) +{ + if (!refcount_dec_and_test(&priv_rx->resync.refcnt)) + return false; + + kfree(priv_rx); + return true; +} + +static void mlx5e_ktls_priv_rx_get(struct mlx5e_ktls_offload_context_rx *priv_rx) +{ + refcount_inc(&priv_rx->resync.refcnt); +} + static int mlx5e_ktls_create_tir(struct mlx5_core_dev *mdev, u32 *tirn, u32 rqtn) { int err, inlen; @@ -326,7 +340,7 @@ static void resync_handle_work(struct work_struct *work) priv_rx = container_of(resync, struct mlx5e_ktls_offload_context_rx, resync); if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags))) { - refcount_dec(&resync->refcnt); + mlx5e_ktls_priv_rx_put(priv_rx); return; } @@ -334,7 +348,7 @@ static void resync_handle_work(struct work_struct *work) sq = &c->async_icosq; if (resync_post_get_progress_params(sq, priv_rx)) - refcount_dec(&resync->refcnt); + mlx5e_ktls_priv_rx_put(priv_rx); } static void resync_init(struct mlx5e_ktls_rx_resync_ctx *resync, @@ -377,7 +391,11 @@ unlock: return err; } -/* Function is called with elevated refcount, it decreases it. */ +/* Function can be called with the refcount being either elevated or not. + * It decreases the refcount and may free the kTLS priv context. + * Refcount is not elevated only if tls_dev_del has been called, but GET_PSV was + * already in flight. + */ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi, struct mlx5e_icosq *sq) { @@ -410,7 +428,7 @@ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi, tls_offload_rx_resync_async_request_end(priv_rx->sk, cpu_to_be32(hw_seq)); priv_rx->stats->tls_resync_req_end++; out: - refcount_dec(&resync->refcnt); + mlx5e_ktls_priv_rx_put(priv_rx); dma_unmap_single(dev, buf->dma_addr, PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE); kfree(buf); } @@ -431,9 +449,9 @@ static bool resync_queue_get_psv(struct sock *sk) return false; resync = &priv_rx->resync; - refcount_inc(&resync->refcnt); + mlx5e_ktls_priv_rx_get(priv_rx); if (unlikely(!queue_work(resync->priv->tls->rx_wq, &resync->work))) - refcount_dec(&resync->refcnt); + mlx5e_ktls_priv_rx_put(priv_rx); return true; } @@ -625,31 +643,6 @@ err_create_key: return err; } -/* Elevated refcount on the resync object means there are - * outstanding operations (uncompleted GET_PSV WQEs) that - * will read the resync / priv_rx objects once completed. - * Wait for them to avoid use-after-free. - */ -static void wait_for_resync(struct net_device *netdev, - struct mlx5e_ktls_rx_resync_ctx *resync) -{ -#define MLX5E_KTLS_RX_RESYNC_TIMEOUT 20000 /* msecs */ - unsigned long exp_time = jiffies + msecs_to_jiffies(MLX5E_KTLS_RX_RESYNC_TIMEOUT); - unsigned int refcnt; - - do { - refcnt = refcount_read(&resync->refcnt); - if (refcnt == 1) - return; - - msleep(20); - } while (time_before(jiffies, exp_time)); - - netdev_warn(netdev, - "Failed waiting for kTLS RX resync refcnt to be released (%u).\n", - refcnt); -} - void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx) { struct mlx5e_ktls_offload_context_rx *priv_rx; @@ -671,8 +664,7 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx) wait_for_completion(&priv_rx->add_ctx); resync = &priv_rx->resync; if (cancel_work_sync(&resync->work)) - refcount_dec(&resync->refcnt); - wait_for_resync(netdev, resync); + mlx5e_ktls_priv_rx_put(priv_rx); priv_rx->stats->tls_del++; if (priv_rx->rule.rule) @@ -680,5 +672,9 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx) mlx5_core_destroy_tir(mdev, priv_rx->tirn); mlx5_ktls_destroy_key(mdev, priv_rx->key_id); - kfree(priv_rx); + /* priv_rx should normally be freed here, but if there is an outstanding + * GET_PSV, deallocation will be delayed until the CQE for GET_PSV is + * processed. + */ + mlx5e_ktls_priv_rx_put(priv_rx); } -- 2.27.0