Skip to content

Commit 618d919

Browse files
committed
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
2 parents 5512320 + 2170a0d commit 618d919

File tree

7 files changed

+117
-71
lines changed

7 files changed

+117
-71
lines changed

drivers/acpi/nfit/core.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,12 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
567567
goto out;
568568
}
569569

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+
570576
if (call_pkg) {
571577
call_pkg->nd_fw_size = out_obj->buffer.length;
572578
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,
585591
return 0;
586592
}
587593

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-
594594
for (i = 0, offset = 0; i < desc->out_num; i++) {
595595
u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, buf,
596596
(u32 *) out_obj->buffer.pointer,

drivers/acpi/nfit/intel.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,8 @@ static int intel_security_change_key(struct nvdimm *nvdimm,
122122
if (!test_bit(cmd, &nfit_mem->dsm_mask))
123123
return -ENOTTY;
124124

125-
if (old_data)
126-
memcpy(nd_cmd.cmd.old_pass, old_data->data,
127-
sizeof(nd_cmd.cmd.old_pass));
125+
memcpy(nd_cmd.cmd.old_pass, old_data->data,
126+
sizeof(nd_cmd.cmd.old_pass));
128127
memcpy(nd_cmd.cmd.new_pass, new_data->data,
129128
sizeof(nd_cmd.cmd.new_pass));
130129
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,
336335

337336
/* flush all cache before we erase DIMM */
338337
nvdimm_invalidate_cache();
339-
if (nkey)
340-
memcpy(nd_cmd.cmd.passphrase, nkey->data,
341-
sizeof(nd_cmd.cmd.passphrase));
338+
memcpy(nd_cmd.cmd.passphrase, nkey->data,
339+
sizeof(nd_cmd.cmd.passphrase));
342340
rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
343341
if (rc < 0)
344342
return rc;

drivers/nvdimm/btt_devs.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,14 +198,15 @@ static struct device *__nd_btt_create(struct nd_region *nd_region,
198198
return NULL;
199199

200200
nd_btt->id = ida_simple_get(&nd_region->btt_ida, 0, 0, GFP_KERNEL);
201-
if (nd_btt->id < 0) {
202-
kfree(nd_btt);
203-
return NULL;
204-
}
201+
if (nd_btt->id < 0)
202+
goto out_nd_btt;
205203

206204
nd_btt->lbasize = lbasize;
207-
if (uuid)
205+
if (uuid) {
208206
uuid = kmemdup(uuid, 16, GFP_KERNEL);
207+
if (!uuid)
208+
goto out_put_id;
209+
}
209210
nd_btt->uuid = uuid;
210211
dev = &nd_btt->dev;
211212
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,
220221
return NULL;
221222
}
222223
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;
223231
}
224232

225233
struct device *nd_btt_create(struct nd_region *nd_region)

drivers/nvdimm/namespace_devs.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2249,9 +2249,12 @@ static struct device *create_namespace_blk(struct nd_region *nd_region,
22492249
if (!nsblk->uuid)
22502250
goto blk_err;
22512251
memcpy(name, nd_label->name, NSLABEL_NAME_LEN);
2252-
if (name[0])
2252+
if (name[0]) {
22532253
nsblk->alt_name = kmemdup(name, NSLABEL_NAME_LEN,
22542254
GFP_KERNEL);
2255+
if (!nsblk->alt_name)
2256+
goto blk_err;
2257+
}
22552258
res = nsblk_add_resource(nd_region, ndd, nsblk,
22562259
__le64_to_cpu(nd_label->dpa));
22572260
if (!res)

drivers/nvdimm/pmem.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,13 @@ static void write_pmem(void *pmem_addr, struct page *page,
113113

114114
while (len) {
115115
mem = kmap_atomic(page);
116-
chunk = min_t(unsigned int, len, PAGE_SIZE);
116+
chunk = min_t(unsigned int, len, PAGE_SIZE - off);
117117
memcpy_flushcache(pmem_addr, mem + off, chunk);
118118
kunmap_atomic(mem);
119119
len -= chunk;
120120
off = 0;
121121
page++;
122-
pmem_addr += PAGE_SIZE;
122+
pmem_addr += chunk;
123123
}
124124
}
125125

@@ -132,15 +132,15 @@ static blk_status_t read_pmem(struct page *page, unsigned int off,
132132

133133
while (len) {
134134
mem = kmap_atomic(page);
135-
chunk = min_t(unsigned int, len, PAGE_SIZE);
135+
chunk = min_t(unsigned int, len, PAGE_SIZE - off);
136136
rem = memcpy_mcsafe(mem + off, pmem_addr, chunk);
137137
kunmap_atomic(mem);
138138
if (rem)
139139
return BLK_STS_IOERR;
140140
len -= chunk;
141141
off = 0;
142142
page++;
143-
pmem_addr += PAGE_SIZE;
143+
pmem_addr += chunk;
144144
}
145145
return BLK_STS_OK;
146146
}

drivers/nvdimm/security.c

Lines changed: 73 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ static bool key_revalidate = true;
2222
module_param(key_revalidate, bool, 0444);
2323
MODULE_PARM_DESC(key_revalidate, "Require key validation at init.");
2424

25+
static const char zero_key[NVDIMM_PASSPHRASE_LEN];
26+
2527
static void *key_data(struct key *key)
2628
{
2729
struct encrypted_key_payload *epayload = dereference_key_locked(key);
@@ -75,6 +77,16 @@ static struct key *nvdimm_request_key(struct nvdimm *nvdimm)
7577
return key;
7678
}
7779

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+
7890
static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm,
7991
key_serial_t id, int subclass)
8092
{
@@ -105,36 +117,57 @@ static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm,
105117
return key;
106118
}
107119

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)
109140
{
110141
struct key *key;
111142
int rc;
143+
const void *data;
112144

113145
if (!nvdimm->sec.ops->change_key)
114-
return NULL;
146+
return -EOPNOTSUPP;
115147

116-
key = nvdimm_request_key(nvdimm);
117-
if (!key)
118-
return NULL;
148+
data = nvdimm_get_key_payload(nvdimm, &key);
119149

120150
/*
121151
* Send the same key to the hardware as new and old key to
122152
* verify that the key is good.
123153
*/
124-
rc = nvdimm->sec.ops->change_key(nvdimm, key_data(key),
125-
key_data(key), NVDIMM_USER);
154+
rc = nvdimm->sec.ops->change_key(nvdimm, data, data, NVDIMM_USER);
126155
if (rc < 0) {
127156
nvdimm_put_key(key);
128-
key = NULL;
157+
return rc;
129158
}
130-
return key;
159+
160+
nvdimm_put_key(key);
161+
nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
162+
return 0;
131163
}
132164

