Message ID | 20210503213546.316439-7-russell.h.weight@intel.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | FPGA Security Manager Class Driver | expand |
On Mon, May 03, 2021 at 02:35:45PM -0700, Russ Weight wrote: > Extend the FPGA Security Manager class driver to include > an update/cancel sysfs file that can be written to request > that an update be canceled. The write may return EBUSY if > the update has progressed to the point that it cannot be > canceled by software or ENODEV if there is no update in > progress. > > Signed-off-by: Russ Weight <russell.h.weight@intel.com> > Reviewed-by: Tom Rix <trix@redhat.com> > --- > v12: > - Updated Date and KernelVersion fields in ABI documentation > v11: > - No change > v10: > - Rebased to 5.12-rc2 next > - Updated Date and KernelVersion in ABI documentation > v9: > - Updated Date and KernelVersion in ABI documentation > v8: > - No change > v7: > - Changed Date in documentation file to December 2020 > v6: > - No change > v5: > - No change > v4: > - Changed from "Intel FPGA Security Manager" to FPGA Security Manager" > and removed unnecessary references to "Intel". > - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_ > v3: > - No change > v2: > - Bumped documentation date and version > - Minor code cleanup per review comments > --- > .../ABI/testing/sysfs-class-fpga-sec-mgr | 10 ++++ > drivers/fpga/fpga-sec-mgr.c | 59 +++++++++++++++++-- > include/linux/fpga/fpga-sec-mgr.h | 1 + > 3 files changed, 66 insertions(+), 4 deletions(-) > > diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr > index c5d0b9d7c7e4..749f2d4c78d3 100644 > --- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr > +++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr > @@ -17,6 +17,16 @@ Description: Write only. Write the filename of an image > and Root Entry Hashes, and to cancel Code Signing > Keys (CSK). > > +What: /sys/class/fpga_sec_mgr/fpga_secX/update/cancel > +Date: June 2021 > +KernelVersion: 5.14 > +Contact: Russ Weight <russell.h.weight@intel.com> > +Description: Write-only. Write a "1" to this file to request > + that a current update be canceled. This request > + will be rejected (EBUSY) if the programming phase > + has already started or (ENODEV) if there is no > + update in progress. > + > What: /sys/class/fpga_sec_mgr/fpga_secX/update/status > Date: June 2021 > KernelVersion: 5.14 > diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c > index 2487042ace82..35bd419bd3b9 100644 > --- a/drivers/fpga/fpga-sec-mgr.c > +++ b/drivers/fpga/fpga-sec-mgr.c > @@ -43,6 +43,23 @@ static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr, > smgr->sops->cancel(smgr); > } > > +static int progress_transition(struct fpga_sec_mgr *smgr, > + enum fpga_sec_prog new_progress) > +{ > + int ret = 0; > + > + mutex_lock(&smgr->lock); > + if (smgr->request_cancel) { > + set_error(smgr, FPGA_SEC_ERR_CANCELED); > + smgr->sops->cancel(smgr); > + ret = -ECANCELED; > + } else { > + update_progress(smgr, new_progress); > + } > + mutex_unlock(&smgr->lock); > + return ret; > +} > + > static void progress_complete(struct fpga_sec_mgr *smgr) > { > mutex_lock(&smgr->lock); > @@ -74,15 +91,19 @@ static void fpga_sec_mgr_update(struct work_struct *work) > goto release_fw_exit; > } > > - update_progress(smgr, FPGA_SEC_PROG_PREPARING); > + if (progress_transition(smgr, FPGA_SEC_PROG_PREPARING)) > + goto modput_exit; > + > ret = smgr->sops->prepare(smgr); > if (ret != FPGA_SEC_ERR_NONE) { > fpga_sec_dev_error(smgr, ret); > goto modput_exit; > } > > - update_progress(smgr, FPGA_SEC_PROG_WRITING); > - while (smgr->remaining_size) { > + if (progress_transition(smgr, FPGA_SEC_PROG_WRITING)) > + goto done; > + > + while (smgr->remaining_size && !smgr->request_cancel) { > ret = smgr->sops->write_blk(smgr, offset); > if (ret != FPGA_SEC_ERR_NONE) { > fpga_sec_dev_error(smgr, ret); > @@ -92,7 +113,9 @@ static void fpga_sec_mgr_update(struct work_struct *work) > offset = fw->size - smgr->remaining_size; > } > > - update_progress(smgr, FPGA_SEC_PROG_PROGRAMMING); > + if (progress_transition(smgr, FPGA_SEC_PROG_PROGRAMMING)) > + goto done; > + > ret = smgr->sops->poll_complete(smgr); > if (ret != FPGA_SEC_ERR_NONE) > fpga_sec_dev_error(smgr, ret); > @@ -229,6 +252,7 @@ static ssize_t filename_store(struct device *dev, struct device_attribute *attr, > } > > smgr->err_code = FPGA_SEC_ERR_NONE; > + smgr->request_cancel = false; > smgr->progress = FPGA_SEC_PROG_READING; > reinit_completion(&smgr->update_done); > schedule_work(&smgr->work); > @@ -239,8 +263,32 @@ static ssize_t filename_store(struct device *dev, struct device_attribute *attr, > } > static DEVICE_ATTR_WO(filename); > > +static ssize_t cancel_store(struct device *dev, struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + struct fpga_sec_mgr *smgr = to_sec_mgr(dev); > + bool cancel; > + int ret = count; > + > + if (kstrtobool(buf, &cancel) || !cancel) > + return -EINVAL; > + > + mutex_lock(&smgr->lock); > + if (smgr->progress == FPGA_SEC_PROG_PROGRAMMING) > + ret = -EBUSY; > + else if (smgr->progress == FPGA_SEC_PROG_IDLE) > + ret = -ENODEV; > + else > + smgr->request_cancel = true; > + mutex_unlock(&smgr->lock); > + > + return ret; > +} > +static DEVICE_ATTR_WO(cancel); > + > static struct attribute *sec_mgr_update_attrs[] = { > &dev_attr_filename.attr, > + &dev_attr_cancel.attr, > &dev_attr_status.attr, > &dev_attr_error.attr, > &dev_attr_remaining_size.attr, > @@ -464,6 +512,9 @@ void fpga_sec_mgr_unregister(struct fpga_sec_mgr *smgr) > goto unregister; > } > > + if (smgr->progress != FPGA_SEC_PROG_PROGRAMMING) > + smgr->request_cancel = true; > + > mutex_unlock(&smgr->lock); > wait_for_completion(&smgr->update_done); > > diff --git a/include/linux/fpga/fpga-sec-mgr.h b/include/linux/fpga/fpga-sec-mgr.h > index 6b7b8a3d6aac..0e1f50434024 100644 > --- a/include/linux/fpga/fpga-sec-mgr.h > +++ b/include/linux/fpga/fpga-sec-mgr.h > @@ -72,6 +72,7 @@ struct fpga_sec_mgr { > enum fpga_sec_prog progress; > enum fpga_sec_prog err_state; /* progress state at time of failure */ > enum fpga_sec_err err_code; /* security manager error code */ > + bool request_cancel; > bool driver_unload; > void *priv; > }; > -- > 2.25.1 > Looks good, Moritz
diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr index c5d0b9d7c7e4..749f2d4c78d3 100644 --- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr +++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr @@ -17,6 +17,16 @@ Description: Write only. Write the filename of an image and Root Entry Hashes, and to cancel Code Signing Keys (CSK). +What: /sys/class/fpga_sec_mgr/fpga_secX/update/cancel +Date: June 2021 +KernelVersion: 5.14 +Contact: Russ Weight <russell.h.weight@intel.com> +Description: Write-only. Write a "1" to this file to request + that a current update be canceled. This request + will be rejected (EBUSY) if the programming phase + has already started or (ENODEV) if there is no + update in progress. + What: /sys/class/fpga_sec_mgr/fpga_secX/update/status Date: June 2021 KernelVersion: 5.14 diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c index 2487042ace82..35bd419bd3b9 100644 --- a/drivers/fpga/fpga-sec-mgr.c +++ b/drivers/fpga/fpga-sec-mgr.c @@ -43,6 +43,23 @@ static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr, smgr->sops->cancel(smgr); } +static int progress_transition(struct fpga_sec_mgr *smgr, + enum fpga_sec_prog new_progress) +{ + int ret = 0; + + mutex_lock(&smgr->lock); + if (smgr->request_cancel) { + set_error(smgr, FPGA_SEC_ERR_CANCELED); + smgr->sops->cancel(smgr); + ret = -ECANCELED; + } else { + update_progress(smgr, new_progress); + } + mutex_unlock(&smgr->lock); + return ret; +} + static void progress_complete(struct fpga_sec_mgr *smgr) { mutex_lock(&smgr->lock); @@ -74,15 +91,19 @@ static void fpga_sec_mgr_update(struct work_struct *work) goto release_fw_exit; } - update_progress(smgr, FPGA_SEC_PROG_PREPARING); + if (progress_transition(smgr, FPGA_SEC_PROG_PREPARING)) + goto modput_exit; + ret = smgr->sops->prepare(smgr); if (ret != FPGA_SEC_ERR_NONE) { fpga_sec_dev_error(smgr, ret); goto modput_exit; } - update_progress(smgr, FPGA_SEC_PROG_WRITING); - while (smgr->remaining_size) { + if (progress_transition(smgr, FPGA_SEC_PROG_WRITING)) + goto done; + + while (smgr->remaining_size && !smgr->request_cancel) { ret = smgr->sops->write_blk(smgr, offset); if (ret != FPGA_SEC_ERR_NONE) { fpga_sec_dev_error(smgr, ret); @@ -92,7 +113,9 @@ static void fpga_sec_mgr_update(struct work_struct *work) offset = fw->size - smgr->remaining_size; } - update_progress(smgr, FPGA_SEC_PROG_PROGRAMMING); + if (progress_transition(smgr, FPGA_SEC_PROG_PROGRAMMING)) + goto done; + ret = smgr->sops->poll_complete(smgr); if (ret != FPGA_SEC_ERR_NONE) fpga_sec_dev_error(smgr, ret); @@ -229,6 +252,7 @@ static ssize_t filename_store(struct device *dev, struct device_attribute *attr, } smgr->err_code = FPGA_SEC_ERR_NONE; + smgr->request_cancel = false; smgr->progress = FPGA_SEC_PROG_READING; reinit_completion(&smgr->update_done); schedule_work(&smgr->work); @@ -239,8 +263,32 @@ static ssize_t filename_store(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_WO(filename); +static ssize_t cancel_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fpga_sec_mgr *smgr = to_sec_mgr(dev); + bool cancel; + int ret = count; + + if (kstrtobool(buf, &cancel) || !cancel) + return -EINVAL; + + mutex_lock(&smgr->lock); + if (smgr->progress == FPGA_SEC_PROG_PROGRAMMING) + ret = -EBUSY; + else if (smgr->progress == FPGA_SEC_PROG_IDLE) + ret = -ENODEV; + else + smgr->request_cancel = true; + mutex_unlock(&smgr->lock); + + return ret; +} +static DEVICE_ATTR_WO(cancel); + static struct attribute *sec_mgr_update_attrs[] = { &dev_attr_filename.attr, + &dev_attr_cancel.attr, &dev_attr_status.attr, &dev_attr_error.attr, &dev_attr_remaining_size.attr, @@ -464,6 +512,9 @@ void fpga_sec_mgr_unregister(struct fpga_sec_mgr *smgr) goto unregister; } + if (smgr->progress != FPGA_SEC_PROG_PROGRAMMING) + smgr->request_cancel = true; + mutex_unlock(&smgr->lock); wait_for_completion(&smgr->update_done); diff --git a/include/linux/fpga/fpga-sec-mgr.h b/include/linux/fpga/fpga-sec-mgr.h index 6b7b8a3d6aac..0e1f50434024 100644 --- a/include/linux/fpga/fpga-sec-mgr.h +++ b/include/linux/fpga/fpga-sec-mgr.h @@ -72,6 +72,7 @@ struct fpga_sec_mgr { enum fpga_sec_prog progress; enum fpga_sec_prog err_state; /* progress state at time of failure */ enum fpga_sec_err err_code; /* security manager error code */ + bool request_cancel; bool driver_unload; void *priv; };