misc: c2port: Calculate bin_attribute size through group callback
authorThomas Weißschuh <linux@weissschuh.net>
Sat, 21 Dec 2024 14:48:10 +0000 (15:48 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 24 Dec 2024 08:36:02 +0000 (09:36 +0100)
Modifying the size of the global bin_attribute instance can be racy.
Instead use the new .bin_size callback to do so safely.

For this to work move the initialization of c2dev->ops before the call
to device_create() as the size callback will need access to it.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://lore.kernel.org/r/20241221-sysfs-const-bin_attr-misc-drivers-v2-4-ba5e79fe8771@weissschuh.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/c2port/core.c

index 2bb1dd2511f9dd178b8c06baa460bb609f7f8fd7..f455d702b9cd4999648a57985e305aac5301403f 100644 (file)
@@ -874,9 +874,22 @@ static struct bin_attribute *c2port_bin_attrs[] = {
        NULL,
 };
 
+static size_t c2port_bin_attr_size(struct kobject *kobj,
+                                  const struct bin_attribute *attr,
+                                  int i)
+{
+       struct c2port_device *c2dev = dev_get_drvdata(kobj_to_dev(kobj));
+
+       if (attr == &bin_attr_flash_data)
+               return c2dev->ops->blocks_num * c2dev->ops->block_size;
+
+       return attr->size;
+}
+
 static const struct attribute_group c2port_group = {
        .attrs = c2port_attrs,
        .bin_attrs = c2port_bin_attrs,
+       .bin_size = c2port_bin_attr_size,
 };
 
 static const struct attribute_group *c2port_groups[] = {
@@ -912,8 +925,7 @@ struct c2port_device *c2port_device_register(char *name,
        if (ret < 0)
                goto error_idr_alloc;
        c2dev->id = ret;
-
-       bin_attr_flash_data.size = ops->blocks_num * ops->block_size;
+       c2dev->ops = ops;
 
        c2dev->dev = device_create(c2port_class, NULL, 0, c2dev,
                                   "c2port%d", c2dev->id);
@@ -924,7 +936,6 @@ struct c2port_device *c2port_device_register(char *name,
        dev_set_drvdata(c2dev->dev, c2dev);
 
        strscpy(c2dev->name, name, sizeof(c2dev->name));
-       c2dev->ops = ops;
        mutex_init(&c2dev->mutex);
 
        /* By default C2 port access is off */