133165
static int __nvdimm_security_unlock(struct nvdimm *nvdimm)
134166
{
135167
struct device *dev = &nvdimm->dev;
136168
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
137-
struct key *key = NULL;
169+
struct key *key;
170+
const void *data;
138171
int rc;
139172

140173
/* 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)
160193
if (!key_revalidate)
161194
return 0;
162195

163-
key = nvdimm_key_revalidate(nvdimm);
164-
if (!key)
165-
return nvdimm_security_freeze(nvdimm);
196+
return nvdimm_key_revalidate(nvdimm);
166197
} else
167-
key = nvdimm_request_key(nvdimm);
198+
data = nvdimm_get_key_payload(nvdimm, &key);
168199

169-
if (!key)
170-
return -ENOKEY;
171-
172-
rc = nvdimm->sec.ops->unlock(nvdimm, key_data(key));
200+
rc = nvdimm->sec.ops->unlock(nvdimm, data);
173201
dev_dbg(dev, "key: %d unlock: %s\n", key_serial(key),
174202
rc == 0 ? "success" : "fail");
175203

@@ -195,6 +223,7 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
195223
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
196224
struct key *key;
197225
int rc;
226+
const void *data;
198227

199228
/* The bus lock should be held at the top level of the call stack */
200229
lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
@@ -214,11 +243,12 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
214243
return -EBUSY;
215244
}
216245

217-
key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY);
218-
if (!key)
246+
data = nvdimm_get_user_key_payload(nvdimm, keyid,
247+
NVDIMM_BASE_KEY, &key);
248+
if (!data)
219249
return -ENOKEY;
220250

