firmware: arm_scmi: Fix device node validation for mailbox transport
authorCristian Marussi <cristian.marussi@arm.com>
Tue, 7 Mar 2023 16:23:24 +0000 (16:23 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 30 Mar 2023 10:48:00 +0000 (12:48 +0200)
commit 2ab4f4018cb6b8010ca5002c3bdc37783b5d28c2 upstream.

When mailboxes are used as a transport it is possible to setup the SCMI
transport layer, depending on the underlying channels configuration, to use
one or two mailboxes, associated, respectively, to one or two, distinct,
shared memory areas: any other combination should be treated as invalid.

Add more strict checking of SCMI mailbox transport device node descriptors.

Fixes: 5c8a47a5a91d ("firmware: arm_scmi: Make scmi core independent of the transport type")
Cc: <stable@vger.kernel.org> # 4.19
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Link: https://lore.kernel.org/r/20230307162324.891866-1-cristian.marussi@arm.com
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/firmware/arm_scmi/mailbox.c

index e09eb12bf4219fc5c2c8b435485b8cbb1c4bd637..ed9b83aee8bd7b155597e45a289a09532dcfbbd4 100644 (file)
@@ -52,6 +52,39 @@ static bool mailbox_chan_available(struct device *dev, int idx)
                                           "#mbox-cells", idx, NULL);
 }
 
+static int mailbox_chan_validate(struct device *cdev)
+{
+       int num_mb, num_sh, ret = 0;
+       struct device_node *np = cdev->of_node;
+
+       num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
+       num_sh = of_count_phandle_with_args(np, "shmem", NULL);
+       /* Bail out if mboxes and shmem descriptors are inconsistent */
+       if (num_mb <= 0 || num_sh > 2 || num_mb != num_sh) {
+               dev_warn(cdev, "Invalid channel descriptor for '%s'\n",
+                        of_node_full_name(np));
+               return -EINVAL;
+       }
+
+       if (num_sh > 1) {
+               struct device_node *np_tx, *np_rx;
+
+               np_tx = of_parse_phandle(np, "shmem", 0);
+               np_rx = of_parse_phandle(np, "shmem", 1);
+               /* SCMI Tx and Rx shared mem areas have to be distinct */
+               if (!np_tx || !np_rx || np_tx == np_rx) {
+                       dev_warn(cdev, "Invalid shmem descriptor for '%s'\n",
+                                of_node_full_name(np));
+                       ret = -EINVAL;
+               }
+
+               of_node_put(np_tx);
+               of_node_put(np_rx);
+       }
+
+       return ret;
+}
+
 static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
                              bool tx)
 {
@@ -64,6 +97,10 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
        resource_size_t size;
        struct resource res;
 
+       ret = mailbox_chan_validate(cdev);
+       if (ret)
+               return ret;
+
        smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL);
        if (!smbox)
                return -ENOMEM;