2020-07-24 16:11:04

by Jane Chu

[permalink] [raw]
Subject: [PATCH 1/2] libnvdimm/security: 'security' attr never show 'overwrite' state

Since
commit d78c620a2e82 ("libnvdimm/security: Introduce a 'frozen' attribute"),
when issue
# ndctl sanitize-dimm nmem0 --overwrite
then immediately check the 'security' attribute,
# cat /sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/nmem0/security
unlocked
Actually the attribute stays 'unlocked' through out the entire overwrite
operation, never changed. That's because 'nvdimm->sec.flags' is a bitmap
that has both bits set indicating 'overwrite' and 'unlocked'.
But security_show() checks the mutually exclusive bits before it checks
the 'overwrite' bit at last. The order should be reversed.

The commit also has a typo: in one occasion, 'nvdimm->sec.ext_state'
assignment is replaced with 'nvdimm->sec.flags' assignment for
the NVDIMM_MASTER type.

Cc: Dan Williams <[email protected]>
Fixes: d78c620a2e82 ("libnvdimm/security: Introduce a 'frozen' attribute")
Signed-off-by: Jane Chu <[email protected]>
---
drivers/nvdimm/dimm_devs.c | 4 ++--
drivers/nvdimm/security.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index b7b77e8..5d72026 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -363,14 +363,14 @@ __weak ssize_t security_show(struct device *dev,
{
struct nvdimm *nvdimm = to_nvdimm(dev);

+ if (test_bit(NVDIMM_SECURITY_OVERWRITE, &nvdimm->sec.flags))
+ return sprintf(buf, "overwrite\n");
if (test_bit(NVDIMM_SECURITY_DISABLED, &nvdimm->sec.flags))
return sprintf(buf, "disabled\n");
if (test_bit(NVDIMM_SECURITY_UNLOCKED, &nvdimm->sec.flags))
return sprintf(buf, "unlocked\n");
if (test_bit(NVDIMM_SECURITY_LOCKED, &nvdimm->sec.flags))
return sprintf(buf, "locked\n");
- if (test_bit(NVDIMM_SECURITY_OVERWRITE, &nvdimm->sec.flags))
- return sprintf(buf, "overwrite\n");
return -ENOTTY;
}

diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
index 4cef69b..8f3971c 100644
--- a/drivers/nvdimm/security.c
+++ b/drivers/nvdimm/security.c
@@ -457,7 +457,7 @@ void __nvdimm_security_overwrite_query(struct nvdimm *nvdimm)
clear_bit(NDD_WORK_PENDING, &nvdimm->flags);
put_device(&nvdimm->dev);
nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
- nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
+ nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
}

void nvdimm_security_overwrite_query(struct work_struct *work)
--
1.8.3.1


2020-07-24 16:14:51

by Jane Chu

[permalink] [raw]
Subject: [PATCH 2/2] libnvdimm/security: ensure sysfs poll thread woke up and fetch updated attr

commit 7d988097c546 ("acpi/nfit, libnvdimm/security: Add security DSM overwrite support")
adds a sysfs_notify_dirent() to wake up userspace poll thread when the "overwrite"
operation has completed. But the notification is issued before the internal
dimm security state and flags have been updated, so the userspace poll thread
wakes up and fetches the not-yet-updated attr and falls back to sleep, forever.
But if user from another terminal issue "ndctl wait-overwrite nmemX" again,
the command returns instantly.

Cc: Dave Jiang <[email protected]>
Cc: Dan Williams <[email protected]>
Fixes: 7d988097c546 ("acpi/nfit, libnvdimm/security: Add security DSM overwrite support")
Signed-off-by: Jane Chu <[email protected]>
---
drivers/nvdimm/security.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
index 8f3971c..4b80150 100644
--- a/drivers/nvdimm/security.c
+++ b/drivers/nvdimm/security.c
@@ -450,14 +450,19 @@ void __nvdimm_security_overwrite_query(struct nvdimm *nvdimm)
else
dev_dbg(&nvdimm->dev, "overwrite completed\n");

- if (nvdimm->sec.overwrite_state)
- sysfs_notify_dirent(nvdimm->sec.overwrite_state);
+ /*
+ * Mark the overwrite work done and update dimm security flags,
+ * then send a sysfs event notification to wake up userspace
+ * poll threads to picked up the changed state.
+ */
nvdimm->sec.overwrite_tmo = 0;
clear_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags);
clear_bit(NDD_WORK_PENDING, &nvdimm->flags);
- put_device(&nvdimm->dev);
nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
+ if (nvdimm->sec.overwrite_state)
+ sysfs_notify_dirent(nvdimm->sec.overwrite_state);
+ put_device(&nvdimm->dev);
}

