Message ID | 20230224194652.1990604-5-dave@stgolabs.net |
---|---|
State | Superseded |
Headers | show |
Series | cxl: Background cmds and device sanitation | expand |
On 2/24/23 12:46 PM, Davidlohr Bueso wrote: > Implement support for the non-pmem exclusive sanitize (aka overwrite), > per CXL specs. This is the baseline for the sanitize-on-release > functionality. > > To properly support this feature, create a 'security/sanitize' sysfs > file that when read will list the current pmem security state and > when written to, perform the requested operation. I think this segment needs to be updated? The attrib is write only from the code below. DJ > > This operation can run in the background and the driver must wait > for completion (no timeout), where the poller will awake every > ~10 seconds (this could be further based on the size of the device). > > Signed-off-by: Davidlohr Bueso <dave@stgolabs.net> > --- > Documentation/ABI/testing/sysfs-bus-cxl | 14 ++++++ > drivers/cxl/core/mbox.c | 61 +++++++++++++++++++++++++ > drivers/cxl/core/memdev.c | 39 ++++++++++++++++ > drivers/cxl/cxlmem.h | 2 + > 4 files changed, 116 insertions(+) > > diff --git a/Documentation/ABI/testing/sysfs-bus-cxl b/Documentation/ABI/testing/sysfs-bus-cxl > index e9c432a5a841..b315d78b7e91 100644 > --- a/Documentation/ABI/testing/sysfs-bus-cxl > +++ b/Documentation/ABI/testing/sysfs-bus-cxl > @@ -66,6 +66,20 @@ Description: > are available: frozen, locked, unlocked and disabled (which > is also the case for any unsupported security features). > > +What: /sys/bus/cxl/devices/memX/security/sanitize > +Date: February, 2023 > +KernelVersion: v6.4 > +Contact: linux-cxl@vger.kernel.org > +Description: > + (WO) Write a boolean 'true' string value to this attribute to > + sanitize the device to securely re-purpose or decommission it. > + This is done by ensuring that all user data and meta-data, > + whether it resides in persistent capacity, volatile capacity, > + or the LSA, is made permanently unavailable by whatever means > + is appropriate for the media type. This causes all CPU caches > + to be flushed. If this sysfs entry is not present then the > + architecture does not support security features. > + > What: /sys/bus/cxl/devices/*/devtype > Date: June, 2021 > KernelVersion: v5.14 > diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c > index f2addb457172..885de3506735 100644 > --- a/drivers/cxl/core/mbox.c > +++ b/drivers/cxl/core/mbox.c > @@ -1,6 +1,7 @@ > // SPDX-License-Identifier: GPL-2.0-only > /* Copyright(c) 2020 Intel Corporation. All rights reserved. */ > #include <linux/io-64-nonatomic-lo-hi.h> > +#include <linux/memregion.h> > #include <linux/security.h> > #include <linux/debugfs.h> > #include <linux/ktime.h> > @@ -1021,6 +1022,66 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds) > } > EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, CXL); > > +/** > + * cxl_mem_sanitize() - Send sanitation (aka overwrite) command to the device. > + * @cxlds: The device data for the operation > + * > + * Return: 0 if the command was executed successfully, regardless of > + * whether or not the actual security operation is done in the background. > + * Upon error, return the result of the mailbox command or -EINVAL if > + * security requirements are not met. CPU caches are flushed before and > + * after succesful completion of each command. > + * > + * See CXL 3.0 @8.2.9.8.5.1 Sanitize. > + */ > +int cxl_mem_sanitize(struct cxl_dev_state *cxlds) > +{ > + int rc; > + u32 sec_out = 0; > + struct cxl_get_security_output { > + __le32 flags; > + } out; > + struct cxl_mbox_cmd sec_cmd = { > + .opcode = CXL_MBOX_OP_GET_SECURITY_STATE, > + .payload_out = &out, > + .size_out = sizeof(out), > + }; > + struct cxl_mbox_cmd mbox_cmd = { > + .opcode = CXL_MBOX_OP_SANITIZE, > + .poll_interval = 10000UL, > + }; > + > + if (!cpu_cache_has_invalidate_memregion()) > + return -EINVAL; > + > + rc = cxl_internal_send_cmd(cxlds, &sec_cmd); > + if (rc < 0) { > + dev_err(cxlds->dev, "Failed to get security state : %d", rc); > + return rc; > + } > + > + /* > + * Prior to using these commands, any security applied to > + * the user data areas of the device shall be DISABLED (or > + * UNLOCKED for secure erase case). > + */ > + sec_out = le32_to_cpu(out.flags); > + if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET) > + return -EINVAL; > + > + cpu_cache_invalidate_memregion(IORES_DESC_CXL); > + > + rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); > + if (rc < 0) { > + dev_err(cxlds->dev, "Failed to sanitize device : %d", rc); > + return rc; > + } > + > + cpu_cache_invalidate_memregion(IORES_DESC_CXL); > + return 0; > +} > +EXPORT_SYMBOL_NS_GPL(cxl_mem_sanitize, CXL); > + > static int add_dpa_res(struct device *dev, struct resource *parent, > struct resource *res, resource_size_t start, > resource_size_t size, const char *type) > diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c > index 68c0ab06b999..a1bb095d081c 100644 > --- a/drivers/cxl/core/memdev.c > +++ b/drivers/cxl/core/memdev.c > @@ -127,6 +127,34 @@ static ssize_t security_state_show(struct device *dev, > static struct device_attribute dev_attr_security_state = > __ATTR(state, 0444, security_state_show, NULL); > > +static ssize_t security_sanitize_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t len) > +{ > + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); > + struct cxl_dev_state *cxlds = cxlmd->cxlds; > + ssize_t rc; > + bool sanitize; > + > + rc = kstrtobool(buf, &sanitize); > + if (rc) > + return rc; > + > + if (sanitize) { > + if (cxl_memdev_active_region(cxlmd)) > + return -EBUSY; > + > + rc = cxl_mem_sanitize(cxlds); > + } > + > + if (rc == 0) > + rc = len; > + return rc; > +} > + > +static struct device_attribute dev_attr_security_sanitize = > + __ATTR(sanitize, 0200, NULL, security_sanitize_store); > + > static ssize_t serial_show(struct device *dev, struct device_attribute *attr, > char *buf) > { > @@ -188,11 +216,22 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = { > > static struct attribute *cxl_memdev_security_attributes[] = { > &dev_attr_security_state.attr, > + &dev_attr_security_sanitize.attr, > NULL, > }; > > +static umode_t cxl_security_visible(struct kobject *kobj, > + struct attribute *a, int n) > +{ > + if (!cpu_cache_has_invalidate_memregion() && > + a == &dev_attr_security_sanitize.attr) > + return 0; > + return a->mode; > +} > + > static struct attribute_group cxl_memdev_security_attribute_group = { > .name = "security", > + .is_visible = cxl_security_visible, > .attrs = cxl_memdev_security_attributes, > }; > > diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h > index 4e31f3234519..0d2009b36933 100644 > --- a/drivers/cxl/cxlmem.h > +++ b/drivers/cxl/cxlmem.h > @@ -631,6 +631,8 @@ static inline void cxl_mem_active_dec(void) > } > #endif > > +int cxl_mem_sanitize(struct cxl_dev_state *cxlds); > + > struct cxl_hdm { > struct cxl_component_regs regs; > unsigned int decoder_count;
On Tue, 28 Feb 2023, Dave Jiang wrote: >On 2/24/23 12:46 PM, Davidlohr Bueso wrote: >>Implement support for the non-pmem exclusive sanitize (aka overwrite), >>per CXL specs. This is the baseline for the sanitize-on-release >>functionality. >> >>To properly support this feature, create a 'security/sanitize' sysfs >>file that when read will list the current pmem security state and >>when written to, perform the requested operation. > >I think this segment needs to be updated? The attrib is write only >from the code below. Bleh, indeed both commands need the changelog updated, these are intended to be write-only. Thanks, Davidlohr
Hi Davidlohr, Davidlohr Bueso wrote: > Implement support for the non-pmem exclusive sanitize (aka overwrite), > per CXL specs. This is the baseline for the sanitize-on-release > functionality. Wait, what sanitize-on-release functionality? The DCD facility to sanitize-on-release (CXL 3.0 Table 8-126. DC Region Configuration) is indepdent of background command functionality, i.e. "Release Dynamic Capacity" is a foreground operation. > To properly support this feature, create a 'security/sanitize' sysfs > file that when read will list the current pmem security state and > when written to, perform the requested operation. Sanitize (command set 0x44) is independent of the pmem security state (command set 0x45), and I thought patch2 will list the current pmem security state via security/state. > This operation can run in the background and the driver must wait > for completion (no timeout), where the poller will awake every > ~10 seconds (this could be further based on the size of the device). Per the feedback on 1 this changes to be a facility that returns immediately and signals completion via sysfs_notify_dirent() because if it takes seconds and is hardware uninterruptible then that warrants userspace being able to poll for completion if it wants. > Signed-off-by: Davidlohr Bueso <dave@stgolabs.net> > --- > Documentation/ABI/testing/sysfs-bus-cxl | 14 ++++++ > drivers/cxl/core/mbox.c | 61 +++++++++++++++++++++++++ > drivers/cxl/core/memdev.c | 39 ++++++++++++++++ > drivers/cxl/cxlmem.h | 2 + > 4 files changed, 116 insertions(+) > > diff --git a/Documentation/ABI/testing/sysfs-bus-cxl b/Documentation/ABI/testing/sysfs-bus-cxl > index e9c432a5a841..b315d78b7e91 100644 > --- a/Documentation/ABI/testing/sysfs-bus-cxl > +++ b/Documentation/ABI/testing/sysfs-bus-cxl > @@ -66,6 +66,20 @@ Description: > are available: frozen, locked, unlocked and disabled (which > is also the case for any unsupported security features). > > +What: /sys/bus/cxl/devices/memX/security/sanitize > +Date: February, 2023 > +KernelVersion: v6.4 > +Contact: linux-cxl@vger.kernel.org > +Description: > + (WO) Write a boolean 'true' string value to this attribute to > + sanitize the device to securely re-purpose or decommission it. > + This is done by ensuring that all user data and meta-data, > + whether it resides in persistent capacity, volatile capacity, > + or the LSA, is made permanently unavailable by whatever means > + is appropriate for the media type. This causes all CPU caches > + to be flushed. If this sysfs entry is not present then the > + architecture does not support security features. > + > What: /sys/bus/cxl/devices/*/devtype > Date: June, 2021 > KernelVersion: v5.14 > diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c > index f2addb457172..885de3506735 100644 > --- a/drivers/cxl/core/mbox.c > +++ b/drivers/cxl/core/mbox.c > @@ -1,6 +1,7 @@ > // SPDX-License-Identifier: GPL-2.0-only > /* Copyright(c) 2020 Intel Corporation. All rights reserved. */ > #include <linux/io-64-nonatomic-lo-hi.h> > +#include <linux/memregion.h> > #include <linux/security.h> > #include <linux/debugfs.h> > #include <linux/ktime.h> > @@ -1021,6 +1022,66 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds) > } > EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, CXL); > > +/** > + * cxl_mem_sanitize() - Send sanitation (aka overwrite) command to the device. > + * @cxlds: The device data for the operation > + * > + * Return: 0 if the command was executed successfully, regardless of > + * whether or not the actual security operation is done in the background. > + * Upon error, return the result of the mailbox command or -EINVAL if > + * security requirements are not met. CPU caches are flushed before and > + * after succesful completion of each command. > + * > + * See CXL 3.0 @8.2.9.8.5.1 Sanitize. > + */ > +int cxl_mem_sanitize(struct cxl_dev_state *cxlds) > +{ > + int rc; > + u32 sec_out = 0; > + struct cxl_get_security_output { > + __le32 flags; > + } out; > + struct cxl_mbox_cmd sec_cmd = { > + .opcode = CXL_MBOX_OP_GET_SECURITY_STATE, > + .payload_out = &out, > + .size_out = sizeof(out), > + }; > + struct cxl_mbox_cmd mbox_cmd = { > + .opcode = CXL_MBOX_OP_SANITIZE, > + .poll_interval = 10000UL, > + }; > + > + if (!cpu_cache_has_invalidate_memregion()) > + return -EINVAL; Given that the regions are already offline I think there is no additional damage to allow santize to go through, because they could not be dynamically re-enabled. > + > + rc = cxl_internal_send_cmd(cxlds, &sec_cmd); > + if (rc < 0) { > + dev_err(cxlds->dev, "Failed to get security state : %d", rc); > + return rc; > + } > + > + /* > + * Prior to using these commands, any security applied to > + * the user data areas of the device shall be DISABLED (or > + * UNLOCKED for secure erase case). > + */ > + sec_out = le32_to_cpu(out.flags); > + if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET) > + return -EINVAL; > + > + cpu_cache_invalidate_memregion(IORES_DESC_CXL); Given that sanitize mandates bouncing the decoders the reconnect will set CXL_REGION_F_INCOHERENT in attach_target(), I think it is safe to assume that caches will be managed before the sanitized data will be ingested by anything. Specifically, I notice that attach_target() sets CXL_REGION_F_INCOHERENT in the region creation and autodiscovery case. The latter is a bug that I'll fix up. It should only be set when the chance the HPA-to-DPA mapping has changed, or the contents of the DPA has changed in a cache incoherent manner. The fact that sanitize mandates what appears to be an HPA-to-DPA change then no need to manage caches explicitly. > + > + rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); > + if (rc < 0) { > + dev_err(cxlds->dev, "Failed to sanitize device : %d", rc); > + return rc; > + } > + > + cpu_cache_invalidate_memregion(IORES_DESC_CXL); > + return 0; > +} > +EXPORT_SYMBOL_NS_GPL(cxl_mem_sanitize, CXL); > + > static int add_dpa_res(struct device *dev, struct resource *parent, > struct resource *res, resource_size_t start, > resource_size_t size, const char *type) > diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c > index 68c0ab06b999..a1bb095d081c 100644 > --- a/drivers/cxl/core/memdev.c > +++ b/drivers/cxl/core/memdev.c > @@ -127,6 +127,34 @@ static ssize_t security_state_show(struct device *dev, > static struct device_attribute dev_attr_security_state = > __ATTR(state, 0444, security_state_show, NULL); > > +static ssize_t security_sanitize_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t len) > +{ > + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); > + struct cxl_dev_state *cxlds = cxlmd->cxlds; > + ssize_t rc; > + bool sanitize; > + > + rc = kstrtobool(buf, &sanitize); > + if (rc) > + return rc; > + > + if (sanitize) { > + if (cxl_memdev_active_region(cxlmd)) > + return -EBUSY; > + > + rc = cxl_mem_sanitize(cxlds); > + } > + > + if (rc == 0) > + rc = len; > + return rc; > +} > + > +static struct device_attribute dev_attr_security_sanitize = > + __ATTR(sanitize, 0200, NULL, security_sanitize_store); > + DEVICE_ATTR_RW() to poll(2) for completion. > static ssize_t serial_show(struct device *dev, struct device_attribute *attr, > char *buf) > { > @@ -188,11 +216,22 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = { > > static struct attribute *cxl_memdev_security_attributes[] = { > &dev_attr_security_state.attr, > + &dev_attr_security_sanitize.attr, > NULL, > }; > > +static umode_t cxl_security_visible(struct kobject *kobj, > + struct attribute *a, int n) > +{ > + if (!cpu_cache_has_invalidate_memregion() && > + a == &dev_attr_security_sanitize.attr) No need to hide the attribute given the above discussion about invalidation being done somewhere else. > + return 0; > + return a->mode; > +} > + > static struct attribute_group cxl_memdev_security_attribute_group = { > .name = "security", > + .is_visible = cxl_security_visible, > .attrs = cxl_memdev_security_attributes, > }; > > diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h > index 4e31f3234519..0d2009b36933 100644 > --- a/drivers/cxl/cxlmem.h > +++ b/drivers/cxl/cxlmem.h > @@ -631,6 +631,8 @@ static inline void cxl_mem_active_dec(void) > } > #endif > > +int cxl_mem_sanitize(struct cxl_dev_state *cxlds); > + > struct cxl_hdm { > struct cxl_component_regs regs; > unsigned int decoder_count; > -- > 2.39.2 >
On Mon, 27 Mar 2023, Dan Williams wrote: >Per the feedback on 1 this changes to be a facility that returns >immediately and signals completion via sysfs_notify_dirent() because if >it takes seconds and is hardware uninterruptible then that warrants >userspace being able to poll for completion if it wants. Perhaps I'm missing something here, but how can we signal completion for sanitation if we return immediately (after timing out) and loose context of the background command? Or are you referring to use the Background Operation Status command (0002h), which afaict would be the only way to do this, as nvdimm's overwrite_query. But as we've discussed in the past, this also means that another bg command could occur in between when the command finished and the query is done. Thanks, Davidlohr
Davidlohr Bueso wrote: > On Mon, 27 Mar 2023, Dan Williams wrote: > > >Per the feedback on 1 this changes to be a facility that returns > >immediately and signals completion via sysfs_notify_dirent() because if > >it takes seconds and is hardware uninterruptible then that warrants > >userspace being able to poll for completion if it wants. > > Perhaps I'm missing something here, but how can we signal completion > for sanitation if we return immediately (after timing out) and loose > context of the background command? Or are you referring to use the > Background Operation Status command (0002h), which afaict would be > the only way to do this, as nvdimm's overwrite_query. But as we've > discussed in the past, this also means that another bg command could > occur in between when the command finished and the query is done. The observation is that sanitation is special compared to other background commands. It's so special that it gets to skip the normal rules that background commands are parceled into tiny pieces to prevent monopolization of the background command slot. Sanitization monopolizes the device by definition. Given that sanitation is going to take on the order of seconds, don't trap the submitter in uninterruptible sleep. Instead, put the mailbox into "santizing" mode, and return immediately after sanitation is started. In "sanitizing" mode. New background command submissions fail immediately with EBUSY (as opposed to queuing because sanitization destoys the device's context). The end of sanitization mode occurs when the completion interrupt fires, or a kernel polling thread notices the completion (in case the device does not implement background command completion interrupts). When that happens the mailbox exits "sanitizing" mode and reflects the completion status in the sysfs file that was used trigger sanitization. When that state changes sysfs_notify_dirent() tells userspace that the sysfs status has changed in case userspace actually wanted to go to sleep while awaiting the completion rather than live polling (but that sleep is interruptible and resumable if userspace wants). This is similar to what happens with address range scrubs in the ACPI NFIT driver. See drivers/acpi/nfit/core.c::notify_ars_done(). Think of this like O_ASYNC semantics for sysfs files that trigger long running operations.
diff --git a/Documentation/ABI/testing/sysfs-bus-cxl b/Documentation/ABI/testing/sysfs-bus-cxl index e9c432a5a841..b315d78b7e91 100644 --- a/Documentation/ABI/testing/sysfs-bus-cxl +++ b/Documentation/ABI/testing/sysfs-bus-cxl @@ -66,6 +66,20 @@ Description: are available: frozen, locked, unlocked and disabled (which is also the case for any unsupported security features). +What: /sys/bus/cxl/devices/memX/security/sanitize +Date: February, 2023 +KernelVersion: v6.4 +Contact: linux-cxl@vger.kernel.org +Description: + (WO) Write a boolean 'true' string value to this attribute to + sanitize the device to securely re-purpose or decommission it. + This is done by ensuring that all user data and meta-data, + whether it resides in persistent capacity, volatile capacity, + or the LSA, is made permanently unavailable by whatever means + is appropriate for the media type. This causes all CPU caches + to be flushed. If this sysfs entry is not present then the + architecture does not support security features. + What: /sys/bus/cxl/devices/*/devtype Date: June, 2021 KernelVersion: v5.14 diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index f2addb457172..885de3506735 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright(c) 2020 Intel Corporation. All rights reserved. */ #include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/memregion.h> #include <linux/security.h> #include <linux/debugfs.h> #include <linux/ktime.h> @@ -1021,6 +1022,66 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds) } EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, CXL); +/** + * cxl_mem_sanitize() - Send sanitation (aka overwrite) command to the device. + * @cxlds: The device data for the operation + * + * Return: 0 if the command was executed successfully, regardless of + * whether or not the actual security operation is done in the background. + * Upon error, return the result of the mailbox command or -EINVAL if + * security requirements are not met. CPU caches are flushed before and + * after succesful completion of each command. + * + * See CXL 3.0 @8.2.9.8.5.1 Sanitize. + */ +int cxl_mem_sanitize(struct cxl_dev_state *cxlds) +{ + int rc; + u32 sec_out = 0; + struct cxl_get_security_output { + __le32 flags; + } out; + struct cxl_mbox_cmd sec_cmd = { + .opcode = CXL_MBOX_OP_GET_SECURITY_STATE, + .payload_out = &out, + .size_out = sizeof(out), + }; + struct cxl_mbox_cmd mbox_cmd = { + .opcode = CXL_MBOX_OP_SANITIZE, + .poll_interval = 10000UL, + }; + + if (!cpu_cache_has_invalidate_memregion()) + return -EINVAL; + + rc = cxl_internal_send_cmd(cxlds, &sec_cmd); + if (rc < 0) { + dev_err(cxlds->dev, "Failed to get security state : %d", rc); + return rc; + } + + /* + * Prior to using these commands, any security applied to + * the user data areas of the device shall be DISABLED (or + * UNLOCKED for secure erase case). + */ + sec_out = le32_to_cpu(out.flags); + if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET) + return -EINVAL; + + cpu_cache_invalidate_memregion(IORES_DESC_CXL); + + rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + if (rc < 0) { + dev_err(cxlds->dev, "Failed to sanitize device : %d", rc); + return rc; + } + + cpu_cache_invalidate_memregion(IORES_DESC_CXL); + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_mem_sanitize, CXL); + static int add_dpa_res(struct device *dev, struct resource *parent, struct resource *res, resource_size_t start, resource_size_t size, const char *type) diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 68c0ab06b999..a1bb095d081c 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -127,6 +127,34 @@ static ssize_t security_state_show(struct device *dev, static struct device_attribute dev_attr_security_state = __ATTR(state, 0444, security_state_show, NULL); +static ssize_t security_sanitize_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + ssize_t rc; + bool sanitize; + + rc = kstrtobool(buf, &sanitize); + if (rc) + return rc; + + if (sanitize) { + if (cxl_memdev_active_region(cxlmd)) + return -EBUSY; + + rc = cxl_mem_sanitize(cxlds); + } + + if (rc == 0) + rc = len; + return rc; +} + +static struct device_attribute dev_attr_security_sanitize = + __ATTR(sanitize, 0200, NULL, security_sanitize_store); + static ssize_t serial_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -188,11 +216,22 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = { static struct attribute *cxl_memdev_security_attributes[] = { &dev_attr_security_state.attr, + &dev_attr_security_sanitize.attr, NULL, }; +static umode_t cxl_security_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + if (!cpu_cache_has_invalidate_memregion() && + a == &dev_attr_security_sanitize.attr) + return 0; + return a->mode; +} + static struct attribute_group cxl_memdev_security_attribute_group = { .name = "security", + .is_visible = cxl_security_visible, .attrs = cxl_memdev_security_attributes, }; diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 4e31f3234519..0d2009b36933 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -631,6 +631,8 @@ static inline void cxl_mem_active_dec(void) } #endif +int cxl_mem_sanitize(struct cxl_dev_state *cxlds); + struct cxl_hdm { struct cxl_component_regs regs; unsigned int decoder_count;
Implement support for the non-pmem exclusive sanitize (aka overwrite), per CXL specs. This is the baseline for the sanitize-on-release functionality. To properly support this feature, create a 'security/sanitize' sysfs file that when read will list the current pmem security state and when written to, perform the requested operation. This operation can run in the background and the driver must wait for completion (no timeout), where the poller will awake every ~10 seconds (this could be further based on the size of the device). Signed-off-by: Davidlohr Bueso <dave@stgolabs.net> --- Documentation/ABI/testing/sysfs-bus-cxl | 14 ++++++ drivers/cxl/core/mbox.c | 61 +++++++++++++++++++++++++ drivers/cxl/core/memdev.c | 39 ++++++++++++++++ drivers/cxl/cxlmem.h | 2 + 4 files changed, 116 insertions(+)