summaryrefslogtreecommitdiff
path: root/drivers/acpi/nfit/core.c
diff options
context:
space:
mode:
authorDave Jiang <dave.jiang@intel.com>2018-12-04 10:31:11 -0800
committerDan Williams <dan.j.williams@intel.com>2018-12-04 10:31:11 -0800
commitb3ed2ce024c36054e51cca2eb31a1cdbe4a5f11e (patch)
tree6407ab38fea25437e92ddfbd5cf4104bdcf5b306 /drivers/acpi/nfit/core.c
parent2595646791c319cadfdbf271563aac97d0843dc7 (diff)
acpi/nfit: Add support for Intel DSM 1.8 commands
Add command definition for security commands defined in Intel DSM specification v1.8 [1]. This includes "get security state", "set passphrase", "unlock unit", "freeze lock", "secure erase", "overwrite", "overwrite query", "master passphrase enable/disable", and "master erase", . Since this adds several Intel definitions, move the relevant bits to their own header. These commands mutate physical data, but that manipulation is not cache coherent. The requirement to flush and invalidate caches makes these commands unsuitable to be called from userspace, so extra logic is added to detect and block these commands from being submitted via the ioctl command submission path. Lastly, the commands may contain sensitive key material that should not be dumped in a standard debug session. Update the nvdimm-command payload-dump facility to move security command payloads behind a default-off compile time switch. [1]: http://pmem.io/documents/NVDIMM_DSM_Interface-V1.8.pdf Signed-off-by: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/acpi/nfit/core.c')
-rw-r--r--drivers/acpi/nfit/core.c46
1 files changed, 42 insertions, 4 deletions
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 14d9f5bea015..58fb4ce42548 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -24,6 +24,7 @@
#include <linux/nd.h>
#include <asm/cacheflush.h>
#include <acpi/nfit.h>
+#include "intel.h"
#include "nfit.h"
#include "intel.h"
@@ -380,6 +381,14 @@ static u8 nfit_dsm_revid(unsigned family, unsigned func)
[NVDIMM_INTEL_QUERY_FWUPDATE] = 2,
[NVDIMM_INTEL_SET_THRESHOLD] = 2,
[NVDIMM_INTEL_INJECT_ERROR] = 2,
+ [NVDIMM_INTEL_GET_SECURITY_STATE] = 2,
+ [NVDIMM_INTEL_SET_PASSPHRASE] = 2,
+ [NVDIMM_INTEL_DISABLE_PASSPHRASE] = 2,
+ [NVDIMM_INTEL_UNLOCK_UNIT] = 2,
+ [NVDIMM_INTEL_FREEZE_LOCK] = 2,
+ [NVDIMM_INTEL_SECURE_ERASE] = 2,
+ [NVDIMM_INTEL_OVERWRITE] = 2,
+ [NVDIMM_INTEL_QUERY_OVERWRITE] = 2,
},
};
u8 id;
@@ -394,6 +403,17 @@ static u8 nfit_dsm_revid(unsigned family, unsigned func)
return id;
}
+static bool payload_dumpable(struct nvdimm *nvdimm, unsigned int func)
+{
+ struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
+
+ if (nfit_mem && nfit_mem->family == NVDIMM_FAMILY_INTEL
+ && func >= NVDIMM_INTEL_GET_SECURITY_STATE
+ && func <= NVDIMM_INTEL_MASTER_SECURE_ERASE)
+ return IS_ENABLED(CONFIG_NFIT_SECURITY_DEBUG);
+ return true;
+}
+
int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
{
@@ -478,9 +498,10 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
dev_dbg(dev, "%s cmd: %d: func: %d input length: %d\n",
dimm_name, cmd, func, in_buf.buffer.length);
- print_hex_dump_debug("nvdimm in ", DUMP_PREFIX_OFFSET, 4, 4,
- in_buf.buffer.pointer,
- min_t(u32, 256, in_buf.buffer.length), true);
+ if (payload_dumpable(nvdimm, func))
+ print_hex_dump_debug("nvdimm in ", DUMP_PREFIX_OFFSET, 4, 4,
+ in_buf.buffer.pointer,
+ min_t(u32, 256, in_buf.buffer.length), true);
/* call the BIOS, prefer the named methods over _DSM if available */
if (nvdimm && cmd == ND_CMD_GET_CONFIG_SIZE
@@ -3337,7 +3358,7 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
return 0;
}
-static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
+static int __acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
struct nvdimm *nvdimm, unsigned int cmd)
{
struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
@@ -3359,6 +3380,23 @@ static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
return 0;
}
+/* prevent security commands from being issued via ioctl */
+static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
+ struct nvdimm *nvdimm, unsigned int cmd, void *buf)
+{
+ struct nd_cmd_pkg *call_pkg = buf;
+ unsigned int func;
+
+ if (nvdimm && cmd == ND_CMD_CALL &&
+ call_pkg->nd_family == NVDIMM_FAMILY_INTEL) {
+ func = call_pkg->nd_command;
+ if ((1 << func) & NVDIMM_INTEL_SECURITY_CMDMASK)
+ return -EOPNOTSUPP;
+ }
+
+ return __acpi_nfit_clear_to_send(nd_desc, nvdimm, cmd);
+}
+
int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc,
enum nfit_ars_state req_type)
{