Thanks,
Davidlohr
-----<8----------------------------------------------------
[PATCH 16/15] cxl/mbox: Add "Secure Erase" security command support
To properly support this feature, create a 'security' sysfs
file that when read will list the current pmem security state,
and when written to, perform the requested operation (only
secure erase is currently supported).
Signed-off-by: Davidlohr Bueso <d...@stgolabs.net>
---
Documentation/ABI/testing/sysfs-bus-cxl | 13 +++++++
drivers/cxl/core/mbox.c | 44 +++++++++++++++++++++
drivers/cxl/core/memdev.c | 51 +++++++++++++++++++++++++
drivers/cxl/cxlmem.h | 3 ++
4 files changed, 111 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-cxl
b/Documentation/ABI/testing/sysfs-bus-cxl
index 7c2b846521f3..ca5216b37bcf 100644
--- a/Documentation/ABI/testing/sysfs-bus-cxl
+++ b/Documentation/ABI/testing/sysfs-bus-cxl
@@ -52,6 +52,19 @@ Description:
host PCI device for this memory device, emit the CPU node
affinity for this device.
+What: /sys/bus/cxl/devices/memX/security
+Date: July, 2022
+KernelVersion: v5.21
+Contact: linux-...@vger.kernel.org
+Description:
+ Reading this file will display the security state for that
+ device. The following states are available: disabled, frozen,
+ locked and unlocked. When writing to the file, the following
+ command(s) are supported:
+ erase - Secure Erase user data by changing the media encryption
+ keys for all user data areas of the device. This causes
+ all CPU caches to be flushed.
+
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 54f434733b56..54b4aec615ee 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -787,6 +787,50 @@ int cxl_dev_state_identify(struct cxl_dev_state
*cxlds)
}
EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, CXL);
+/**
+ * cxl_mem_sanitize() - Send sanitation related commands to the device.
+ * @cxlds: The device data for the operation
+ * @cmd: The command opcode to send
+ *
+ * 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.
+ *
+ * See CXL 2.0 @8.2.9.5.5 Sanitize.
+ */
+int cxl_mem_sanitize(struct cxl_dev_state *cxlds, enum cxl_opcode cmd)
+{
+ int rc;
+ u32 sec_out;
+
+ /* TODO: CXL_MBOX_OP_SECURE_SANITIZE */
+ if (cmd != CXL_MBOX_OP_SECURE_ERASE)
+ return -EINVAL;
+
+ rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_GET_SECURITY_STATE,
+ NULL, 0, &sec_out, sizeof(sec_out));
+ if (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).
+ */
+ if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET ||
+ sec_out & CXL_PMEM_SEC_STATE_LOCKED)
+ return -EINVAL;
+
+ rc = cxl_mbox_send_cmd(cxlds, cmd, NULL, 0, NULL, 0);
+ if (rc == 0) {
+ /* flush all CPU caches before we read it */
+ flush_cache_all();
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_mem_sanitize, CXL);
+
int cxl_mem_create_range_info(struct cxl_dev_state *cxlds)
{
int rc;
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index f7cdcd33504a..13563facfd62 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -106,12 +106,63 @@ static ssize_t numa_node_show(struct device
*dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(numa_node);
+#define CXL_SEC_CMD_SIZE 32
+
+static ssize_t security_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ u32 sec_out;
+ int rc;
+
+ rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_GET_SECURITY_STATE,
+ NULL, 0, &sec_out, sizeof(sec_out));
+ if (rc)
+ return rc;
+
+ if (!(sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET))
+ return sprintf(buf, "disabled\n");
+ if (sec_out & CXL_PMEM_SEC_STATE_FROZEN)
+ return sprintf(buf, "frozen\n");
+ if (sec_out & CXL_PMEM_SEC_STATE_LOCKED)
+ return sprintf(buf, "locked\n");
+ else
+ return sprintf(buf, "unlocked\n");
+}
+
+static ssize_t security_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;
+ char cmd[CXL_SEC_CMD_SIZE+1];
+ ssize_t rc;
+
+ rc = sscanf(buf, "%"__stringify(CXL_SEC_CMD_SIZE)"s", cmd);
+ if (rc < 1)
+ return -EINVAL;
+
+ if (sysfs_streq(cmd, "erase")) {
+ dev_dbg(dev, "secure-erase\n");
+ rc = cxl_mem_sanitize(cxlds, CXL_MBOX_OP_SECURE_ERASE);
+ } else
+ rc = -EINVAL;
+
+ if (rc == 0)
+ rc = len;
+ return rc;
+}
+static DEVICE_ATTR_RW(security);
+
static struct attribute *cxl_memdev_attributes[] = {
&dev_attr_serial.attr,
&dev_attr_firmware_version.attr,
&dev_attr_payload_max.attr,
&dev_attr_label_storage_size.attr,
&dev_attr_numa_node.attr,
+ &dev_attr_security.attr,
NULL,
};
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index a375a69040d2..cd6650ff757f 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -250,6 +250,7 @@ enum cxl_opcode {
CXL_MBOX_OP_GET_SCAN_MEDIA_CAPS = 0x4303,
CXL_MBOX_OP_SCAN_MEDIA = 0x4304,
CXL_MBOX_OP_GET_SCAN_MEDIA = 0x4305,
+ CXL_MBOX_OP_SECURE_ERASE = 0x4401,
CXL_MBOX_OP_GET_SECURITY_STATE = 0x4500,
CXL_MBOX_OP_SET_PASSPHRASE = 0x4501,
CXL_MBOX_OP_DISABLE_PASSPHRASE = 0x4502,
@@ -348,6 +349,8 @@ struct cxl_mem_command {
#define CXL_CMD_FLAG_FORCE_ENABLE BIT(0)
};
+int cxl_mem_sanitize(struct cxl_dev_state *cxlds, enum cxl_opcode cmd);
+
#define CXL_PMEM_SEC_STATE_USER_PASS_SET 0x01
#define CXL_PMEM_SEC_STATE_MASTER_PASS_SET 0x02
#define CXL_PMEM_SEC_STATE_LOCKED 0x04