diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-04-15 19:48:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-04-15 19:48:51 -0400 |
commit | 618d919cae2fcaadc752f27ddac8b939da8b441a (patch) | |
tree | def6e581d1787e1cd2f758c7e1c5917ac4441dba | |
parent | 5512320c9f6f2acd7972c05400473c2338325339 (diff) | |
parent | 2170a0d53bee1a6c1a4ebd042f99d85aafc6c0ea (diff) |
Merge tag 'libnvdimm-fixes-5.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull libnvdimm fixes from Dan Williams:
"I debated holding this back for the v5.2 merge window due to the size
of the "zero-key" changes, but affected users would benefit from
having the fixes sooner. It did not make sense to change the zero-key
semantic in isolation for the "secure-erase" command, but instead
include it for all security commands.
The short background on the need for these changes is that some NVDIMM
platforms enable security with a default zero-key rather than let the
OS specify the initial key. This makes the security enabling that
landed in v5.0 unusable for some users.
Summary:
- Compatibility fix for nvdimm-security implementations with a
default zero-key.
- Miscellaneous small fixes for out-of-bound accesses, cleanup after
initialization failures, and missing debug messages"
* tag 'libnvdimm-fixes-5.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
tools/testing/nvdimm: Retain security state after overwrite
libnvdimm/pmem: fix a possible OOB access when read and write pmem
libnvdimm/security, acpi/nfit: unify zero-key for all security commands
libnvdimm/security: provide fix for secure-erase to use zero-key
libnvdimm/btt: Fix a kmemdup failure check
libnvdimm/namespace: Fix a potential NULL pointer dereference
acpi/nfit: Always dump _DSM output payload
-rw-r--r-- | drivers/acpi/nfit/core.c | 12 | ||||
-rw-r--r-- | drivers/acpi/nfit/intel.c | 10 | ||||
-rw-r--r-- | drivers/nvdimm/btt_devs.c | 18 | ||||
-rw-r--r-- | drivers/nvdimm/namespace_devs.c | 5 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 8 | ||||
-rw-r--r-- | drivers/nvdimm/security.c | 118 | ||||
-rw-r--r-- | tools/testing/nvdimm/test/nfit.c | 17 |
7 files changed, 117 insertions, 71 deletions
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 5a389a4f4f65..f1ed0befe303 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c | |||
@@ -567,6 +567,12 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, | |||
567 | goto out; | 567 | goto out; |
568 | } | 568 | } |
569 | 569 | ||
570 | dev_dbg(dev, "%s cmd: %s output length: %d\n", dimm_name, | ||
571 | cmd_name, out_obj->buffer.length); | ||
572 | print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4, 4, | ||
573 | out_obj->buffer.pointer, | ||
574 | min_t(u32, 128, out_obj->buffer.length), true); | ||
575 | |||
570 | if (call_pkg) { | 576 | if (call_pkg) { |
571 | call_pkg->nd_fw_size = out_obj->buffer.length; | 577 | call_pkg->nd_fw_size = out_obj->buffer.length; |
572 | memcpy(call_pkg->nd_payload + call_pkg->nd_size_in, | 578 | memcpy(call_pkg->nd_payload + call_pkg->nd_size_in, |
@@ -585,12 +591,6 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, | |||
585 | return 0; | 591 | return 0; |
586 | } | 592 | } |
587 | 593 | ||
588 | dev_dbg(dev, "%s cmd: %s output length: %d\n", dimm_name, | ||
589 | cmd_name, out_obj->buffer.length); | ||
590 | print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4, 4, | ||
591 | out_obj->buffer.pointer, | ||
592 | min_t(u32, 128, out_obj->buffer.length), true); | ||
593 | |||
594 | for (i = 0, offset = 0; i < desc->out_num; i++) { | 594 | for (i = 0, offset = 0; i < desc->out_num; i++) { |
595 | u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, buf, | 595 | u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, buf, |
596 | (u32 *) out_obj->buffer.pointer, | 596 | (u32 *) out_obj->buffer.pointer, |
diff --git a/drivers/acpi/nfit/intel.c b/drivers/acpi/nfit/intel.c index f70de71f79d6..cddd0fcf622c 100644 --- a/drivers/acpi/nfit/intel.c +++ b/drivers/acpi/nfit/intel.c | |||
@@ -122,9 +122,8 @@ static int intel_security_change_key(struct nvdimm *nvdimm, | |||
122 | if (!test_bit(cmd, &nfit_mem->dsm_mask)) | 122 | if (!test_bit(cmd, &nfit_mem->dsm_mask)) |
123 | return -ENOTTY; | 123 | return -ENOTTY; |
124 | 124 | ||
125 | if (old_data) | 125 | memcpy(nd_cmd.cmd.old_pass, old_data->data, |
126 | memcpy(nd_cmd.cmd.old_pass, old_data->data, | 126 | sizeof(nd_cmd.cmd.old_pass)); |
127 | sizeof(nd_cmd.cmd.old_pass)); | ||
128 | memcpy(nd_cmd.cmd.new_pass, new_data->data, | 127 | memcpy(nd_cmd.cmd.new_pass, new_data->data, |
129 | sizeof(nd_cmd.cmd.new_pass)); | 128 | sizeof(nd_cmd.cmd.new_pass)); |
130 | rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); | 129 | rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); |
@@ -336,9 +335,8 @@ static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm, | |||
336 | 335 | ||
337 | /* flush all cache before we erase DIMM */ | 336 | /* flush all cache before we erase DIMM */ |
338 | nvdimm_invalidate_cache(); | 337 | nvdimm_invalidate_cache(); |
339 | if (nkey) | 338 | memcpy(nd_cmd.cmd.passphrase, nkey->data, |
340 | memcpy(nd_cmd.cmd.passphrase, nkey->data, | 339 | sizeof(nd_cmd.cmd.passphrase)); |
341 | sizeof(nd_cmd.cmd.passphrase)); | ||
342 | rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); | 340 | rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); |
343 | if (rc < 0) | 341 | if (rc < 0) |
344 | return rc; | 342 | return rc; |
diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c index b72a303176c7..9486acc08402 100644 --- a/drivers/nvdimm/btt_devs.c +++ b/drivers/nvdimm/btt_devs.c | |||
@@ -198,14 +198,15 @@ static struct device *__nd_btt_create(struct nd_region *nd_region, | |||
198 | return NULL; | 198 | return NULL; |
199 | 199 | ||
200 | nd_btt->id = ida_simple_get(&nd_region->btt_ida, 0, 0, GFP_KERNEL); | 200 | nd_btt->id = ida_simple_get(&nd_region->btt_ida, 0, 0, GFP_KERNEL); |
201 | if (nd_btt->id < 0) { | 201 | if (nd_btt->id < 0) |
202 | kfree(nd_btt); | 202 | goto out_nd_btt; |
203 | return NULL; | ||
204 | } | ||
205 | 203 | ||
206 | nd_btt->lbasize = lbasize; | 204 | nd_btt->lbasize = lbasize; |
207 | if (uuid) | 205 | if (uuid) { |
208 | uuid = kmemdup(uuid, 16, GFP_KERNEL); | 206 | uuid = kmemdup(uuid, 16, GFP_KERNEL); |
207 | if (!uuid) | ||
208 | goto out_put_id; | ||
209 | } | ||
209 | nd_btt->uuid = uuid; | 210 | nd_btt->uuid = uuid; |
210 | dev = &nd_btt->dev; | 211 | dev = &nd_btt->dev; |
211 | dev_set_name(dev, "btt%d.%d", nd_region->id, nd_btt->id); | 212 | dev_set_name(dev, "btt%d.%d", nd_region->id, nd_btt->id); |
@@ -220,6 +221,13 @@ static struct device *__nd_btt_create(struct nd_region *nd_region, | |||
220 | return NULL; | 221 | return NULL; |
221 | } | 222 | } |
222 | return dev; | 223 | return dev; |
224 | |||
225 | out_put_id: | ||
226 | ida_simple_remove(&nd_region->btt_ida, nd_btt->id); | ||
227 | |||
228 | out_nd_btt: | ||
229 | kfree(nd_btt); | ||
230 | return NULL; | ||
223 | } | 231 | } |
224 | 232 | ||
225 | struct device *nd_btt_create(struct nd_region *nd_region) | 233 | struct device *nd_btt_create(struct nd_region *nd_region) |
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index 7849bf1812c4..f293556cbbf6 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c | |||
@@ -2249,9 +2249,12 @@ static struct device *create_namespace_blk(struct nd_region *nd_region, | |||
2249 | if (!nsblk->uuid) | 2249 | if (!nsblk->uuid) |
2250 | goto blk_err; | 2250 | goto blk_err; |
2251 | memcpy(name, nd_label->name, NSLABEL_NAME_LEN); | 2251 | memcpy(name, nd_label->name, NSLABEL_NAME_LEN); |
2252 | if (name[0]) | 2252 | if (name[0]) { |
2253 | nsblk->alt_name = kmemdup(name, NSLABEL_NAME_LEN, | 2253 | nsblk->alt_name = kmemdup(name, NSLABEL_NAME_LEN, |
2254 | GFP_KERNEL); | 2254 | GFP_KERNEL); |
2255 | if (!nsblk->alt_name) | ||
2256 | goto blk_err; | ||
2257 | } | ||
2255 | res = nsblk_add_resource(nd_region, ndd, nsblk, | 2258 | res = nsblk_add_resource(nd_region, ndd, nsblk, |
2256 | __le64_to_cpu(nd_label->dpa)); | 2259 | __le64_to_cpu(nd_label->dpa)); |
2257 | if (!res) | 2260 | if (!res) |
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index bc2f700feef8..0279eb1da3ef 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c | |||
@@ -113,13 +113,13 @@ static void write_pmem(void *pmem_addr, struct page *page, | |||
113 | 113 | ||
114 | while (len) { | 114 | while (len) { |
115 | mem = kmap_atomic(page); | 115 | mem = kmap_atomic(page); |
116 | chunk = min_t(unsigned int, len, PAGE_SIZE); | 116 | chunk = min_t(unsigned int, len, PAGE_SIZE - off); |
117 | memcpy_flushcache(pmem_addr, mem + off, chunk); | 117 | memcpy_flushcache(pmem_addr, mem + off, chunk); |
118 | kunmap_atomic(mem); | 118 | kunmap_atomic(mem); |
119 | len -= chunk; | 119 | len -= chunk; |
120 | off = 0; | 120 | off = 0; |
121 | page++; | 121 | page++; |
122 | pmem_addr += PAGE_SIZE; | 122 | pmem_addr += chunk; |
123 | } | 123 | } |
124 | } | 124 | } |
125 | 125 | ||
@@ -132,7 +132,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off, | |||
132 | 132 | ||
133 | while (len) { | 133 | while (len) { |
134 | mem = kmap_atomic(page); | 134 | mem = kmap_atomic(page); |
135 | chunk = min_t(unsigned int, len, PAGE_SIZE); | 135 | chunk = min_t(unsigned int, len, PAGE_SIZE - off); |
136 | rem = memcpy_mcsafe(mem + off, pmem_addr, chunk); | 136 | rem = memcpy_mcsafe(mem + off, pmem_addr, chunk); |
137 | kunmap_atomic(mem); | 137 | kunmap_atomic(mem); |
138 | if (rem) | 138 | if (rem) |
@@ -140,7 +140,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off, | |||
140 | len -= chunk; | 140 | len -= chunk; |
141 | off = 0; | 141 | off = 0; |
142 | page++; | 142 | page++; |
143 | pmem_addr += PAGE_SIZE; | 143 | pmem_addr += chunk; |
144 | } | 144 | } |
145 | return BLK_STS_OK; | 145 | return BLK_STS_OK; |
146 | } | 146 | } |
diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c index f8bb746a549f..a570f2263a42 100644 --- a/drivers/nvdimm/security.c +++ b/drivers/nvdimm/security.c | |||
@@ -22,6 +22,8 @@ static bool key_revalidate = true; | |||
22 | module_param(key_revalidate, bool, 0444); | 22 | module_param(key_revalidate, bool, 0444); |
23 | MODULE_PARM_DESC(key_revalidate, "Require key validation at init."); | 23 | MODULE_PARM_DESC(key_revalidate, "Require key validation at init."); |
24 | 24 | ||
25 | static const char zero_key[NVDIMM_PASSPHRASE_LEN]; | ||
26 | |||
25 | static void *key_data(struct key *key) | 27 | static void *key_data(struct key *key) |
26 | { | 28 | { |
27 | struct encrypted_key_payload *epayload = dereference_key_locked(key); | 29 | struct encrypted_key_payload *epayload = dereference_key_locked(key); |
@@ -75,6 +77,16 @@ static struct key *nvdimm_request_key(struct nvdimm *nvdimm) | |||
75 | return key; | 77 | return key; |
76 | } | 78 | } |
77 | 79 | ||
80 | static const void *nvdimm_get_key_payload(struct nvdimm *nvdimm, | ||
81 | struct key **key) | ||
82 | { | ||
83 | *key = nvdimm_request_key(nvdimm); | ||
84 | if (!*key) | ||
85 | return zero_key; | ||
86 | |||
87 | return key_data(*key); | ||
88 | } | ||
89 | |||
78 | static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, | 90 | static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, |
79 | key_serial_t id, int subclass) | 91 | key_serial_t id, int subclass) |
80 | { | 92 | { |
@@ -105,36 +117,57 @@ static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, | |||
105 | return key; | 117 | return key; |
106 | } | 118 | } |
107 | 119 | ||
108 | static struct key *nvdimm_key_revalidate(struct nvdimm *nvdimm) | 120 | static const void *nvdimm_get_user_key_payload(struct nvdimm *nvdimm, |
121 | key_serial_t id, int subclass, struct key **key) | ||
122 | { | ||
123 | *key = NULL; | ||
124 | if (id == 0) { | ||
125 | if (subclass == NVDIMM_BASE_KEY) | ||
126 | return zero_key; | ||
127 | else | ||
128 | return NULL; | ||
129 | } | ||
130 | |||
131 | *key = nvdimm_lookup_user_key(nvdimm, id, subclass); | ||
132 | if (!*key) | ||
133 | return NULL; | ||
134 | |||
135 | return key_data(*key); | ||
136 | } | ||
137 | |||
138 | |||
139 | static int nvdimm_key_revalidate(struct nvdimm *nvdimm) | ||
109 | { | 140 | { |
110 | struct key *key; | 141 | struct key *key; |
111 | int rc; | 142 | int rc; |
143 | const void *data; | ||
112 | 144 | ||
113 | if (!nvdimm->sec.ops->change_key) | 145 | if (!nvdimm->sec.ops->change_key) |
114 | return NULL; | 146 | return -EOPNOTSUPP; |
115 | 147 | ||
116 | key = nvdimm_request_key(nvdimm); | 148 | data = nvdimm_get_key_payload(nvdimm, &key); |
117 | if (!key) | ||
118 | return NULL; | ||
119 | 149 | ||
120 | /* | 150 | /* |
121 | * Send the same key to the hardware as new and old key to | 151 | * Send the same key to the hardware as new and old key to |
122 | * verify that the key is good. | 152 | * verify that the key is good. |
123 | */ | 153 | */ |
124 | rc = nvdimm->sec.ops->change_key(nvdimm, key_data(key), | 154 | rc = nvdimm->sec.ops->change_key(nvdimm, data, data, NVDIMM_USER); |
125 | key_data(key), NVDIMM_USER); | ||
126 | if (rc < 0) { | 155 | if (rc < 0) { |
127 | nvdimm_put_key(key); | 156 | nvdimm_put_key(key); |
128 | key = NULL; | 157 | return rc; |
129 | } | 158 | } |
130 | return key; | 159 | |
160 | nvdimm_put_key(key); | ||
161 | nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); | ||
162 | return 0; | ||
131 | } | 163 | } |
132 | 164 | ||
133 | static int __nvdimm_security_unlock(struct nvdimm *nvdimm) | 165 | static int __nvdimm_security_unlock(struct nvdimm *nvdimm) |
134 | { | 166 | { |
135 | struct device *dev = &nvdimm->dev; | 167 | struct device *dev = &nvdimm->dev; |
136 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | 168 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); |
137 | struct key *key = NULL; | 169 | struct key *key; |
170 | const void *data; | ||
138 | int rc; | 171 | int rc; |
139 | 172 | ||
140 | /* The bus lock should be held at the top level of the call stack */ | 173 | /* The bus lock should be held at the top level of the call stack */ |
@@ -160,16 +193,11 @@ static int __nvdimm_security_unlock(struct nvdimm *nvdimm) | |||
160 | if (!key_revalidate) | 193 | if (!key_revalidate) |
161 | return 0; | 194 | return 0; |
162 | 195 | ||
163 | key = nvdimm_key_revalidate(nvdimm); | 196 | return nvdimm_key_revalidate(nvdimm); |
164 | if (!key) | ||
165 | return nvdimm_security_freeze(nvdimm); | ||
166 | } else | 197 | } else |
167 | key = nvdimm_request_key(nvdimm); | 198 | data = nvdimm_get_key_payload(nvdimm, &key); |
168 | 199 | ||
169 | if (!key) | 200 | rc = nvdimm->sec.ops->unlock(nvdimm, data); |
170 | return -ENOKEY; | ||
171 | |||
172 | rc = nvdimm->sec.ops->unlock(nvdimm, key_data(key)); | ||
173 | dev_dbg(dev, "key: %d unlock: %s\n", key_serial(key), | 201 | dev_dbg(dev, "key: %d unlock: %s\n", key_serial(key), |
174 | rc == 0 ? "success" : "fail"); | 202 | rc == 0 ? "success" : "fail"); |
175 | 203 | ||
@@ -195,6 +223,7 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid) | |||
195 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | 223 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); |
196 | struct key *key; | 224 | struct key *key; |
197 | int rc; | 225 | int rc; |
226 | const void *data; | ||
198 | 227 | ||
199 | /* The bus lock should be held at the top level of the call stack */ | 228 | /* The bus lock should be held at the top level of the call stack */ |
200 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | 229 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); |
@@ -214,11 +243,12 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid) | |||
214 | return -EBUSY; | 243 | return -EBUSY; |
215 | } | 244 | } |
216 | 245 | ||
217 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); | 246 | data = nvdimm_get_user_key_payload(nvdimm, keyid, |
218 | if (!key) | 247 | NVDIMM_BASE_KEY, &key); |
248 | if (!data) | ||
219 | return -ENOKEY; | 249 | return -ENOKEY; |
220 | 250 | ||
221 | rc = nvdimm->sec.ops->disable(nvdimm, key_data(key)); | 251 | rc = nvdimm->sec.ops->disable(nvdimm, data); |
222 | dev_dbg(dev, "key: %d disable: %s\n", key_serial(key), | 252 | dev_dbg(dev, "key: %d disable: %s\n", key_serial(key), |
223 | rc == 0 ? "success" : "fail"); | 253 | rc == 0 ? "success" : "fail"); |
224 | 254 | ||
@@ -235,6 +265,7 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid, | |||
235 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | 265 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); |
236 | struct key *key, *newkey; | 266 | struct key *key, *newkey; |
237 | int rc; | 267 | int rc; |
268 | const void *data, *newdata; | ||
238 | 269 | ||
239 | /* The bus lock should be held at the top level of the call stack */ | 270 | /* The bus lock should be held at the top level of the call stack */ |
240 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | 271 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); |
@@ -249,22 +280,19 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid, | |||
249 | return -EIO; | 280 | return -EIO; |
250 | } | 281 | } |
251 | 282 | ||
252 | if (keyid == 0) | 283 | data = nvdimm_get_user_key_payload(nvdimm, keyid, |
253 | key = NULL; | 284 | NVDIMM_BASE_KEY, &key); |
254 | else { | 285 | if (!data) |
255 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); | 286 | return -ENOKEY; |
256 | if (!key) | ||
257 | return -ENOKEY; | ||
258 | } | ||
259 | 287 | ||
260 | newkey = nvdimm_lookup_user_key(nvdimm, new_keyid, NVDIMM_NEW_KEY); | 288 | newdata = nvdimm_get_user_key_payload(nvdimm, new_keyid, |
261 | if (!newkey) { | 289 | NVDIMM_NEW_KEY, &newkey); |
290 | if (!newdata) { | ||
262 | nvdimm_put_key(key); | 291 | nvdimm_put_key(key); |
263 | return -ENOKEY; | 292 | return -ENOKEY; |
264 | } | 293 | } |
265 | 294 | ||
266 | rc = nvdimm->sec.ops->change_key(nvdimm, key ? key_data(key) : NULL, | 295 | rc = nvdimm->sec.ops->change_key(nvdimm, data, newdata, pass_type); |
267 | key_data(newkey), pass_type); | ||
268 | dev_dbg(dev, "key: %d %d update%s: %s\n", | 296 | dev_dbg(dev, "key: %d %d update%s: %s\n", |
269 | key_serial(key), key_serial(newkey), | 297 | key_serial(key), key_serial(newkey), |
270 | pass_type == NVDIMM_MASTER ? "(master)" : "(user)", | 298 | pass_type == NVDIMM_MASTER ? "(master)" : "(user)", |
@@ -286,8 +314,9 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid, | |||
286 | { | 314 | { |
287 | struct device *dev = &nvdimm->dev; | 315 | struct device *dev = &nvdimm->dev; |
288 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | 316 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); |
289 | struct key *key; | 317 | struct key *key = NULL; |
290 | int rc; | 318 | int rc; |
319 | const void *data; | ||
291 | 320 | ||
292 | /* The bus lock should be held at the top level of the call stack */ | 321 | /* The bus lock should be held at the top level of the call stack */ |
293 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | 322 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); |
@@ -319,11 +348,12 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid, | |||
319 | return -EOPNOTSUPP; | 348 | return -EOPNOTSUPP; |
320 | } | 349 | } |
321 | 350 | ||
322 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); | 351 | data = nvdimm_get_user_key_payload(nvdimm, keyid, |
323 | if (!key) | 352 | NVDIMM_BASE_KEY, &key); |
353 | if (!data) | ||
324 | return -ENOKEY; | 354 | return -ENOKEY; |
325 | 355 | ||
326 | rc = nvdimm->sec.ops->erase(nvdimm, key_data(key), pass_type); | 356 | rc = nvdimm->sec.ops->erase(nvdimm, data, pass_type); |
327 | dev_dbg(dev, "key: %d erase%s: %s\n", key_serial(key), | 357 | dev_dbg(dev, "key: %d erase%s: %s\n", key_serial(key), |
328 | pass_type == NVDIMM_MASTER ? "(master)" : "(user)", | 358 | pass_type == NVDIMM_MASTER ? "(master)" : "(user)", |
329 | rc == 0 ? "success" : "fail"); | 359 | rc == 0 ? "success" : "fail"); |
@@ -337,8 +367,9 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid) | |||
337 | { | 367 | { |
338 | struct device *dev = &nvdimm->dev; | 368 | struct device *dev = &nvdimm->dev; |
339 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | 369 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); |
340 | struct key *key; | 370 | struct key *key = NULL; |
341 | int rc; | 371 | int rc; |
372 | const void *data; | ||
342 | 373 | ||
343 | /* The bus lock should be held at the top level of the call stack */ | 374 | /* The bus lock should be held at the top level of the call stack */ |
344 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | 375 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); |
@@ -368,15 +399,12 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid) | |||
368 | return -EBUSY; | 399 | return -EBUSY; |
369 | } | 400 | } |
370 | 401 | ||
371 | if (keyid == 0) | 402 | data = nvdimm_get_user_key_payload(nvdimm, keyid, |
372 | key = NULL; | 403 | NVDIMM_BASE_KEY, &key); |
373 | else { | 404 | if (!data) |
374 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); | 405 | return -ENOKEY; |
375 | if (!key) | ||
376 | return -ENOKEY; | ||
377 | } | ||
378 | 406 | ||
379 | rc = nvdimm->sec.ops->overwrite(nvdimm, key ? key_data(key) : NULL); | 407 | rc = nvdimm->sec.ops->overwrite(nvdimm, data); |
380 | dev_dbg(dev, "key: %d overwrite submission: %s\n", key_serial(key), | 408 | dev_dbg(dev, "key: %d overwrite submission: %s\n", key_serial(key), |
381 | rc == 0 ? "success" : "fail"); | 409 | rc == 0 ? "success" : "fail"); |
382 | 410 | ||
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index b579f962451d..85ffdcfa596b 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c | |||
@@ -146,6 +146,7 @@ static int dimm_fail_cmd_code[ARRAY_SIZE(handle)]; | |||
146 | struct nfit_test_sec { | 146 | struct nfit_test_sec { |
147 | u8 state; | 147 | u8 state; |
148 | u8 ext_state; | 148 | u8 ext_state; |
149 | u8 old_state; | ||
149 | u8 passphrase[32]; | 150 | u8 passphrase[32]; |
150 | u8 master_passphrase[32]; | 151 | u8 master_passphrase[32]; |
151 | u64 overwrite_end_time; | 152 | u64 overwrite_end_time; |
@@ -225,6 +226,8 @@ static struct workqueue_struct *nfit_wq; | |||
225 | 226 | ||
226 | static struct gen_pool *nfit_pool; | 227 | static struct gen_pool *nfit_pool; |
227 | 228 | ||
229 | static const char zero_key[NVDIMM_PASSPHRASE_LEN]; | ||
230 | |||
228 | static struct nfit_test *to_nfit_test(struct device *dev) | 231 | static struct nfit_test *to_nfit_test(struct device *dev) |
229 | { | 232 | { |
230 | struct platform_device *pdev = to_platform_device(dev); | 233 | struct platform_device *pdev = to_platform_device(dev); |
@@ -1059,8 +1062,7 @@ static int nd_intel_test_cmd_secure_erase(struct nfit_test *t, | |||
1059 | struct device *dev = &t->pdev.dev; | 1062 | struct device *dev = &t->pdev.dev; |
1060 | struct nfit_test_sec *sec = &dimm_sec_info[dimm]; | 1063 | struct nfit_test_sec *sec = &dimm_sec_info[dimm]; |
1061 | 1064 | ||
1062 | if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED) || | 1065 | if (sec->state & ND_INTEL_SEC_STATE_FROZEN) { |
1063 | (sec->state & ND_INTEL_SEC_STATE_FROZEN)) { | ||
1064 | nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE; | 1066 | nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE; |
1065 | dev_dbg(dev, "secure erase: wrong security state\n"); | 1067 | dev_dbg(dev, "secure erase: wrong security state\n"); |
1066 | } else if (memcmp(nd_cmd->passphrase, sec->passphrase, | 1068 | } else if (memcmp(nd_cmd->passphrase, sec->passphrase, |
@@ -1068,6 +1070,12 @@ static int nd_intel_test_cmd_secure_erase(struct nfit_test *t, | |||
1068 | nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS; | 1070 | nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS; |
1069 | dev_dbg(dev, "secure erase: wrong passphrase\n"); | 1071 | dev_dbg(dev, "secure erase: wrong passphrase\n"); |
1070 | } else { | 1072 | } else { |
1073 | if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED) | ||
1074 | && (memcmp(nd_cmd->passphrase, zero_key, | ||
1075 | ND_INTEL_PASSPHRASE_SIZE) != 0)) { | ||
1076 | dev_dbg(dev, "invalid zero key\n"); | ||
1077 | return 0; | ||
1078 | } | ||
1071 | memset(sec->passphrase, 0, ND_INTEL_PASSPHRASE_SIZE); | 1079 | memset(sec->passphrase, 0, ND_INTEL_PASSPHRASE_SIZE); |
1072 | memset(sec->master_passphrase, 0, ND_INTEL_PASSPHRASE_SIZE); | 1080 | memset(sec->master_passphrase, 0, ND_INTEL_PASSPHRASE_SIZE); |
1073 | sec->state = 0; | 1081 | sec->state = 0; |
@@ -1093,7 +1101,7 @@ static int nd_intel_test_cmd_overwrite(struct nfit_test *t, | |||
1093 | return 0; | 1101 | return 0; |
1094 | } | 1102 | } |
1095 | 1103 | ||
1096 | memset(sec->passphrase, 0, ND_INTEL_PASSPHRASE_SIZE); | 1104 | sec->old_state = sec->state; |
1097 | sec->state = ND_INTEL_SEC_STATE_OVERWRITE; | 1105 | sec->state = ND_INTEL_SEC_STATE_OVERWRITE; |
1098 | dev_dbg(dev, "overwrite progressing.\n"); | 1106 | dev_dbg(dev, "overwrite progressing.\n"); |
1099 | sec->overwrite_end_time = get_jiffies_64() + 5 * HZ; | 1107 | sec->overwrite_end_time = get_jiffies_64() + 5 * HZ; |
@@ -1115,7 +1123,8 @@ static int nd_intel_test_cmd_query_overwrite(struct nfit_test *t, | |||
1115 | 1123 | ||
1116 | if (time_is_before_jiffies64(sec->overwrite_end_time)) { | 1124 | if (time_is_before_jiffies64(sec->overwrite_end_time)) { |
1117 | sec->overwrite_end_time = 0; | 1125 | sec->overwrite_end_time = 0; |
1118 | sec->state = 0; | 1126 | sec->state = sec->old_state; |
1127 | sec->old_state = 0; | ||
1119 | sec->ext_state = ND_INTEL_SEC_ESTATE_ENABLED; | 1128 | sec->ext_state = ND_INTEL_SEC_ESTATE_ENABLED; |
1120 | dev_dbg(dev, "overwrite is complete\n"); | 1129 | dev_dbg(dev, "overwrite is complete\n"); |
1121 | } else | 1130 | } else |