From nobody Mon Jun 8 20:41:43 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 648D54028E4 for ; Tue, 26 May 2026 14:42:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779806558; cv=none; b=rl48T9lmDf+mg0dUaSeqrwqwX1VrImvQF9QHkpVQBrj61V3OpVlbtWNtcvwyDrrNwmKwYEQvHghdFbaqjYmr5Zq+qZWOT5B+w69LJ84FGFknJ5tGPJ2RaIakrtrzbufXDgQmUGEuRgXTB0NK+pz7jWlJ+t5yWqMeyJAoQ9u1QJQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779806558; c=relaxed/simple; bh=BNdG3RxyCfQUMZqmYRPrtdwKGrMxNPihk4+VB2ELmbM=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=gGN0WSKf11PMoXOuqTKUyMXKce8nME435QlhcJNMBp5v4++oadRLdPixW8JxPsUH/RgdtcT3vY3do4F/m7Qt7un2wEhcdkXiDOvn9ONU+oxkWSKHPfYm1BLEozi6AMJuz4wDYB4SuBMGkpiAFt66Hg6T/WIazPQIODv2wncdLvo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oO748QPr; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oO748QPr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 847211F000E9; Tue, 26 May 2026 14:42:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779806555; bh=ObbrvJvOAD2GmdS+AnkxmXPTnyA/nre74I2RrO+aC0Q=; h=From:To:Cc:Subject:Date; b=oO748QPrzt2xwHOk5jmHhIRUnOXki16hWmA10B+kKpU9zJz5VF9YAOIec9hZNInDC Dft/Q1rwRm+a/DoFKd0QVd2FjXI4jf5P9gwFWyziyAIo9mXDJr7iglrqFCvLnBUAs6 nSC7PBNIKw62QkFkY9Eqyb5I/yVHANXO+k7piSn0ccFKOX7YkmjUFacj49N7lCM7yZ TLmWBxY3GeQr1n3G2e0BQDL1td3TrkyhPNj5oDmWbsyI9Q0LIavJfD/ywTh+88C/n3 zFXmTJrkJJxhkk9Eb8VA4ZwMNcIcOy3YuElnbTkv7b7+ka0jCGn9APb3T02Fnsio0f zxM2f+GizLKXA== From: Dinh Nguyen To: linux-kernel@vger.kernel.org Cc: dinguyen@kernel.org, Markus.Elfring@web.de, tze.yee.ng@altera.com, stable@kernel.org Subject: [PATCHv2] firmware: stratix10-rsu: Fix NULL deref on rsu_send_msg() timeout in probe Date: Tue, 26 May 2026 09:42:16 -0500 Message-ID: <20260526144216.3863269-1-dinguyen@kernel.org> X-Mailer: git-send-email 2.42.0.411.g813d9a9188 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" rsu_send_msg() can return -ETIMEDOUT when wait_for_completion_interruptible_timeout() fires while the SMC call is sti= ll pending. In stratix10_rsu_probe(), the error paths for COMMAND_RSU_DCMF_VER= SION, COMMAND_RSU_DCMF_STATUS, COMMAND_RSU_MAX_RETRY and COMMAND_RSU_GET_SPT_TABLE call stratix10_svc_free_channel() - which sets chan->scl to NULL - but then fall through and queue the next request on the same channel. The next svc kthread that runs will dereference pdata->chan->scl in its receive callback path, triggering a NULL pointer dereference identical to the one fixed by commit c45f7263100c ("firmware: stratix10-rsu: Fix NULL pointer dereference when RSU is disabled") for the COMMAND_RSU_STATUS path. Apply the same cleanup pattern to the remaining failure paths: remove the async client, free the channel, and return early so no further messages are queued on a channel whose scl has been cleared. While at it, clean up stratix10_rsu_probe() in two ways without changing behavior: - Drop redundant zero-initialization of fields already cleared by devm_kzalloc(): client.receive_cb, status.* and spt0/1_address (INVALID_SPT_ADDRESS is 0x0). - Replace five identical 3-line error-cleanup blocks (stratix10_svc_remove_async_client() + stratix10_svc_free_channel() + return ret) with goto labels (remove_async_client, free_channel), matching the standard kernel resource-unwinding pattern and making it easier to extend the probe sequence without forgetting matching cleanup. Also move init_completion() next to mutex_init() so sync-primitive initialization is grouped before anything that could trigger a callback. Fixes: 15847537b623 ("firmware: stratix10-rsu: Migrate RSU driver to use st= ratix10 asynchronous framework.") Cc: stable@kernel.org Assisted-by: Claude:claude-4.7-opus-high Cursor Signed-off-by: Dinh Nguyen --- drivers/firmware/stratix10-rsu.c | 45 ++++++++++++++------------------ 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/drivers/firmware/stratix10-rsu.c b/drivers/firmware/stratix10-= rsu.c index e1912108a0fee..2a7a0f7743893 100644 --- a/drivers/firmware/stratix10-rsu.c +++ b/drivers/firmware/stratix10-rsu.c @@ -723,15 +723,9 @@ static int stratix10_rsu_probe(struct platform_device = *pdev) return -ENOMEM; =20 priv->client.dev =3D dev; - priv->client.receive_cb =3D NULL; priv->client.priv =3D priv; - priv->status.current_image =3D 0; - priv->status.fail_image =3D 0; - priv->status.error_location =3D 0; - priv->status.error_details =3D 0; - priv->status.version =3D 0; - priv->status.state =3D 0; priv->retry_counter =3D INVALID_RETRY_COUNTER; + priv->max_retry =3D INVALID_RETRY_COUNTER; priv->dcmf_version.dcmf0 =3D INVALID_DCMF_VERSION; priv->dcmf_version.dcmf1 =3D INVALID_DCMF_VERSION; priv->dcmf_version.dcmf2 =3D INVALID_DCMF_VERSION; @@ -740,11 +734,11 @@ static int stratix10_rsu_probe(struct platform_device= *pdev) priv->dcmf_status.dcmf1 =3D INVALID_DCMF_STATUS; priv->dcmf_status.dcmf2 =3D INVALID_DCMF_STATUS; priv->dcmf_status.dcmf3 =3D INVALID_DCMF_STATUS; - priv->max_retry =3D INVALID_RETRY_COUNTER; - priv->spt0_address =3D INVALID_SPT_ADDRESS; - priv->spt1_address =3D INVALID_SPT_ADDRESS; + /* spt0/1_address and status fields default to 0 from kzalloc */ =20 mutex_init(&priv->lock); + init_completion(&priv->completion); + priv->chan =3D stratix10_svc_request_channel_byname(&priv->client, SVC_CLIENT_RSU); if (IS_ERR(priv->chan)) { @@ -756,11 +750,9 @@ static int stratix10_rsu_probe(struct platform_device = *pdev) ret =3D stratix10_svc_add_async_client(priv->chan, false); if (ret) { dev_err(dev, "failed to add async client\n"); - stratix10_svc_free_channel(priv->chan); - return ret; + goto free_channel; } =20 - init_completion(&priv->completion); platform_set_drvdata(pdev, priv); =20 /* get the initial state from firmware */ @@ -768,41 +760,44 @@ static int stratix10_rsu_probe(struct platform_device= *pdev) rsu_async_status_callback); if (ret) { dev_err(dev, "Error, getting RSU status %i\n", ret); - stratix10_svc_remove_async_client(priv->chan); - stratix10_svc_free_channel(priv->chan); - return ret; + goto remove_async_client; } =20 /* get DCMF version from firmware */ - ret =3D rsu_send_msg(priv, COMMAND_RSU_DCMF_VERSION, - 0, rsu_dcmf_version_callback); + ret =3D rsu_send_msg(priv, COMMAND_RSU_DCMF_VERSION, 0, + rsu_dcmf_version_callback); if (ret) { dev_err(dev, "Error, getting DCMF version %i\n", ret); - stratix10_svc_free_channel(priv->chan); + goto remove_async_client; } =20 - ret =3D rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS, - 0, rsu_dcmf_status_callback); + ret =3D rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS, 0, + rsu_dcmf_status_callback); if (ret) { dev_err(dev, "Error, getting DCMF status %i\n", ret); - stratix10_svc_free_channel(priv->chan); + goto remove_async_client; } =20 ret =3D rsu_send_msg(priv, COMMAND_RSU_MAX_RETRY, 0, rsu_max_retry_callback); if (ret) { dev_err(dev, "Error, getting RSU max retry %i\n", ret); - stratix10_svc_free_channel(priv->chan); + goto remove_async_client; } =20 - ret =3D rsu_send_async_msg(dev, priv, COMMAND_RSU_GET_SPT_TABLE, 0, rsu_async_get_spt_table_callback); if (ret) { dev_err(dev, "Error, getting SPT table %i\n", ret); - stratix10_svc_free_channel(priv->chan); + goto remove_async_client; } =20 + return 0; + +remove_async_client: + stratix10_svc_remove_async_client(priv->chan); +free_channel: + stratix10_svc_free_channel(priv->chan); return ret; } =20 --=20 2.42.0.411.g813d9a9188