Re: [PATCH v1 1/1] fpga: m10bmc-sec: add image_load sysfs for N3000 and D5005
Lee Jones <[email protected]> Thu, 23 Jul 2026 14:37:11 +0100
| Newsgroups | dev.linux.lists.mfd,dev.linux.lists.sashiko-reviews |
|---|---|
| Message-ID | <[email protected]> |
On Wed, 15 Jul 2026, [email protected] wrote: > Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: > - [High] Lack of synchronization in the `image_load` sysfs handler allows concurrent firmware reloads and races with ongoing secure firmware uploads. > - [Medium] The 'control' sysfs group creates an empty directory even when the device does not support image loading, failing to completely hide the group. > - [Low] The image load handler arrays and their pointer in `m10bmc_sec_ops` are not declared as `const`, storing function pointers in mutable memory. Please show that you have at least considered these, or better mitigated them. > -- > > --- Patch [1]: [PATCH v1 1/1] fpga: m10bmc-sec: add image_load sysfs for N3000 and D5005 --- > commit d97d9214f834756bd204bc187982a995a0b7658d > Author: Ionut Nechita <[email protected]> > > fpga: m10bmc-sec: add image_load sysfs for N3000 and D5005 > > This commit adds the control/available_images and control/image_load > sysfs attributes to trigger a reload of a BMC or PKVL retimer firmware > image. It handles device-specific configuration for N3000 and D5005 cards. > The control group is intended to be hidden when not supported. > > > diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c > > index 7d23d914df3f2..7a390cd705161 100644 > > --- a/drivers/fpga/intel-m10-bmc-sec-update.c > > +++ b/drivers/fpga/intel-m10-bmc-sec-update.c > > @@ -15,8 +15,14 @@ > > > > struct m10bmc_sec; > > > > +struct image_load { > > + const char *name; > > + int (*load_image)(struct m10bmc_sec *sec); > > +}; > > + > > struct m10bmc_sec_ops { > > int (*rsu_status)(struct m10bmc_sec *sec); > > + struct image_load *image_load; /* terminated with { } member */ > > [Severity: Low] > Should this pointer be declared as const struct image_load * to ensure the > function pointers remain in read-only memory? > > > }; > > [ ... ] > > > +static struct image_load n3000_image_load_hndlrs[] = { > > + { > > + .name = "bmc_factory", > > + .load_image = m10bmc_sec_bmc_image_load_1, > > + }, > > + { > > + .name = "bmc_user", > > + .load_image = m10bmc_sec_bmc_image_load_0, > > + }, > > + { > > + .name = "retimer_fw", > > + .load_image = m10bmc_sec_retimer_eeprom_load, > > + }, > > + {} > > +}; > > + > > +static struct image_load d5005_image_load_hndlrs[] = { > > + { > > + .name = "bmc_factory", > > + .load_image = m10bmc_sec_bmc_image_load_0, > > + }, > > + { > > + .name = "bmc_user", > > + .load_image = m10bmc_sec_bmc_image_load_1, > > + }, > > + {} > > +}; > > [Severity: Low] > Would it be better to mark these arrays as const? Placing executable > function targets in mutable memory increases the kernel's attack surface. > > [ ... ] > > > +static ssize_t image_load_store(struct device *dev, > > + struct device_attribute *attr, > > + const char *buf, size_t count) > > +{ > > + struct m10bmc_sec *sec = dev_get_drvdata(dev); > > + const struct image_load *hndlr; > > + int ret = -EINVAL; > > + > > + for (hndlr = sec->ops->image_load; hndlr->name; hndlr++) { > > + if (sysfs_streq(buf, hndlr->name)) { > > + ret = hndlr->load_image(sec); > > + break; > > + } > > + } > > + > > + return ret ? : count; > > +} > > +static DEVICE_ATTR_WO(image_load); > > [Severity: High] > Does this sysfs handler need synchronization (such as acquiring bmcfw_lock)? > > Without driver-level locking, concurrent writes to the image_load attribute > could cause multi-step hardware operations to race. This might also race > with ongoing secure firmware uploads in the background. > > For example, m10bmc_sec_retimer_eeprom_load() performs a check-then-act > sequence: > > m10bmc_sec_retimer_eeprom_load() > retimer_check_idle(sec); > trigger_retimer_eeprom_load(sec); > poll_retimer_eeprom_load_done(sec); > > Could concurrent executions silently corrupt the hardware doorbell state? > > > + > > +static umode_t > > +m10bmc_control_visible(struct kobject *kobj, struct attribute *attr, int n) > > +{ > > + struct m10bmc_sec *sec = dev_get_drvdata(kobj_to_dev(kobj)); > > + > > + if (!sec->ops->image_load) > > + return 0; > > + > > + return attr->mode; > > +} > > [Severity: Medium] > The commit message states the control group is hidden for the N6000: > "The control group is hidden via its is_visible() callback whenever the > device ops do not provide an image_load table, so N6000 ... is unaffected." > > However, does returning 0 here actually hide the group directory? > > As per the sysfs API, returning 0 for a named group only suppresses its > internal attributes, leaving an empty directory visible. Should this > return SYSFS_GROUP_INVISIBLE to completely hide the control/ directory? > > -- > Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1 -- Lee Jones