acpi/nfit, libnvdimm: Introduce nvdimm_security_ops

Some NVDIMMs, like the ones defined by the NVDIMM_FAMILY_INTEL command
set, expose a security capability to lock the DIMMs at poweroff and
require a passphrase to unlock them. The security model is derived from
ATA security. In anticipation of other DIMMs implementing a similar
scheme, and to abstract the core security implementation away from the
device-specific details, introduce nvdimm_security_ops.

Initially only a status retrieval operation, ->state(), is defined,
along with the base infrastructure and definitions for future
operations.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Co-developed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Dave Jiang
2018-12-05 23:39:29 -08:00
committed by Dan Williams
parent 9db67581b9
commit f298939655
9 changed files with 158 additions and 4 deletions

View File

@@ -370,23 +370,60 @@ static ssize_t available_slots_show(struct device *dev,
}
static DEVICE_ATTR_RO(available_slots);
static ssize_t security_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct nvdimm *nvdimm = to_nvdimm(dev);
switch (nvdimm->sec.state) {
case NVDIMM_SECURITY_DISABLED:
return sprintf(buf, "disabled\n");
case NVDIMM_SECURITY_UNLOCKED:
return sprintf(buf, "unlocked\n");
case NVDIMM_SECURITY_LOCKED:
return sprintf(buf, "locked\n");
case NVDIMM_SECURITY_FROZEN:
return sprintf(buf, "frozen\n");
case NVDIMM_SECURITY_OVERWRITE:
return sprintf(buf, "overwrite\n");
}
return -ENOTTY;
}
static DEVICE_ATTR_RO(security);
static struct attribute *nvdimm_attributes[] = {
&dev_attr_state.attr,
&dev_attr_flags.attr,
&dev_attr_commands.attr,
&dev_attr_available_slots.attr,
&dev_attr_security.attr,
NULL,
};
static umode_t nvdimm_visible(struct kobject *kobj, struct attribute *a, int n)
{
struct device *dev = container_of(kobj, typeof(*dev), kobj);
struct nvdimm *nvdimm = to_nvdimm(dev);
if (a != &dev_attr_security.attr)
return a->mode;
if (nvdimm->sec.state < 0)
return 0;
return a->mode;
}
struct attribute_group nvdimm_attribute_group = {
.attrs = nvdimm_attributes,
.is_visible = nvdimm_visible,
};
EXPORT_SYMBOL_GPL(nvdimm_attribute_group);
struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
void *provider_data, const struct attribute_group **groups,
unsigned long flags, unsigned long cmd_mask, int num_flush,
struct resource *flush_wpq, const char *dimm_id)
struct resource *flush_wpq, const char *dimm_id,
const struct nvdimm_security_ops *sec_ops)
{
struct nvdimm *nvdimm = kzalloc(sizeof(*nvdimm), GFP_KERNEL);
struct device *dev;
@@ -413,6 +450,12 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
dev->type = &nvdimm_device_type;
dev->devt = MKDEV(nvdimm_major, nvdimm->id);
dev->groups = groups;
nvdimm->sec.ops = sec_ops;
/*
* Security state must be initialized before device_add() for
* attribute visibility.
*/
nvdimm->sec.state = nvdimm_security_state(nvdimm);
nd_device_register(dev);
return nvdimm;