diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-28 18:05:13 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-28 18:05:13 -0500 |
| commit | 75f95da078b2891cd186f074ffc15a8e7c3f082d (patch) | |
| tree | 2ba8da10d0d1e20565e893a777d4349fe9d483dd /include/linux | |
| parent | 4ed7bdc1eb4c82cf4bfdf6a94dd36fd695f6f387 (diff) | |
| parent | 4b5f747e82b12b6d8ab815fc259827a615c7f2c3 (diff) | |
Merge tag 'libnvdimm-for-4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull libnvdimm updates from Dan Williams:
"The vast bulk of this update is the new support for the security
capabilities of some nvdimms.
The userspace tooling for this capability is still a work in progress,
but the changes survive the existing libnvdimm unit tests. The changes
also pass manual checkout on hardware and the new nfit_test emulation
of the security capability.
The touches of the security/keys/ files have received the necessary
acks from Mimi and David. Those changes were necessary to allow for a
new generic encrypted-key type, and allow the nvdimm sub-system to
lookup key material referenced by the libnvdimm-sysfs interface.
Summary:
- Add support for the security features of nvdimm devices that
implement a security model similar to ATA hard drive security. The
security model supports locking access to the media at
device-power-loss, to be unlocked with a passphrase, and
secure-erase (crypto-scramble).
Unlike the ATA security case where the kernel expects device
security to be managed in a pre-OS environment, the libnvdimm
security implementation allows key provisioning and key-operations
at OS runtime. Keys are managed with the kernel's encrypted-keys
facility to provide data-at-rest security for the libnvdimm key
material. The usage model mirrors fscrypt key management, but is
driven via libnvdimm sysfs.
- Miscellaneous updates for api usage and comment fixes"
* tag 'libnvdimm-for-4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: (21 commits)
libnvdimm/security: Quiet security operations
libnvdimm/security: Add documentation for nvdimm security support
tools/testing/nvdimm: add Intel DSM 1.8 support for nfit_test
tools/testing/nvdimm: Add overwrite support for nfit_test
tools/testing/nvdimm: Add test support for Intel nvdimm security DSMs
acpi/nfit, libnvdimm/security: add Intel DSM 1.8 master passphrase support
acpi/nfit, libnvdimm/security: Add security DSM overwrite support
acpi/nfit, libnvdimm: Add support for issue secure erase DSM to Intel nvdimm
acpi/nfit, libnvdimm: Add enable/update passphrase support for Intel nvdimms
acpi/nfit, libnvdimm: Add disable passphrase support to Intel nvdimm.
acpi/nfit, libnvdimm: Add unlock of nvdimm support for Intel DIMMs
acpi/nfit, libnvdimm: Add freeze security support to Intel nvdimm
acpi/nfit, libnvdimm: Introduce nvdimm_security_ops
keys-encrypted: add nvdimm key format type to encrypted keys
keys: Export lookup_user_key to external users
acpi/nfit, libnvdimm: Store dimm id as a member to struct nvdimm
libnvdimm, namespace: Replace kmemdup() with kstrndup()
libnvdimm, label: Switch to bitmap_zalloc()
ACPI/nfit: Adjust annotation for why return 0 if fail to find NFIT at start
libnvdimm, bus: Check id immediately following ida_simple_get
...
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/key.h | 3 | ||||
| -rw-r--r-- | include/linux/libnvdimm.h | 76 |
2 files changed, 74 insertions, 5 deletions
diff --git a/include/linux/key.h b/include/linux/key.h index e58ee10f6e58..7099985e35a9 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
| @@ -346,6 +346,9 @@ static inline key_serial_t key_serial(const struct key *key) | |||
| 346 | 346 | ||
| 347 | extern void key_set_timeout(struct key *, unsigned); | 347 | extern void key_set_timeout(struct key *, unsigned); |
| 348 | 348 | ||
| 349 | extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, | ||
| 350 | key_perm_t perm); | ||
| 351 | |||
| 349 | /* | 352 | /* |
| 350 | * The permissions required on a key that we're looking up. | 353 | * The permissions required on a key that we're looking up. |
| 351 | */ | 354 | */ |
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h index 097072c5a852..5440f11b0907 100644 --- a/include/linux/libnvdimm.h +++ b/include/linux/libnvdimm.h | |||
| @@ -38,6 +38,10 @@ enum { | |||
| 38 | NDD_UNARMED = 1, | 38 | NDD_UNARMED = 1, |
| 39 | /* locked memory devices should not be accessed */ | 39 | /* locked memory devices should not be accessed */ |
| 40 | NDD_LOCKED = 2, | 40 | NDD_LOCKED = 2, |
| 41 | /* memory under security wipes should not be accessed */ | ||
| 42 | NDD_SECURITY_OVERWRITE = 3, | ||
| 43 | /* tracking whether or not there is a pending device reference */ | ||
| 44 | NDD_WORK_PENDING = 4, | ||
| 41 | 45 | ||
| 42 | /* need to set a limit somewhere, but yes, this is likely overkill */ | 46 | /* need to set a limit somewhere, but yes, this is likely overkill */ |
| 43 | ND_IOCTL_MAX_BUFLEN = SZ_4M, | 47 | ND_IOCTL_MAX_BUFLEN = SZ_4M, |
| @@ -87,7 +91,7 @@ struct nvdimm_bus_descriptor { | |||
| 87 | ndctl_fn ndctl; | 91 | ndctl_fn ndctl; |
| 88 | int (*flush_probe)(struct nvdimm_bus_descriptor *nd_desc); | 92 | int (*flush_probe)(struct nvdimm_bus_descriptor *nd_desc); |
| 89 | int (*clear_to_send)(struct nvdimm_bus_descriptor *nd_desc, | 93 | int (*clear_to_send)(struct nvdimm_bus_descriptor *nd_desc, |
| 90 | struct nvdimm *nvdimm, unsigned int cmd); | 94 | struct nvdimm *nvdimm, unsigned int cmd, void *data); |
| 91 | }; | 95 | }; |
| 92 | 96 | ||
| 93 | struct nd_cmd_desc { | 97 | struct nd_cmd_desc { |
| @@ -155,6 +159,46 @@ static inline struct nd_blk_region_desc *to_blk_region_desc( | |||
| 155 | 159 | ||
| 156 | } | 160 | } |
| 157 | 161 | ||
| 162 | enum nvdimm_security_state { | ||
| 163 | NVDIMM_SECURITY_DISABLED, | ||
| 164 | NVDIMM_SECURITY_UNLOCKED, | ||
| 165 | NVDIMM_SECURITY_LOCKED, | ||
| 166 | NVDIMM_SECURITY_FROZEN, | ||
| 167 | NVDIMM_SECURITY_OVERWRITE, | ||
| 168 | }; | ||
| 169 | |||
| 170 | #define NVDIMM_PASSPHRASE_LEN 32 | ||
| 171 | #define NVDIMM_KEY_DESC_LEN 22 | ||
| 172 | |||
| 173 | struct nvdimm_key_data { | ||
| 174 | u8 data[NVDIMM_PASSPHRASE_LEN]; | ||
| 175 | }; | ||
| 176 | |||
| 177 | enum nvdimm_passphrase_type { | ||
| 178 | NVDIMM_USER, | ||
| 179 | NVDIMM_MASTER, | ||
| 180 | }; | ||
| 181 | |||
| 182 | struct nvdimm_security_ops { | ||
| 183 | enum nvdimm_security_state (*state)(struct nvdimm *nvdimm, | ||
| 184 | enum nvdimm_passphrase_type pass_type); | ||
| 185 | int (*freeze)(struct nvdimm *nvdimm); | ||
| 186 | int (*change_key)(struct nvdimm *nvdimm, | ||
| 187 | const struct nvdimm_key_data *old_data, | ||
| 188 | const struct nvdimm_key_data *new_data, | ||
| 189 | enum nvdimm_passphrase_type pass_type); | ||
| 190 | int (*unlock)(struct nvdimm *nvdimm, | ||
| 191 | const struct nvdimm_key_data *key_data); | ||
| 192 | int (*disable)(struct nvdimm *nvdimm, | ||
| 193 | const struct nvdimm_key_data *key_data); | ||
| 194 | int (*erase)(struct nvdimm *nvdimm, | ||
| 195 | const struct nvdimm_key_data *key_data, | ||
| 196 | enum nvdimm_passphrase_type pass_type); | ||
| 197 | int (*overwrite)(struct nvdimm *nvdimm, | ||
| 198 | const struct nvdimm_key_data *key_data); | ||
| 199 | int (*query_overwrite)(struct nvdimm *nvdimm); | ||
| 200 | }; | ||
| 201 | |||
| 158 | void badrange_init(struct badrange *badrange); | 202 | void badrange_init(struct badrange *badrange); |
| 159 | int badrange_add(struct badrange *badrange, u64 addr, u64 length); | 203 | int badrange_add(struct badrange *badrange, u64 addr, u64 length); |
| 160 | void badrange_forget(struct badrange *badrange, phys_addr_t start, | 204 | void badrange_forget(struct badrange *badrange, phys_addr_t start, |
| @@ -165,6 +209,7 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent, | |||
| 165 | struct nvdimm_bus_descriptor *nfit_desc); | 209 | struct nvdimm_bus_descriptor *nfit_desc); |
| 166 | void nvdimm_bus_unregister(struct nvdimm_bus *nvdimm_bus); | 210 | void nvdimm_bus_unregister(struct nvdimm_bus *nvdimm_bus); |
| 167 | struct nvdimm_bus *to_nvdimm_bus(struct device *dev); | 211 | struct nvdimm_bus *to_nvdimm_bus(struct device *dev); |
| 212 | struct nvdimm_bus *nvdimm_to_bus(struct nvdimm *nvdimm); | ||
| 168 | struct nvdimm *to_nvdimm(struct device *dev); | 213 | struct nvdimm *to_nvdimm(struct device *dev); |
| 169 | struct nd_region *to_nd_region(struct device *dev); | 214 | struct nd_region *to_nd_region(struct device *dev); |
| 170 | struct device *nd_region_dev(struct nd_region *nd_region); | 215 | struct device *nd_region_dev(struct nd_region *nd_region); |
| @@ -175,10 +220,21 @@ const char *nvdimm_name(struct nvdimm *nvdimm); | |||
| 175 | struct kobject *nvdimm_kobj(struct nvdimm *nvdimm); | 220 | struct kobject *nvdimm_kobj(struct nvdimm *nvdimm); |
| 176 | unsigned long nvdimm_cmd_mask(struct nvdimm *nvdimm); | 221 | unsigned long nvdimm_cmd_mask(struct nvdimm *nvdimm); |
| 177 | void *nvdimm_provider_data(struct nvdimm *nvdimm); | 222 | void *nvdimm_provider_data(struct nvdimm *nvdimm); |
| 178 | struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data, | 223 | struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus, |
| 179 | const struct attribute_group **groups, unsigned long flags, | 224 | void *provider_data, const struct attribute_group **groups, |
| 180 | unsigned long cmd_mask, int num_flush, | 225 | unsigned long flags, unsigned long cmd_mask, int num_flush, |
| 181 | struct resource *flush_wpq); | 226 | struct resource *flush_wpq, const char *dimm_id, |
| 227 | const struct nvdimm_security_ops *sec_ops); | ||
| 228 | static inline struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, | ||
| 229 | void *provider_data, const struct attribute_group **groups, | ||
| 230 | unsigned long flags, unsigned long cmd_mask, int num_flush, | ||
| 231 | struct resource *flush_wpq) | ||
| 232 | { | ||
| 233 | return __nvdimm_create(nvdimm_bus, provider_data, groups, flags, | ||
| 234 | cmd_mask, num_flush, flush_wpq, NULL, NULL); | ||
| 235 | } | ||
| 236 | |||
| 237 | int nvdimm_security_setup_events(struct nvdimm *nvdimm); | ||
| 182 | const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd); | 238 | const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd); |
| 183 | const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd); | 239 | const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd); |
| 184 | u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd, | 240 | u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd, |
| @@ -204,6 +260,16 @@ u64 nd_fletcher64(void *addr, size_t len, bool le); | |||
| 204 | void nvdimm_flush(struct nd_region *nd_region); | 260 | void nvdimm_flush(struct nd_region *nd_region); |
| 205 | int nvdimm_has_flush(struct nd_region *nd_region); | 261 | int nvdimm_has_flush(struct nd_region *nd_region); |
| 206 | int nvdimm_has_cache(struct nd_region *nd_region); | 262 | int nvdimm_has_cache(struct nd_region *nd_region); |
| 263 | int nvdimm_in_overwrite(struct nvdimm *nvdimm); | ||
| 264 | |||
| 265 | static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf, | ||
| 266 | unsigned int buf_len, int *cmd_rc) | ||
| 267 | { | ||
| 268 | struct nvdimm_bus *nvdimm_bus = nvdimm_to_bus(nvdimm); | ||
| 269 | struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus); | ||
| 270 | |||
| 271 | return nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, cmd_rc); | ||
| 272 | } | ||
| 207 | 273 | ||
| 208 | #ifdef CONFIG_ARCH_HAS_PMEM_API | 274 | #ifdef CONFIG_ARCH_HAS_PMEM_API |
| 209 | #define ARCH_MEMREMAP_PMEM MEMREMAP_WB | 275 | #define ARCH_MEMREMAP_PMEM MEMREMAP_WB |