void nvdimm_security_overwrite_query(struct work_struct *work)
--
1.8.3.1

2020-08-03 20:44:09

by Dave Jiang

[permalink] [raw]
Subject: Re: [PATCH 1/2] libnvdimm/security: 'security' attr never show 'overwrite' state



On 7/24/2020 9:09 AM, Jane Chu wrote:
> Since
> commit d78c620a2e82 ("libnvdimm/security: Introduce a 'frozen' attribute"),
> when issue
> # ndctl sanitize-dimm nmem0 --overwrite
> then immediately check the 'security' attribute,
> # cat /sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/nmem0/security
> unlocked
> Actually the attribute stays 'unlocked' through out the entire overwrite
> operation, never changed. That's because 'nvdimm->sec.flags' is a bitmap
> that has both bits set indicating 'overwrite' and 'unlocked'.
> But security_show() checks the mutually exclusive bits before it checks
> the 'overwrite' bit at last. The order should be reversed.
>
> The commit also has a typo: in one occasion, 'nvdimm->sec.ext_state'
> assignment is replaced with 'nvdimm->sec.flags' assignment for
> the NVDIMM_MASTER type.

May be best to split this fix to a different patch? Just thinking git bisect
later on to track issues. Otherwise Reviewed-by: Dave Jiang <[email protected]>

>
> Cc: Dan Williams <[email protected]>
> Fixes: d78c620a2e82 ("libnvdimm/security: Introduce a 'frozen' attribute")
> Signed-off-by: Jane Chu <[email protected]>
> ---
> drivers/nvdimm/dimm_devs.c | 4 ++--
> drivers/nvdimm/security.c | 2 +-
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
> index b7b77e8..5d72026 100644
> --- a/drivers/nvdimm/dimm_devs.c
> +++ b/drivers/nvdimm/dimm_devs.c
> @@ -363,14 +363,14 @@ __weak ssize_t security_show(struct device *dev,
> {
> struct nvdimm *nvdimm = to_nvdimm(dev);
>
> + if (test_bit(NVDIMM_SECURITY_OVERWRITE, &nvdimm->sec.flags))
> + return sprintf(buf, "overwrite\n");
> if (test_bit(NVDIMM_SECURITY_DISABLED, &nvdimm->sec.flags))
> return sprintf(buf, "disabled\n");
> if (test_bit(NVDIMM_SECURITY_UNLOCKED, &nvdimm->sec.flags))
> return sprintf(buf, "unlocked\n");
> if (test_bit(NVDIMM_SECURITY_LOCKED, &nvdimm->sec.flags))
> return sprintf(buf, "locked\n");
> - if (test_bit(NVDIMM_SECURITY_OVERWRITE, &nvdimm->sec.flags))
> - return sprintf(buf, "overwrite\n");
> return -ENOTTY;
> }
>
> diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
> index 4cef69b..8f3971c 100644
> --- a/drivers/nvdimm/security.c
> +++ b/drivers/nvdimm/security.c
> @@ -457,7 +457,7 @@ void __nvdimm_security_overwrite_query(struct nvdimm *nvdimm)
> clear_bit(NDD_WORK_PENDING, &nvdimm->flags);
> put_device(&nvdimm->dev);
> nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
> - nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
> + nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
> }
>
> void nvdimm_security_overwrite_query(struct work_struct *work)
>

2020-08-03 20:44:44

by Dave Jiang

[permalink] [raw]
Subject: Re: [PATCH 2/2] libnvdimm/security: ensure sysfs poll thread woke up and fetch updated attr



On 7/24/2020 9:09 AM, Jane Chu wrote:
> commit 7d988097c546 ("acpi/nfit, libnvdimm/security: Add security DSM overwrite support")
> adds a sysfs_notify_dirent() to wake up userspace poll thread when the "overwrite"
> operation has completed. But the notification is issued before the internal
> dimm security state and flags have been updated, so the userspace poll thread
> wakes up and fetches the not-yet-updated attr and falls back to sleep, forever.
> But if user from another terminal issue "ndctl wait-overwrite nmemX" again,
> the command returns instantly.
>
> Cc: Dave Jiang <[email protected]>
> Cc: Dan Williams <[email protected]>
> Fixes: 7d988097c546 ("acpi/nfit, libnvdimm/security: Add security DSM overwrite support")
> Signed-off-by: Jane Chu <[email protected]>