221-
rc = nvdimm->sec.ops->disable(nvdimm, key_data(key));
251+
rc = nvdimm->sec.ops->disable(nvdimm, data);
222252
dev_dbg(dev, "key: %d disable: %s\n", key_serial(key),
223253
rc == 0 ? "success" : "fail");
224254

@@ -235,6 +265,7 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
235265
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
236266
struct key *key, *newkey;
237267
int rc;
268+
const void *data, *newdata;
238269

239270
/* The bus lock should be held at the top level of the call stack */
240271
lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
@@ -249,22 +280,19 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
249280
return -EIO;
250281
}
251282

252-
if (keyid == 0)
253-
key = NULL;
254-
else {
255-
key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY);
256-
if (!key)
257-
return -ENOKEY;
258-
}
283+
data = nvdimm_get_user_key_payload(nvdimm, keyid,
284+
NVDIMM_BASE_KEY, &key);
285+
if (!data)
286+
return -ENOKEY;
259287

260-
newkey = nvdimm_lookup_user_key(nvdimm, new_keyid, NVDIMM_NEW_KEY);
261-
if (!newkey) {
288+
newdata = nvdimm_get_user_key_payload(nvdimm, new_keyid,
289+
NVDIMM_NEW_KEY, &newkey);
290+
if (!newdata) {
262291
nvdimm_put_key(key);
263292
return -ENOKEY;
264293
}
265294

266-
rc = nvdimm->sec.ops->change_key(nvdimm, key ? key_data(key) : NULL,
267-
key_data(newkey), pass_type);
295+
rc = nvdimm->sec.ops->change_key(nvdimm, data, newdata, pass_type);
268296
dev_dbg(dev, "key: %d %d update%s: %s\n",
269297
key_serial(key), key_serial(newkey),
270298
pass_type == NVDIMM_MASTER ? "(master)" : "(user)",
@@ -286,8 +314,9 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid,
286314
{
287315
struct device *dev = &nvdimm->dev;
288316
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
289-
struct key *key;
317+
struct key *key = NULL;
290318
int rc;
319+
const void *data;
291320

292321
/* The bus lock should be held at the top level of the call stack */
293322
lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
@@ -319,11 +348,12 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid,
319348
return -EOPNOTSUPP;
320349
}
321350

322-
key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY);
323-
if (!key)
351+
data = nvdimm_get_user_key_payload(nvdimm, keyid,
352+
NVDIMM_BASE_KEY, &key);
353+
if (!data)
324354
return -ENOKEY;
325355

326-
rc = nvdimm->sec.ops->erase(nvdimm, key_data(key), pass_type);
356+
rc = nvdimm->sec.ops->erase(nvdimm, data, pass_type);
327357
dev_dbg(dev, "key: %d erase%s: %s\n", key_serial(key),
328358
pass_type == NVDIMM_MASTER ? "(master)" : "(user)",
329359
rc == 0 ? "success" : "fail");
@@ -337,8 +367,9 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
337367
{
338368
struct device *dev = &nvdimm->dev;
339369
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
340-
struct key *key;
370+
struct key *key = NULL;
341371
int rc;
372+
const void *data;
342373

343374
/* The bus lock should be held at the top level of the call stack */
344375
lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
@@ -368,15 +399,12 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
368399
return -EBUSY;
369400
}
370401

371-
if (keyid == 0)
372-
key = NULL;
373-
else {
374-
key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY);
375-
if (!key)
376-
return -ENOKEY;
377-
}
402+
data = nvdimm_get_user_key_payload(nvdimm, keyid,
403+
NVDIMM_BASE_KEY, &key);
404+
if (!data)
405+
return -ENOKEY;
378406

379-
rc = nvdimm->sec.ops->overwrite(nvdimm, key ? key_data(key) : NULL);
407+
rc = nvdimm->sec.ops->overwrite(nvdimm, data);
380408
dev_dbg(dev, "key: %d overwrite submission: %s\n", key_serial(key),
381409
rc == 0 ? "success" : "fail");
382410

0 commit comments

Comments
 (0)