diff options
Diffstat (limited to 'drivers/nvdimm/dimm_devs.c')
-rw-r--r-- | drivers/nvdimm/dimm_devs.c | 134 |
1 files changed, 31 insertions, 103 deletions
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index 29a065e769ea..196aa44c4936 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c | |||
@@ -372,106 +372,26 @@ __weak ssize_t security_show(struct device *dev, | |||
372 | { | 372 | { |
373 | struct nvdimm *nvdimm = to_nvdimm(dev); | 373 | struct nvdimm *nvdimm = to_nvdimm(dev); |
374 | 374 | ||
375 | switch (nvdimm->sec.state) { | 375 | if (test_bit(NVDIMM_SECURITY_DISABLED, &nvdimm->sec.flags)) |
376 | case NVDIMM_SECURITY_DISABLED: | ||
377 | return sprintf(buf, "disabled\n"); | 376 | return sprintf(buf, "disabled\n"); |
378 | case NVDIMM_SECURITY_UNLOCKED: | 377 | if (test_bit(NVDIMM_SECURITY_UNLOCKED, &nvdimm->sec.flags)) |
379 | return sprintf(buf, "unlocked\n"); | 378 | return sprintf(buf, "unlocked\n"); |
380 | case NVDIMM_SECURITY_LOCKED: | 379 | if (test_bit(NVDIMM_SECURITY_LOCKED, &nvdimm->sec.flags)) |
381 | return sprintf(buf, "locked\n"); | 380 | return sprintf(buf, "locked\n"); |
382 | case NVDIMM_SECURITY_FROZEN: | 381 | if (test_bit(NVDIMM_SECURITY_OVERWRITE, &nvdimm->sec.flags)) |
383 | return sprintf(buf, "frozen\n"); | ||
384 | case NVDIMM_SECURITY_OVERWRITE: | ||
385 | return sprintf(buf, "overwrite\n"); | 382 | return sprintf(buf, "overwrite\n"); |
386 | default: | ||
387 | return -ENOTTY; | ||
388 | } | ||
389 | |||
390 | return -ENOTTY; | 383 | return -ENOTTY; |
391 | } | 384 | } |
392 | 385 | ||
393 | #define OPS \ | 386 | static ssize_t frozen_show(struct device *dev, |
394 | C( OP_FREEZE, "freeze", 1), \ | 387 | struct device_attribute *attr, char *buf) |
395 | C( OP_DISABLE, "disable", 2), \ | ||
396 | C( OP_UPDATE, "update", 3), \ | ||
397 | C( OP_ERASE, "erase", 2), \ | ||
398 | C( OP_OVERWRITE, "overwrite", 2), \ | ||
399 | C( OP_MASTER_UPDATE, "master_update", 3), \ | ||
400 | C( OP_MASTER_ERASE, "master_erase", 2) | ||
401 | #undef C | ||
402 | #define C(a, b, c) a | ||
403 | enum nvdimmsec_op_ids { OPS }; | ||
404 | #undef C | ||
405 | #define C(a, b, c) { b, c } | ||
406 | static struct { | ||
407 | const char *name; | ||
408 | int args; | ||
409 | } ops[] = { OPS }; | ||
410 | #undef C | ||
411 | |||
412 | #define SEC_CMD_SIZE 32 | ||
413 | #define KEY_ID_SIZE 10 | ||
414 | |||
415 | static ssize_t __security_store(struct device *dev, const char *buf, size_t len) | ||
416 | { | 388 | { |
417 | struct nvdimm *nvdimm = to_nvdimm(dev); | 389 | struct nvdimm *nvdimm = to_nvdimm(dev); |
418 | ssize_t rc; | ||
419 | char cmd[SEC_CMD_SIZE+1], keystr[KEY_ID_SIZE+1], | ||
420 | nkeystr[KEY_ID_SIZE+1]; | ||
421 | unsigned int key, newkey; | ||
422 | int i; | ||
423 | 390 | ||
424 | if (atomic_read(&nvdimm->busy)) | 391 | return sprintf(buf, "%d\n", test_bit(NVDIMM_SECURITY_FROZEN, |
425 | return -EBUSY; | 392 | &nvdimm->sec.flags)); |
426 | |||
427 | rc = sscanf(buf, "%"__stringify(SEC_CMD_SIZE)"s" | ||
428 | " %"__stringify(KEY_ID_SIZE)"s" | ||
429 | " %"__stringify(KEY_ID_SIZE)"s", | ||
430 | cmd, keystr, nkeystr); | ||
431 | if (rc < 1) | ||
432 | return -EINVAL; | ||
433 | for (i = 0; i < ARRAY_SIZE(ops); i++) | ||
434 | if (sysfs_streq(cmd, ops[i].name)) | ||
435 | break; | ||
436 | if (i >= ARRAY_SIZE(ops)) | ||
437 | return -EINVAL; | ||
438 | if (ops[i].args > 1) | ||
439 | rc = kstrtouint(keystr, 0, &key); | ||
440 | if (rc >= 0 && ops[i].args > 2) | ||
441 | rc = kstrtouint(nkeystr, 0, &newkey); | ||
442 | if (rc < 0) | ||
443 | return rc; | ||
444 | |||
445 | if (i == OP_FREEZE) { | ||
446 | dev_dbg(dev, "freeze\n"); | ||
447 | rc = nvdimm_security_freeze(nvdimm); | ||
448 | } else if (i == OP_DISABLE) { | ||
449 | dev_dbg(dev, "disable %u\n", key); | ||
450 | rc = nvdimm_security_disable(nvdimm, key); | ||
451 | } else if (i == OP_UPDATE) { | ||
452 | dev_dbg(dev, "update %u %u\n", key, newkey); | ||
453 | rc = nvdimm_security_update(nvdimm, key, newkey, NVDIMM_USER); | ||
454 | } else if (i == OP_ERASE) { | ||
455 | dev_dbg(dev, "erase %u\n", key); | ||
456 | rc = nvdimm_security_erase(nvdimm, key, NVDIMM_USER); | ||
457 | } else if (i == OP_OVERWRITE) { | ||
458 | dev_dbg(dev, "overwrite %u\n", key); | ||
459 | rc = nvdimm_security_overwrite(nvdimm, key); | ||
460 | } else if (i == OP_MASTER_UPDATE) { | ||
461 | dev_dbg(dev, "master_update %u %u\n", key, newkey); | ||
462 | rc = nvdimm_security_update(nvdimm, key, newkey, | ||
463 | NVDIMM_MASTER); | ||
464 | } else if (i == OP_MASTER_ERASE) { | ||
465 | dev_dbg(dev, "master_erase %u\n", key); | ||
466 | rc = nvdimm_security_erase(nvdimm, key, | ||
467 | NVDIMM_MASTER); | ||
468 | } else | ||
469 | return -EINVAL; | ||
470 | |||
471 | if (rc == 0) | ||
472 | rc = len; | ||
473 | return rc; | ||
474 | } | 393 | } |
394 | static DEVICE_ATTR_RO(frozen); | ||
475 | 395 | ||
476 | static ssize_t security_store(struct device *dev, | 396 | static ssize_t security_store(struct device *dev, |
477 | struct device_attribute *attr, const char *buf, size_t len) | 397 | struct device_attribute *attr, const char *buf, size_t len) |
@@ -487,7 +407,7 @@ static ssize_t security_store(struct device *dev, | |||
487 | nd_device_lock(dev); | 407 | nd_device_lock(dev); |
488 | nvdimm_bus_lock(dev); | 408 | nvdimm_bus_lock(dev); |
489 | wait_nvdimm_bus_probe_idle(dev); | 409 | wait_nvdimm_bus_probe_idle(dev); |
490 | rc = __security_store(dev, buf, len); | 410 | rc = nvdimm_security_store(dev, buf, len); |
491 | nvdimm_bus_unlock(dev); | 411 | nvdimm_bus_unlock(dev); |
492 | nd_device_unlock(dev); | 412 | nd_device_unlock(dev); |
493 | 413 | ||
@@ -501,6 +421,7 @@ static struct attribute *nvdimm_attributes[] = { | |||
501 | &dev_attr_commands.attr, | 421 | &dev_attr_commands.attr, |
502 | &dev_attr_available_slots.attr, | 422 | &dev_attr_available_slots.attr, |
503 | &dev_attr_security.attr, | 423 | &dev_attr_security.attr, |
424 | &dev_attr_frozen.attr, | ||
504 | NULL, | 425 | NULL, |
505 | }; | 426 | }; |
506 | 427 | ||
@@ -509,17 +430,24 @@ static umode_t nvdimm_visible(struct kobject *kobj, struct attribute *a, int n) | |||
509 | struct device *dev = container_of(kobj, typeof(*dev), kobj); | 430 | struct device *dev = container_of(kobj, typeof(*dev), kobj); |
510 | struct nvdimm *nvdimm = to_nvdimm(dev); | 431 | struct nvdimm *nvdimm = to_nvdimm(dev); |
511 | 432 | ||
512 | if (a != &dev_attr_security.attr) | 433 | if (a != &dev_attr_security.attr && a != &dev_attr_frozen.attr) |
513 | return a->mode; | 434 | return a->mode; |
514 | if (nvdimm->sec.state < 0) | 435 | if (!nvdimm->sec.flags) |
515 | return 0; | 436 | return 0; |
516 | /* Are there any state mutation ops? */ | 437 | |
517 | if (nvdimm->sec.ops->freeze || nvdimm->sec.ops->disable | 438 | if (a == &dev_attr_security.attr) { |
518 | || nvdimm->sec.ops->change_key | 439 | /* Are there any state mutation ops (make writable)? */ |
519 | || nvdimm->sec.ops->erase | 440 | if (nvdimm->sec.ops->freeze || nvdimm->sec.ops->disable |
520 | || nvdimm->sec.ops->overwrite) | 441 | || nvdimm->sec.ops->change_key |
442 | || nvdimm->sec.ops->erase | ||
443 | || nvdimm->sec.ops->overwrite) | ||
444 | return a->mode; | ||
445 | return 0444; | ||
446 | } | ||
447 | |||
448 | if (nvdimm->sec.ops->freeze) | ||
521 | return a->mode; | 449 | return a->mode; |
522 | return 0444; | 450 | return 0; |
523 | } | 451 | } |
524 | 452 | ||
525 | struct attribute_group nvdimm_attribute_group = { | 453 | struct attribute_group nvdimm_attribute_group = { |
@@ -569,8 +497,8 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus, | |||
569 | * attribute visibility. | 497 | * attribute visibility. |
570 | */ | 498 | */ |
571 | /* get security state and extended (master) state */ | 499 | /* get security state and extended (master) state */ |
572 | nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); | 500 | nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER); |
573 | nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, NVDIMM_MASTER); | 501 | nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER); |
574 | nd_device_register(dev); | 502 | nd_device_register(dev); |
575 | 503 | ||
576 | return nvdimm; | 504 | return nvdimm; |
@@ -588,7 +516,7 @@ int nvdimm_security_setup_events(struct device *dev) | |||
588 | { | 516 | { |
589 | struct nvdimm *nvdimm = to_nvdimm(dev); | 517 | struct nvdimm *nvdimm = to_nvdimm(dev); |
590 | 518 | ||
591 | if (nvdimm->sec.state < 0 || !nvdimm->sec.ops | 519 | if (!nvdimm->sec.flags || !nvdimm->sec.ops |
592 | || !nvdimm->sec.ops->overwrite) | 520 | || !nvdimm->sec.ops->overwrite) |
593 | return 0; | 521 | return 0; |
594 | nvdimm->sec.overwrite_state = sysfs_get_dirent(dev->kobj.sd, "security"); | 522 | nvdimm->sec.overwrite_state = sysfs_get_dirent(dev->kobj.sd, "security"); |
@@ -614,7 +542,7 @@ int nvdimm_security_freeze(struct nvdimm *nvdimm) | |||
614 | if (!nvdimm->sec.ops || !nvdimm->sec.ops->freeze) | 542 | if (!nvdimm->sec.ops || !nvdimm->sec.ops->freeze) |
615 | return -EOPNOTSUPP; | 543 | return -EOPNOTSUPP; |
616 | 544 | ||
617 | if (nvdimm->sec.state < 0) | 545 | if (!nvdimm->sec.flags) |
618 | return -EIO; | 546 | return -EIO; |
619 | 547 | ||
620 | if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) { | 548 | if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) { |
@@ -623,7 +551,7 @@ int nvdimm_security_freeze(struct nvdimm *nvdimm) | |||
623 | } | 551 | } |
624 | 552 | ||
625 | rc = nvdimm->sec.ops->freeze(nvdimm); | 553 | rc = nvdimm->sec.ops->freeze(nvdimm); |
626 | nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); | 554 | nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER); |
627 | 555 | ||
628 | return rc; | 556 | return rc; |
629 | } | 557 | } |