linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff Moyer <jmoyer@redhat.com>
To: Dan Williams <dan.j.williams@intel.com>
Cc: linux-nvdimm@lists.01.org, Dave Jiang <dave.jiang@intel.com>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 1/3] libnvdimm/security: Introduce a 'frozen' attribute
Date: Wed, 28 Aug 2019 13:56:44 -0400	[thread overview]
Message-ID: <x49blw9897n.fsf@segfault.boston.devel.redhat.com> (raw)
In-Reply-To: <156686729474.184120.5835135644278860826.stgit@dwillia2-desk3.amr.corp.intel.com> (Dan Williams's message of "Mon, 26 Aug 2019 17:54:54 -0700")

Dan Williams <dan.j.williams@intel.com> writes:

> In the process of debugging a system with an NVDIMM that was failing to
> unlock it was found that the kernel is reporting 'locked' while the DIMM
> security interface is 'frozen'. Unfortunately the security state is
> tracked internally as an enum which prevents it from communicating the
> difference between 'locked' and 'locked + frozen'. It follows that the
> enum also prevents the kernel from communicating 'unlocked + frozen'
> which would be useful for debugging why security operations like 'change
> passphrase' are disabled.
>
> Ditch the security state enum for a set of flags and introduce a new
> sysfs attribute explicitly for the 'frozen' state. The regression risk
> is low because the 'frozen' state was already blocked behind the
> 'locked' state, but will need to revisit if there were cases where
> applications need 'frozen' to show up in the primary 'security'
> attribute. The expectation is that communicating 'frozen' is mostly a
> helper for debug and status monitoring.
>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reported-by: Jeff Moyer <jmoyer@redhat.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>

Reviewed-by: Jeff Moyer <jmoyer@redhat.com>

> ---
>  drivers/acpi/nfit/intel.c        |   59 ++++++++++++-----------
>  drivers/nvdimm/bus.c             |    2 -
>  drivers/nvdimm/dimm_devs.c       |   59 +++++++++++++----------
>  drivers/nvdimm/nd-core.h         |   21 ++++++--
>  drivers/nvdimm/security.c        |   99 ++++++++++++++++++--------------------
>  include/linux/libnvdimm.h        |    9 ++-
>  tools/testing/nvdimm/dimm_devs.c |   19 ++-----
>  7 files changed, 141 insertions(+), 127 deletions(-)
>
> diff --git a/drivers/acpi/nfit/intel.c b/drivers/acpi/nfit/intel.c
> index cddd0fcf622c..1113b679cd7b 100644
> --- a/drivers/acpi/nfit/intel.c
> +++ b/drivers/acpi/nfit/intel.c
> @@ -7,10 +7,11 @@
>  #include "intel.h"
>  #include "nfit.h"
>  
> -static enum nvdimm_security_state intel_security_state(struct nvdimm *nvdimm,
> +static unsigned long intel_security_flags(struct nvdimm *nvdimm,
>  		enum nvdimm_passphrase_type ptype)
>  {
>  	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
> +	unsigned long security_flags = 0;
>  	struct {
>  		struct nd_cmd_pkg pkg;
>  		struct nd_intel_get_security_state cmd;
> @@ -27,7 +28,7 @@ static enum nvdimm_security_state intel_security_state(struct nvdimm *nvdimm,
>  	int rc;
>  
>  	if (!test_bit(NVDIMM_INTEL_GET_SECURITY_STATE, &nfit_mem->dsm_mask))
> -		return -ENXIO;
> +		return 0;
>  
>  	/*
>  	 * Short circuit the state retrieval while we are doing overwrite.
> @@ -35,38 +36,42 @@ static enum nvdimm_security_state intel_security_state(struct nvdimm *nvdimm,
>  	 * until the overwrite DSM completes.
>  	 */
>  	if (nvdimm_in_overwrite(nvdimm) && ptype == NVDIMM_USER)
> -		return NVDIMM_SECURITY_OVERWRITE;
> +		return BIT(NVDIMM_SECURITY_OVERWRITE);
>  
>  	rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
> -	if (rc < 0)
> -		return rc;
> -	if (nd_cmd.cmd.status)
> -		return -EIO;
> +	if (rc < 0 || nd_cmd.cmd.status) {
> +		pr_err("%s: security state retrieval failed (%d:%#x)\n",
> +				nvdimm_name(nvdimm), rc, nd_cmd.cmd.status);
> +		return 0;
> +	}
>  
>  	/* check and see if security is enabled and locked */
>  	if (ptype == NVDIMM_MASTER) {
>  		if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_ENABLED)
> -			return NVDIMM_SECURITY_UNLOCKED;
> -		else if (nd_cmd.cmd.extended_state &
> -				ND_INTEL_SEC_ESTATE_PLIMIT)
> -			return NVDIMM_SECURITY_FROZEN;
> -	} else {
> -		if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_UNSUPPORTED)
> -			return -ENXIO;
> -		else if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_ENABLED) {
> -			if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_LOCKED)
> -				return NVDIMM_SECURITY_LOCKED;
> -			else if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_FROZEN
> -					|| nd_cmd.cmd.state &
> -					ND_INTEL_SEC_STATE_PLIMIT)
> -				return NVDIMM_SECURITY_FROZEN;
> -			else
> -				return NVDIMM_SECURITY_UNLOCKED;
> -		}
> +			set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
> +		else
> +			set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
> +		if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_PLIMIT)
> +			set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
> +		return security_flags;
>  	}
>  
> -	/* this should cover master security disabled as well */
> -	return NVDIMM_SECURITY_DISABLED;
> +	if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_UNSUPPORTED)
> +		return 0;
> +
> +	if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_ENABLED) {
> +		if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_FROZEN ||
> +		    nd_cmd.cmd.state & ND_INTEL_SEC_STATE_PLIMIT)
> +			set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
> +
> +		if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_LOCKED)
> +			set_bit(NVDIMM_SECURITY_LOCKED, &security_flags);
> +		else
> +			set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
> +	} else
> +		set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
> +
> +	return security_flags;
>  }
>  
>  static int intel_security_freeze(struct nvdimm *nvdimm)
> @@ -371,7 +376,7 @@ static void nvdimm_invalidate_cache(void)
>  #endif
>  
>  static const struct nvdimm_security_ops __intel_security_ops = {
> -	.state = intel_security_state,
> +	.get_flags = intel_security_flags,
>  	.freeze = intel_security_freeze,
>  	.change_key = intel_security_change_key,
>  	.disable = intel_security_disable,
> diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
> index 798c5c4aea9c..29479d3b01b0 100644
> --- a/drivers/nvdimm/bus.c
> +++ b/drivers/nvdimm/bus.c
> @@ -400,7 +400,7 @@ static int child_unregister(struct device *dev, void *data)
>  
>  		/* We are shutting down. Make state frozen artificially. */
>  		nvdimm_bus_lock(dev);
> -		nvdimm->sec.state = NVDIMM_SECURITY_FROZEN;
> +		set_bit(NVDIMM_SECURITY_FROZEN, &nvdimm->sec.flags);
>  		if (test_and_clear_bit(NDD_WORK_PENDING, &nvdimm->flags))
>  			dev_put = true;
>  		nvdimm_bus_unlock(dev);
> diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
> index 29a065e769ea..53330625fe07 100644
> --- a/drivers/nvdimm/dimm_devs.c
> +++ b/drivers/nvdimm/dimm_devs.c
> @@ -372,24 +372,27 @@ __weak ssize_t security_show(struct device *dev,
>  {
>  	struct nvdimm *nvdimm = to_nvdimm(dev);
>  
> -	switch (nvdimm->sec.state) {
> -	case NVDIMM_SECURITY_DISABLED:
> +	if (test_bit(NVDIMM_SECURITY_DISABLED, &nvdimm->sec.flags))
>  		return sprintf(buf, "disabled\n");
> -	case NVDIMM_SECURITY_UNLOCKED:
> +	if (test_bit(NVDIMM_SECURITY_UNLOCKED, &nvdimm->sec.flags))
>  		return sprintf(buf, "unlocked\n");
> -	case NVDIMM_SECURITY_LOCKED:
> +	if (test_bit(NVDIMM_SECURITY_LOCKED, &nvdimm->sec.flags))
>  		return sprintf(buf, "locked\n");
> -	case NVDIMM_SECURITY_FROZEN:
> -		return sprintf(buf, "frozen\n");
> -	case NVDIMM_SECURITY_OVERWRITE:
> +	if (test_bit(NVDIMM_SECURITY_OVERWRITE, &nvdimm->sec.flags))
>  		return sprintf(buf, "overwrite\n");
> -	default:
> -		return -ENOTTY;
> -	}
> -
>  	return -ENOTTY;
>  }
>  
> +static ssize_t frozen_show(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	struct nvdimm *nvdimm = to_nvdimm(dev);
> +
> +	return sprintf(buf, "%d\n", test_bit(NVDIMM_SECURITY_FROZEN,
> +				&nvdimm->sec.flags));
> +}
> +static DEVICE_ATTR_RO(frozen);
> +
>  #define OPS							\
>  	C( OP_FREEZE,		"freeze",		1),	\
>  	C( OP_DISABLE,		"disable",		2),	\
> @@ -501,6 +504,7 @@ static struct attribute *nvdimm_attributes[] = {
>  	&dev_attr_commands.attr,
>  	&dev_attr_available_slots.attr,
>  	&dev_attr_security.attr,
> +	&dev_attr_frozen.attr,
>  	NULL,
>  };
>  
> @@ -509,17 +513,24 @@ 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)
> +	if (a != &dev_attr_security.attr && a != &dev_attr_frozen.attr)
>  		return a->mode;
> -	if (nvdimm->sec.state < 0)
> +	if (!nvdimm->sec.flags)
>  		return 0;
> -	/* Are there any state mutation ops? */
> -	if (nvdimm->sec.ops->freeze || nvdimm->sec.ops->disable
> -			|| nvdimm->sec.ops->change_key
> -			|| nvdimm->sec.ops->erase
> -			|| nvdimm->sec.ops->overwrite)
> +
> +	if (a == &dev_attr_security.attr) {
> +		/* Are there any state mutation ops (make writable)? */
> +		if (nvdimm->sec.ops->freeze || nvdimm->sec.ops->disable
> +				|| nvdimm->sec.ops->change_key
> +				|| nvdimm->sec.ops->erase
> +				|| nvdimm->sec.ops->overwrite)
> +			return a->mode;
> +		return 0444;
> +	}
> +
> +	if (nvdimm->sec.ops->freeze)
>  		return a->mode;
> -	return 0444;
> +	return 0;
>  }
>  
>  struct attribute_group nvdimm_attribute_group = {
> @@ -569,8 +580,8 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
>  	 * attribute visibility.
>  	 */
>  	/* get security state and extended (master) state */
> -	nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
> -	nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, NVDIMM_MASTER);
> +	nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
> +	nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
>  	nd_device_register(dev);
>  
>  	return nvdimm;
> @@ -588,7 +599,7 @@ int nvdimm_security_setup_events(struct device *dev)
>  {
>  	struct nvdimm *nvdimm = to_nvdimm(dev);
>  
> -	if (nvdimm->sec.state < 0 || !nvdimm->sec.ops
> +	if (!nvdimm->sec.flags || !nvdimm->sec.ops
>  			|| !nvdimm->sec.ops->overwrite)
>  		return 0;
>  	nvdimm->sec.overwrite_state = sysfs_get_dirent(dev->kobj.sd, "security");
> @@ -614,7 +625,7 @@ int nvdimm_security_freeze(struct nvdimm *nvdimm)
>  	if (!nvdimm->sec.ops || !nvdimm->sec.ops->freeze)
>  		return -EOPNOTSUPP;
>  
> -	if (nvdimm->sec.state < 0)
> +	if (!nvdimm->sec.flags)
>  		return -EIO;
>  
>  	if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
> @@ -623,7 +634,7 @@ int nvdimm_security_freeze(struct nvdimm *nvdimm)
>  	}
>  
>  	rc = nvdimm->sec.ops->freeze(nvdimm);
> -	nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
> +	nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
>  
>  	return rc;
>  }
> diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h
> index 0ac52b6eb00e..da2bbfd56d9f 100644
> --- a/drivers/nvdimm/nd-core.h
> +++ b/drivers/nvdimm/nd-core.h
> @@ -39,21 +39,32 @@ struct nvdimm {
>  	const char *dimm_id;
>  	struct {
>  		const struct nvdimm_security_ops *ops;
> -		enum nvdimm_security_state state;
> -		enum nvdimm_security_state ext_state;
> +		unsigned long flags;
> +		unsigned long ext_flags;
>  		unsigned int overwrite_tmo;
>  		struct kernfs_node *overwrite_state;
>  	} sec;
>  	struct delayed_work dwork;
>  };
>  
> -static inline enum nvdimm_security_state nvdimm_security_state(
> +static inline unsigned long nvdimm_security_flags(
>  		struct nvdimm *nvdimm, enum nvdimm_passphrase_type ptype)
>  {
> +	u64 flags;
> +	const u64 state_flags = 1UL << NVDIMM_SECURITY_DISABLED
> +		| 1UL << NVDIMM_SECURITY_LOCKED
> +		| 1UL << NVDIMM_SECURITY_UNLOCKED
> +		| 1UL << NVDIMM_SECURITY_OVERWRITE;
> +
>  	if (!nvdimm->sec.ops)
> -		return -ENXIO;
> +		return 0;
>  
> -	return nvdimm->sec.ops->state(nvdimm, ptype);
> +	flags = nvdimm->sec.ops->get_flags(nvdimm, ptype);
> +	/* disabled, locked, unlocked, and overwrite are mutually exclusive */
> +	dev_WARN_ONCE(&nvdimm->dev, hweight64(flags & state_flags) > 1,
> +			"reported invalid security state: %#llx\n",
> +			(unsigned long long) flags);
> +	return flags;
>  }
>  int nvdimm_security_freeze(struct nvdimm *nvdimm);
>  #if IS_ENABLED(CONFIG_NVDIMM_KEYS)
> diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
> index a570f2263a42..5862d0eee9db 100644
> --- a/drivers/nvdimm/security.c
> +++ b/drivers/nvdimm/security.c
> @@ -158,7 +158,7 @@ static int nvdimm_key_revalidate(struct nvdimm *nvdimm)
>  	}
>  
>  	nvdimm_put_key(key);
> -	nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
> +	nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
>  	return 0;
>  }
>  
> @@ -174,7 +174,7 @@ static int __nvdimm_security_unlock(struct nvdimm *nvdimm)
>  	lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
>  
>  	if (!nvdimm->sec.ops || !nvdimm->sec.ops->unlock
> -			|| nvdimm->sec.state < 0)
> +			|| !nvdimm->sec.flags)
>  		return -EIO;
>  
>  	if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
> @@ -189,7 +189,7 @@ static int __nvdimm_security_unlock(struct nvdimm *nvdimm)
>  	 * freeze of the security configuration. I.e. if the OS does not
>  	 * have the key, security is being managed pre-OS.
>  	 */
> -	if (nvdimm->sec.state == NVDIMM_SECURITY_UNLOCKED) {
> +	if (test_bit(NVDIMM_SECURITY_UNLOCKED, &nvdimm->sec.flags)) {
>  		if (!key_revalidate)
>  			return 0;
>  
> @@ -202,7 +202,7 @@ static int __nvdimm_security_unlock(struct nvdimm *nvdimm)
>  			rc == 0 ? "success" : "fail");
>  
>  	nvdimm_put_key(key);
> -	nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
> +	nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
>  	return rc;
>  }
>  
> @@ -217,6 +217,24 @@ int nvdimm_security_unlock(struct device *dev)
>  	return rc;
>  }
>  
> +static int check_security_state(struct nvdimm *nvdimm)
> +{
> +	struct device *dev = &nvdimm->dev;
> +
> +	if (test_bit(NVDIMM_SECURITY_FROZEN, &nvdimm->sec.flags)) {
> +		dev_dbg(dev, "Incorrect security state: %#lx\n",
> +				nvdimm->sec.flags);
> +		return -EIO;
> +	}
> +
> +	if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
> +		dev_dbg(dev, "Security operation in progress.\n");
> +		return -EBUSY;
> +	}
> +
> +	return 0;
> +}
> +
>  int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
>  {
>  	struct device *dev = &nvdimm->dev;
> @@ -229,19 +247,12 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
>  	lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
>  
>  	if (!nvdimm->sec.ops || !nvdimm->sec.ops->disable
> -			|| nvdimm->sec.state < 0)
> +			|| !nvdimm->sec.flags)
>  		return -EOPNOTSUPP;
>  
> -	if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) {
> -		dev_dbg(dev, "Incorrect security state: %d\n",
> -				nvdimm->sec.state);
> -		return -EIO;
> -	}
> -
> -	if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
> -		dev_dbg(dev, "Security operation in progress.\n");
> -		return -EBUSY;
> -	}
> +	rc = check_security_state(nvdimm);
> +	if (rc)
> +		return rc;
>  
>  	data = nvdimm_get_user_key_payload(nvdimm, keyid,
>  			NVDIMM_BASE_KEY, &key);
> @@ -253,7 +264,7 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
>  			rc == 0 ? "success" : "fail");
>  
>  	nvdimm_put_key(key);
> -	nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
> +	nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
>  	return rc;
>  }
>  
> @@ -271,14 +282,12 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
>  	lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
>  
>  	if (!nvdimm->sec.ops || !nvdimm->sec.ops->change_key
> -			|| nvdimm->sec.state < 0)
> +			|| !nvdimm->sec.flags)
>  		return -EOPNOTSUPP;
>  
> -	if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) {
> -		dev_dbg(dev, "Incorrect security state: %d\n",
> -				nvdimm->sec.state);
> -		return -EIO;
> -	}
> +	rc = check_security_state(nvdimm);
> +	if (rc)
> +		return rc;
>  
>  	data = nvdimm_get_user_key_payload(nvdimm, keyid,
>  			NVDIMM_BASE_KEY, &key);
> @@ -301,10 +310,10 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
>  	nvdimm_put_key(newkey);
>  	nvdimm_put_key(key);
>  	if (pass_type == NVDIMM_MASTER)
> -		nvdimm->sec.ext_state = nvdimm_security_state(nvdimm,
> +		nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm,
>  				NVDIMM_MASTER);
>  	else
> -		nvdimm->sec.state = nvdimm_security_state(nvdimm,
> +		nvdimm->sec.flags = nvdimm_security_flags(nvdimm,
>  				NVDIMM_USER);
>  	return rc;
>  }
> @@ -322,7 +331,7 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid,
>  	lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
>  
>  	if (!nvdimm->sec.ops || !nvdimm->sec.ops->erase
> -			|| nvdimm->sec.state < 0)
> +			|| !nvdimm->sec.flags)
>  		return -EOPNOTSUPP;
>  
>  	if (atomic_read(&nvdimm->busy)) {
> @@ -330,18 +339,11 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid,
>  		return -EBUSY;
>  	}
>  
> -	if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) {
> -		dev_dbg(dev, "Incorrect security state: %d\n",
> -				nvdimm->sec.state);
> -		return -EIO;
> -	}
> -
> -	if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
> -		dev_dbg(dev, "Security operation in progress.\n");
> -		return -EBUSY;
> -	}
> +	rc = check_security_state(nvdimm);
> +	if (rc)
> +		return rc;
>  
> -	if (nvdimm->sec.ext_state != NVDIMM_SECURITY_UNLOCKED
> +	if (!test_bit(NVDIMM_SECURITY_UNLOCKED, &nvdimm->sec.ext_flags)
>  			&& pass_type == NVDIMM_MASTER) {
>  		dev_dbg(dev,
>  			"Attempt to secure erase in wrong master state.\n");
> @@ -359,7 +361,7 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid,
>  			rc == 0 ? "success" : "fail");
>  
>  	nvdimm_put_key(key);
> -	nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
> +	nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
>  	return rc;
>  }
>  
> @@ -375,7 +377,7 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
>  	lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
>  
>  	if (!nvdimm->sec.ops || !nvdimm->sec.ops->overwrite
> -			|| nvdimm->sec.state < 0)
> +			|| !nvdimm->sec.flags)
>  		return -EOPNOTSUPP;
>  
>  	if (atomic_read(&nvdimm->busy)) {
> @@ -388,16 +390,9 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
>  		return -EINVAL;
>  	}
>  
> -	if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) {
> -		dev_dbg(dev, "Incorrect security state: %d\n",
> -				nvdimm->sec.state);
> -		return -EIO;
> -	}
> -
> -	if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
> -		dev_dbg(dev, "Security operation in progress.\n");
> -		return -EBUSY;
> -	}
> +	rc = check_security_state(nvdimm);
> +	if (rc)
> +		return rc;
>  
>  	data = nvdimm_get_user_key_payload(nvdimm, keyid,
>  			NVDIMM_BASE_KEY, &key);
> @@ -412,7 +407,7 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
>  	if (rc == 0) {
>  		set_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags);
>  		set_bit(NDD_WORK_PENDING, &nvdimm->flags);
> -		nvdimm->sec.state = NVDIMM_SECURITY_OVERWRITE;
> +		set_bit(NVDIMM_SECURITY_OVERWRITE, &nvdimm->sec.flags);
>  		/*
>  		 * Make sure we don't lose device while doing overwrite
>  		 * query.
> @@ -443,7 +438,7 @@ void __nvdimm_security_overwrite_query(struct nvdimm *nvdimm)
>  	tmo = nvdimm->sec.overwrite_tmo;
>  
>  	if (!nvdimm->sec.ops || !nvdimm->sec.ops->query_overwrite
> -			|| nvdimm->sec.state < 0)
> +			|| !nvdimm->sec.flags)
>  		return;
>  
>  	rc = nvdimm->sec.ops->query_overwrite(nvdimm);
> @@ -467,8 +462,8 @@ void __nvdimm_security_overwrite_query(struct nvdimm *nvdimm)
>  	clear_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags);
>  	clear_bit(NDD_WORK_PENDING, &nvdimm->flags);
>  	put_device(&nvdimm->dev);
> -	nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
> -	nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, NVDIMM_MASTER);
> +	nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
> +	nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
>  }
>  
>  void nvdimm_security_overwrite_query(struct work_struct *work)
> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
> index 7a64b3ddb408..b6eddf912568 100644
> --- a/include/linux/libnvdimm.h
> +++ b/include/linux/libnvdimm.h
> @@ -160,8 +160,11 @@ static inline struct nd_blk_region_desc *to_blk_region_desc(
>  
>  }
>  
> -enum nvdimm_security_state {
> -	NVDIMM_SECURITY_ERROR = -1,
> +/*
> + * Note that separate bits for locked + unlocked are defined so that
> + * 'flags == 0' corresponds to an error / not-supported state.
> + */
> +enum nvdimm_security_bits {
>  	NVDIMM_SECURITY_DISABLED,
>  	NVDIMM_SECURITY_UNLOCKED,
>  	NVDIMM_SECURITY_LOCKED,
> @@ -182,7 +185,7 @@ enum nvdimm_passphrase_type {
>  };
>  
>  struct nvdimm_security_ops {
> -	enum nvdimm_security_state (*state)(struct nvdimm *nvdimm,
> +	unsigned long (*get_flags)(struct nvdimm *nvdimm,
>  			enum nvdimm_passphrase_type pass_type);
>  	int (*freeze)(struct nvdimm *nvdimm);
>  	int (*change_key)(struct nvdimm *nvdimm,
> diff --git a/tools/testing/nvdimm/dimm_devs.c b/tools/testing/nvdimm/dimm_devs.c
> index 2d4baf57822f..57bd27dedf1f 100644
> --- a/tools/testing/nvdimm/dimm_devs.c
> +++ b/tools/testing/nvdimm/dimm_devs.c
> @@ -18,24 +18,13 @@ ssize_t security_show(struct device *dev,
>  	 * For the test version we need to poll the "hardware" in order
>  	 * to get the updated status for unlock testing.
>  	 */
> -	nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
> -	nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, NVDIMM_MASTER);
> +	nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
>  
> -	switch (nvdimm->sec.state) {
> -	case NVDIMM_SECURITY_DISABLED:
> +	if (test_bit(NVDIMM_SECURITY_DISABLED, &nvdimm->sec.flags))
>  		return sprintf(buf, "disabled\n");
> -	case NVDIMM_SECURITY_UNLOCKED:
> +	if (test_bit(NVDIMM_SECURITY_UNLOCKED, &nvdimm->sec.flags))
>  		return sprintf(buf, "unlocked\n");
> -	case NVDIMM_SECURITY_LOCKED:
> +	if (test_bit(NVDIMM_SECURITY_LOCKED, &nvdimm->sec.flags))
>  		return sprintf(buf, "locked\n");
> -	case NVDIMM_SECURITY_FROZEN:
> -		return sprintf(buf, "frozen\n");
> -	case NVDIMM_SECURITY_OVERWRITE:
> -		return sprintf(buf, "overwrite\n");
> -	default:
> -		return -ENOTTY;
> -	}
> -
>  	return -ENOTTY;
>  }
> -

  reply	other threads:[~2019-08-28 17:56 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-27  0:54 [PATCH v2 0/3] libnvdimm/security: Enumerate the frozen state and other cleanups Dan Williams
2019-08-27  0:54 ` [PATCH v2 1/3] libnvdimm/security: Introduce a 'frozen' attribute Dan Williams
2019-08-28 17:56   ` Jeff Moyer [this message]
2019-08-27  0:55 ` [PATCH v2 2/3] libnvdimm/security: Tighten scope of nvdimm->busy vs security operations Dan Williams
2019-08-28 17:57   ` Jeff Moyer
2019-08-27  0:55 ` [PATCH v2 3/3] libnvdimm/security: Consolidate 'security' operations Dan Williams
2019-08-28 17:57 ` [PATCH v2 0/3] libnvdimm/security: Enumerate the frozen state and other cleanups Jeff Moyer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=x49blw9897n.fsf@segfault.boston.devel.redhat.com \
    --to=jmoyer@redhat.com \
    --cc=dan.j.williams@intel.com \
    --cc=dave.jiang@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nvdimm@lists.01.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).