FAILED: patch "[PATCH] firmware: arm_scpi: Ensure scpi_info is not assigned if the" failed to apply to 4.19-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 689640efc0a2c4e07e6f88affe6d42cd40cc3f85 Mon Sep 17 00:00:00 2001
From: Sudeep Holla <[email protected]>
Date: Fri, 1 Jul 2022 17:03:10 +0100
Subject: [PATCH] firmware: arm_scpi: Ensure scpi_info is not assigned if the
probe fails
When scpi probe fails, at any point, we need to ensure that the scpi_info is not set and will remain NULL until the probe succeeds. If it is not taken care, then it could result use-after-free as the value is exported via get_scpi_ops() and could refer to a memory allocated via devm_kzalloc() but freed when the probe fails.
drivers/firmware/arm_scpi.c +35 -26
@@ -815,7 +815,7 @@ static int scpi_init_versions(struct scpi_drvinfo *info) info->firmware_version =le32_to_cpu (caps.platform_version); }/* Ignore error if not implemented */ -if (scpi_info->is_legacy && ret == -EOPNOTSUPP ) +if (info->is_legacy && ret == -EOPNOTSUPP )return 0 ;return ret;
@@ -913,13 +913,14 @@ static int scpi_probe(struct platform_device *pdev)struct resource res;struct device *dev = &pdev->dev;struct device_node *np = dev->of_node; +struct scpi_drvinfo *scpi_drvinfo; - scpi_info =devm_kzalloc (dev,sizeof (*scpi_info),GFP_KERNEL ); -if (!scpi_info) + scpi_drvinfo =devm_kzalloc (dev,sizeof (*scpi_drvinfo),GFP_KERNEL ); +if (!scpi_drvinfo)return -ENOMEM ;if (of_match_device (legacy_scpi_of_match, &pdev->dev)) - scpi_info->is_legacy = true; + scpi_drvinfo->is_legacy = true; count =of_count_phandle_with_args (np,"mboxes" ,"#mbox-cells" );if (count <0 ) {
@@ -927,19 +928,19 @@ static int scpi_probe(struct platform_device *pdev)return -ENODEV ; } - scpi_info->channels =devm_kcalloc (dev, count,sizeof (struct scpi_chan ), -GFP_KERNEL ); -if (!scpi_info->channels) + scpi_drvinfo->channels = +devm_kcalloc (dev, count,sizeof (struct scpi_chan ),GFP_KERNEL ); +if (!scpi_drvinfo->channels)return -ENOMEM ; - ret =devm_add_action (dev, scpi_free_channels, scpi_info); + ret =devm_add_action (dev, scpi_free_channels, scpi_drvinfo);if (ret)return ret; -for (; scpi_info->num_chans < count; scpi_info->num_chans++) { +for (; scpi_drvinfo->num_chans < count; scpi_drvinfo->num_chans++) {resource_size_t size; -int idx = scpi_info->num_chans; -struct scpi_chan *pchan = scpi_info->channels + idx; +int idx = scpi_drvinfo->num_chans; +struct scpi_chan *pchan = scpi_drvinfo->channels + idx;struct mbox_client *cl = &pchan->cl;struct device_node *shmem =of_parse_phandle (np,"shmem" , idx);
@@ -986,45 +987,53 @@ static int scpi_probe(struct platform_device *pdev)return ret; } - scpi_info->commands = scpi_std_commands; + scpi_drvinfo->commands = scpi_std_commands; -platform_set_drvdata (pdev, scpi_info); +platform_set_drvdata (pdev, scpi_drvinfo); -if (scpi_info->is_legacy) { +if (scpi_drvinfo->is_legacy) {/* Replace with legacy variants */ scpi_ops.clk_set_val = legacy_scpi_clk_set_val; - scpi_info->commands = scpi_legacy_commands; + scpi_drvinfo->commands = scpi_legacy_commands;/* Fill priority bitmap */ for (idx =0 ; idx <ARRAY_SIZE (legacy_hpriority_cmds); idx++)set_bit (legacy_hpriority_cmds[idx], - scpi_info->cmd_priority); + scpi_drvinfo->cmd_priority); } - ret =scpi_init_versions (scpi_info); + scpi_info = scpi_drvinfo; + + ret =scpi_init_versions (scpi_drvinfo);if (ret) {dev_err (dev,"incorrect or no SCP firmware found\n" ); + scpi_info =NULL ;return ret; } -if (scpi_info->is_legacy && !scpi_info->protocol_version && - !scpi_info->firmware_version) +if (scpi_drvinfo->is_legacy && !scpi_drvinfo->protocol_version && + !scpi_drvinfo->firmware_version)dev_info (dev,"SCP Protocol legacy pre-1.0 firmware\n" );else dev_info (dev,"SCP Protocol %lu.%lu Firmware %lu.%lu.%lu version\n" ,FIELD_GET (PROTO_REV_MAJOR_MASK , - scpi_info->protocol_version), + scpi_drvinfo->protocol_version),FIELD_GET (PROTO_REV_MINOR_MASK , - scpi_info->protocol_version), + scpi_drvinfo->protocol_version),FIELD_GET (FW_REV_MAJOR_MASK , - scpi_info->firmware_version), + scpi_drvinfo->firmware_version),FIELD_GET (FW_REV_MINOR_MASK , - scpi_info->firmware_version), + scpi_drvinfo->firmware_version),FIELD_GET (FW_REV_PATCH_MASK , - scpi_info->firmware_version)); - scpi_info->scpi_ops = &scpi_ops; + scpi_drvinfo->firmware_version)); + + scpi_drvinfo->scpi_ops = &scpi_ops; -return devm_of_platform_populate (dev); + ret =devm_of_platform_populate (dev); +if (ret) + scpi_info =NULL ; + +return ret; }static const struct of_device_id scpi_of_match[] = {