]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
firmware: arm_ffa: Fix the race around setting ffa_dev->properties
authorLevi Yun <yeoreum.yun@arm.com>
Tue, 3 Dec 2024 14:31:08 +0000 (14:31 +0000)
committerSudeep Holla <sudeep.holla@arm.com>
Wed, 4 Dec 2024 09:59:54 +0000 (09:59 +0000)
Currently, ffa_dev->properties is set after the ffa_device_register()
call return in ffa_setup_partitions(). This could potentially result in
a race where the partition's properties is accessed while probing
struct ffa_device before it is set.

Update the ffa_device_register() to receive ffa_partition_info so all
the data from the partition information received from the firmware can
be updated into the struct ffa_device before the calling device_register()
in ffa_device_register().

Fixes: e781858488b9 ("firmware: arm_ffa: Add initial FFA bus support for device enumeration")
Signed-off-by: Levi Yun <yeoreum.yun@arm.com>
Message-Id: <20241203143109.1030514-2-yeoreum.yun@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
drivers/firmware/arm_ffa/bus.c
drivers/firmware/arm_ffa/driver.c
include/linux/arm_ffa.h

index eb17d03b66fec9fe0da1a5f5d93d188e2631e182..dfda5ffc14db7208e8b622cdd648194c9cb1ef34 100644 (file)
@@ -187,13 +187,18 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev)
        return valid;
 }
 
-struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
-                                      const struct ffa_ops *ops)
+struct ffa_device *
+ffa_device_register(const struct ffa_partition_info *part_info,
+                   const struct ffa_ops *ops)
 {
        int id, ret;
+       uuid_t uuid;
        struct device *dev;
        struct ffa_device *ffa_dev;
 
+       if (!part_info)
+               return NULL;
+
        id = ida_alloc_min(&ffa_bus_id, 1, GFP_KERNEL);
        if (id < 0)
                return NULL;
@@ -210,9 +215,11 @@ struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
        dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id);
 
        ffa_dev->id = id;
-       ffa_dev->vm_id = vm_id;
+       ffa_dev->vm_id = part_info->id;
+       ffa_dev->properties = part_info->properties;
        ffa_dev->ops = ops;
-       uuid_copy(&ffa_dev->uuid, uuid);
+       import_uuid(&uuid, (u8 *)part_info->uuid);
+       uuid_copy(&ffa_dev->uuid, &uuid);
 
        ret = device_register(&ffa_dev->dev);
        if (ret) {
index b14cbdae94e82bd2eb83b77cc347529a12cc966d..2c2ec3c35f15612168cdf0ef94022e00c08677b5 100644 (file)
@@ -1387,7 +1387,6 @@ static struct notifier_block ffa_bus_nb = {
 static int ffa_setup_partitions(void)
 {
        int count, idx, ret;
-       uuid_t uuid;
        struct ffa_device *ffa_dev;
        struct ffa_dev_part_info *info;
        struct ffa_partition_info *pbuf, *tpbuf;
@@ -1406,23 +1405,19 @@ static int ffa_setup_partitions(void)
 
        xa_init(&drv_info->partition_info);
        for (idx = 0, tpbuf = pbuf; idx < count; idx++, tpbuf++) {
-               import_uuid(&uuid, (u8 *)tpbuf->uuid);
-
                /* Note that if the UUID will be uuid_null, that will require
                 * ffa_bus_notifier() to find the UUID of this partition id
                 * with help of ffa_device_match_uuid(). FF-A v1.1 and above
                 * provides UUID here for each partition as part of the
                 * discovery API and the same is passed.
                 */
-               ffa_dev = ffa_device_register(&uuid, tpbuf->id, &ffa_drv_ops);
+               ffa_dev = ffa_device_register(tpbuf, &ffa_drv_ops);
                if (!ffa_dev) {
                        pr_err("%s: failed to register partition ID 0x%x\n",
                               __func__, tpbuf->id);
                        continue;
                }
 
-               ffa_dev->properties = tpbuf->properties;
-
                if (drv_info->version > FFA_VERSION_1_0 &&
                    !(tpbuf->properties & FFA_PARTITION_AARCH64_EXEC))
                        ffa_mode_32bit_set(ffa_dev);
index a28e2a6a13d05a371b43fb37bf004eacd7a3852b..74169dd0f65948b05991732358855cdc31b54adb 100644 (file)
@@ -166,9 +166,12 @@ static inline void *ffa_dev_get_drvdata(struct ffa_device *fdev)
        return dev_get_drvdata(&fdev->dev);
 }
 
+struct ffa_partition_info;
+
 #if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)
-struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
-                                      const struct ffa_ops *ops);
+struct ffa_device *
+ffa_device_register(const struct ffa_partition_info *part_info,
+                   const struct ffa_ops *ops);
 void ffa_device_unregister(struct ffa_device *ffa_dev);
 int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
                        const char *mod_name);
@@ -176,9 +179,9 @@ void ffa_driver_unregister(struct ffa_driver *driver);
 bool ffa_device_is_valid(struct ffa_device *ffa_dev);
 
 #else
-static inline
-struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
-                                      const struct ffa_ops *ops)
+static inline struct ffa_device *
+ffa_device_register(const struct ffa_partition_info *part_info,
+                   const struct ffa_ops *ops)
 {
        return NULL;
 }