Reviewed-by: Dave Jiang <[email protected]>

> ---
> drivers/nvdimm/security.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
> index 8f3971c..4b80150 100644
> --- a/drivers/nvdimm/security.c
> +++ b/drivers/nvdimm/security.c
> @@ -450,14 +450,19 @@ void __nvdimm_security_overwrite_query(struct nvdimm *nvdimm)
> else
> dev_dbg(&nvdimm->dev, "overwrite completed\n");
>
> - if (nvdimm->sec.overwrite_state)
> - sysfs_notify_dirent(nvdimm->sec.overwrite_state);
> + /*
> + * Mark the overwrite work done and update dimm security flags,
> + * then send a sysfs event notification to wake up userspace
> + * poll threads to picked up the changed state.
> + */
> nvdimm->sec.overwrite_tmo = 0;
> clear_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags);
> clear_bit(NDD_WORK_PENDING, &nvdimm->flags);
> - put_device(&nvdimm->dev);
> nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
> nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
> + if (nvdimm->sec.overwrite_state)
> + sysfs_notify_dirent(nvdimm->sec.overwrite_state);
> + put_device(&nvdimm->dev);
> }
>
> void nvdimm_security_overwrite_query(struct work_struct *work)
>

2020-08-03 21:13:15

by Jane Chu

[permalink] [raw]
Subject: Re: [PATCH 1/2] libnvdimm/security: 'security' attr never show 'overwrite' state

Hi, Dave,

On 8/3/2020 1:41 PM, Dave Jiang wrote:
> On 7/24/2020 9:09 AM, Jane Chu wrote:
>> Since
>> commit d78c620a2e82 ("libnvdimm/security: Introduce a 'frozen'
>> attribute"),
>> when issue
>>   # ndctl sanitize-dimm nmem0 --overwrite
>> then immediately check the 'security' attribute,
>>   # cat
>> /sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/nmem0/security
>>   unlocked
>> Actually the attribute stays 'unlocked' through out the entire overwrite
>> operation, never changed.  That's because 'nvdimm->sec.flags' is a bitmap
>> that has both bits set indicating 'overwrite' and 'unlocked'.
>> But security_show() checks the mutually exclusive bits before it checks
>> the 'overwrite' bit at last. The order should be reversed.
>>
>> The commit also has a typo: in one occasion, 'nvdimm->sec.ext_state'
>> assignment is replaced with 'nvdimm->sec.flags' assignment for
>> the NVDIMM_MASTER type.
>
> May be best to split this fix to a different patch? Just thinking git
> bisect later on to track issues. Otherwise Reviewed-by: Dave Jiang
> <[email protected]>

Sure. I take it you meant to separate the typo fix from the change that
tests the OVERWRITE bit first?

Regards,
-jane

2020-08-03 21:27:30

by Dave Jiang

[permalink] [raw]
Subject: Re: [PATCH 1/2] libnvdimm/security: 'security' attr never show 'overwrite' state



On 8/3/2020 2:10 PM, Jane Chu wrote:
> Hi, Dave,
>
> On 8/3/2020 1:41 PM, Dave Jiang wrote:
>> On 7/24/2020 9:09 AM, Jane Chu wrote:
>>> Since
>>> commit d78c620a2e82 ("libnvdimm/security: Introduce a 'frozen' attribute"),
>>> when issue
>>>   # ndctl sanitize-dimm nmem0 --overwrite
>>> then immediately check the 'security' attribute,
>>>   # cat /sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/nmem0/security
>>>   unlocked
>>> Actually the attribute stays 'unlocked' through out the entire overwrite
>>> operation, never changed.  That's because 'nvdimm->sec.flags' is a bitmap
>>> that has both bits set indicating 'overwrite' and 'unlocked'.
>>> But security_show() checks the mutually exclusive bits before it checks
>>> the 'overwrite' bit at last. The order should be reversed.
>>>
>>> The commit also has a typo: in one occasion, 'nvdimm->sec.ext_state'
>>> assignment is replaced with 'nvdimm->sec.flags' assignment for
>>> the NVDIMM_MASTER type.
>>
>> May be best to split this fix to a different patch? Just thinking git bisect
>> later on to track issues. Otherwise Reviewed-by: Dave Jiang
>> <[email protected]>
>
> Sure. I take it you meant to separate the typo fix from the change that tests
> the OVERWRITE bit first?

Yep!

>
> Regards,
> -jane