1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2021 Microsoft Corporation
5 * Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
8 * Enables IMA measurements for DM targets
14 #include <linux/ima.h>
15 #include <crypto/hash.h>
16 #include <linux/crypto.h>
17 #include <crypto/hash_info.h>
19 #define DM_MSG_PREFIX "ima"
22 * Internal function to prefix separator characters in input buffer with escape
23 * character, so that they don't interfere with the construction of key-value pairs,
24 * and clients can split the key1=val1,key2=val2,key3=val3; pairs properly.
26 static void fix_separator_chars(char **buf)
31 for (i = 0; i < l; i++)
32 if ((*buf)[i] == '\\' || (*buf)[i] == ';' || (*buf)[i] == '=' || (*buf)[i] == ',')
38 for (i = l-1, j = i+sp; i >= 0; i--) {
39 (*buf)[j--] = (*buf)[i];
40 if ((*buf)[i] == '\\' || (*buf)[i] == ';' || (*buf)[i] == '=' || (*buf)[i] == ',')
46 * Internal function to allocate memory for IMA measurements.
48 static void *dm_ima_alloc(size_t len, gfp_t flags, bool noio)
50 unsigned int noio_flag;
54 noio_flag = memalloc_noio_save();
56 ptr = kzalloc(len, flags);
59 memalloc_noio_restore(noio_flag);
65 * Internal function to allocate and copy name and uuid for IMA measurements.
67 static int dm_ima_alloc_and_copy_name_uuid(struct mapped_device *md, char **dev_name,
68 char **dev_uuid, bool noio)
71 *dev_name = dm_ima_alloc(DM_NAME_LEN*2, GFP_KERNEL, noio);
77 *dev_uuid = dm_ima_alloc(DM_UUID_LEN*2, GFP_KERNEL, noio);
83 r = dm_copy_name_and_uuid(md, *dev_name, *dev_uuid);
87 fix_separator_chars(dev_name);
88 fix_separator_chars(dev_uuid);
100 * Internal function to allocate and copy device data for IMA measurements.
102 static int dm_ima_alloc_and_copy_device_data(struct mapped_device *md, char **device_data,
103 unsigned int num_targets, bool noio)
105 char *dev_name = NULL, *dev_uuid = NULL;
108 r = dm_ima_alloc_and_copy_name_uuid(md, &dev_name, &dev_uuid, noio);
112 *device_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN, GFP_KERNEL, noio);
113 if (!(*device_data)) {
118 scnprintf(*device_data, DM_IMA_DEVICE_BUF_LEN,
119 "name=%s,uuid=%s,major=%d,minor=%d,minor_count=%d,num_targets=%u;",
120 dev_name, dev_uuid, md->disk->major, md->disk->first_minor,
121 md->disk->minors, num_targets);
129 * Internal wrapper function to call IMA to measure DM data.
131 static void dm_ima_measure_data(const char *event_name, const void *buf, size_t buf_len,
134 unsigned int noio_flag;
137 noio_flag = memalloc_noio_save();
139 ima_measure_critical_data(DM_NAME, event_name, buf, buf_len, false);
142 memalloc_noio_restore(noio_flag);
146 * Internal function to allocate and copy current device capacity for IMA measurements.
148 static int dm_ima_alloc_and_copy_capacity_str(struct mapped_device *md, char **capacity_str,
153 capacity = get_capacity(md->disk);
155 *capacity_str = dm_ima_alloc(DM_IMA_DEVICE_CAPACITY_BUF_LEN, GFP_KERNEL, noio);
156 if (!(*capacity_str))
159 scnprintf(*capacity_str, DM_IMA_DEVICE_BUF_LEN, "current_device_capacity=%llu;",
166 * Initialize/reset the dm ima related data structure variables.
168 void dm_ima_reset_data(struct mapped_device *md)
170 memset(&(md->ima), 0, sizeof(md->ima));
171 md->ima.dm_version_str_len = strlen(DM_IMA_VERSION_STR);
175 * Build up the IMA data for each target, and finally measure.
177 void dm_ima_measure_on_table_load(struct dm_table *table, unsigned int status_flags)
179 size_t device_data_buf_len, target_metadata_buf_len, target_data_buf_len, l = 0;
180 char *target_metadata_buf = NULL, *target_data_buf = NULL, *digest_buf = NULL;
181 char *ima_buf = NULL, *device_data_buf = NULL;
182 int digest_size, last_target_measured = -1, r;
183 status_type_t type = STATUSTYPE_IMA;
184 size_t cur_total_buf_len = 0;
185 unsigned int num_targets, i;
186 SHASH_DESC_ON_STACK(shash, NULL);
187 struct crypto_shash *tfm = NULL;
191 * In below hash_alg_prefix_len assignment +1 is for the additional char (':'),
192 * when prefixing the hash value with the hash algorithm name. e.g. sha256:<hash_value>.
194 const size_t hash_alg_prefix_len = strlen(DM_IMA_TABLE_HASH_ALG) + 1;
195 char table_load_event_name[] = "dm_table_load";
197 ima_buf = dm_ima_alloc(DM_IMA_MEASUREMENT_BUF_LEN, GFP_KERNEL, noio);
201 target_metadata_buf = dm_ima_alloc(DM_IMA_TARGET_METADATA_BUF_LEN, GFP_KERNEL, noio);
202 if (!target_metadata_buf)
205 target_data_buf = dm_ima_alloc(DM_IMA_TARGET_DATA_BUF_LEN, GFP_KERNEL, noio);
206 if (!target_data_buf)
209 num_targets = dm_table_get_num_targets(table);
211 if (dm_ima_alloc_and_copy_device_data(table->md, &device_data_buf, num_targets, noio))
214 tfm = crypto_alloc_shash(DM_IMA_TABLE_HASH_ALG, 0, 0);
219 digest_size = crypto_shash_digestsize(tfm);
220 digest = dm_ima_alloc(digest_size, GFP_KERNEL, noio);
224 r = crypto_shash_init(shash);
228 memcpy(ima_buf + l, DM_IMA_VERSION_STR, table->md->ima.dm_version_str_len);
229 l += table->md->ima.dm_version_str_len;
231 device_data_buf_len = strlen(device_data_buf);
232 memcpy(ima_buf + l, device_data_buf, device_data_buf_len);
233 l += device_data_buf_len;
235 for (i = 0; i < num_targets; i++) {
236 struct dm_target *ti = dm_table_get_target(table, i);
241 last_target_measured = 0;
244 * First retrieve the target metadata.
246 scnprintf(target_metadata_buf, DM_IMA_TARGET_METADATA_BUF_LEN,
247 "target_index=%d,target_begin=%llu,target_len=%llu,",
248 i, ti->begin, ti->len);
249 target_metadata_buf_len = strlen(target_metadata_buf);
252 * Then retrieve the actual target data.
254 if (ti->type->status)
255 ti->type->status(ti, type, status_flags, target_data_buf,
256 DM_IMA_TARGET_DATA_BUF_LEN);
258 target_data_buf[0] = '\0';
260 target_data_buf_len = strlen(target_data_buf);
263 * Check if the total data can fit into the IMA buffer.
265 cur_total_buf_len = l + target_metadata_buf_len + target_data_buf_len;
268 * IMA measurements for DM targets are best-effort.
269 * If the total data buffered so far, including the current target,
270 * is too large to fit into DM_IMA_MEASUREMENT_BUF_LEN, measure what
271 * we have in the current buffer, and continue measuring the remaining
272 * targets by prefixing the device metadata again.
274 if (unlikely(cur_total_buf_len >= DM_IMA_MEASUREMENT_BUF_LEN)) {
275 dm_ima_measure_data(table_load_event_name, ima_buf, l, noio);
276 r = crypto_shash_update(shash, (const u8 *)ima_buf, l);
280 memset(ima_buf, 0, DM_IMA_MEASUREMENT_BUF_LEN);
284 * Each new "dm_table_load" entry in IMA log should have device data
285 * prefix, so that multiple records from the same "dm_table_load" for
286 * a given device can be linked together.
288 memcpy(ima_buf + l, DM_IMA_VERSION_STR, table->md->ima.dm_version_str_len);
289 l += table->md->ima.dm_version_str_len;
291 memcpy(ima_buf + l, device_data_buf, device_data_buf_len);
292 l += device_data_buf_len;
295 * If this iteration of the for loop turns out to be the last target
296 * in the table, dm_ima_measure_data("dm_table_load", ...) doesn't need
297 * to be called again, just the hash needs to be finalized.
298 * "last_target_measured" tracks this state.
300 last_target_measured = 1;
304 * Fill-in all the target metadata, so that multiple targets for the same
305 * device can be linked together.
307 memcpy(ima_buf + l, target_metadata_buf, target_metadata_buf_len);
308 l += target_metadata_buf_len;
310 memcpy(ima_buf + l, target_data_buf, target_data_buf_len);
311 l += target_data_buf_len;
314 if (!last_target_measured) {
315 dm_ima_measure_data(table_load_event_name, ima_buf, l, noio);
317 r = crypto_shash_update(shash, (const u8 *)ima_buf, l);
323 * Finalize the table hash, and store it in table->md->ima.inactive_table.hash,
324 * so that the table data can be verified against the future device state change
325 * events, e.g. resume, rename, remove, table-clear etc.
327 r = crypto_shash_final(shash, digest);
331 digest_buf = dm_ima_alloc((digest_size*2) + hash_alg_prefix_len + 1, GFP_KERNEL, noio);
336 snprintf(digest_buf, hash_alg_prefix_len + 1, "%s:", DM_IMA_TABLE_HASH_ALG);
338 for (i = 0; i < digest_size; i++)
339 snprintf((digest_buf + hash_alg_prefix_len + (i*2)), 3, "%02x", digest[i]);
341 if (table->md->ima.active_table.hash != table->md->ima.inactive_table.hash)
342 kfree(table->md->ima.inactive_table.hash);
344 table->md->ima.inactive_table.hash = digest_buf;
345 table->md->ima.inactive_table.hash_len = strlen(digest_buf);
346 table->md->ima.inactive_table.num_targets = num_targets;
348 if (table->md->ima.active_table.device_metadata !=
349 table->md->ima.inactive_table.device_metadata)
350 kfree(table->md->ima.inactive_table.device_metadata);
352 table->md->ima.inactive_table.device_metadata = device_data_buf;
353 table->md->ima.inactive_table.device_metadata_len = device_data_buf_len;
358 kfree(device_data_buf);
362 crypto_free_shash(tfm);
364 kfree(target_metadata_buf);
365 kfree(target_data_buf);
369 * Measure IMA data on device resume.
371 void dm_ima_measure_on_device_resume(struct mapped_device *md, bool swap)
373 char *device_table_data, *dev_name = NULL, *dev_uuid = NULL, *capacity_str = NULL;
374 char active[] = "active_table_hash=";
375 unsigned int active_len = strlen(active), capacity_len = 0;
381 device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN, GFP_KERNEL, noio);
382 if (!device_table_data)
385 r = dm_ima_alloc_and_copy_capacity_str(md, &capacity_str, noio);
389 memcpy(device_table_data + l, DM_IMA_VERSION_STR, md->ima.dm_version_str_len);
390 l += md->ima.dm_version_str_len;
393 if (md->ima.active_table.hash != md->ima.inactive_table.hash)
394 kfree(md->ima.active_table.hash);
396 md->ima.active_table.hash = NULL;
397 md->ima.active_table.hash_len = 0;
399 if (md->ima.active_table.device_metadata !=
400 md->ima.inactive_table.device_metadata)
401 kfree(md->ima.active_table.device_metadata);
403 md->ima.active_table.device_metadata = NULL;
404 md->ima.active_table.device_metadata_len = 0;
405 md->ima.active_table.num_targets = 0;
407 if (md->ima.inactive_table.hash) {
408 md->ima.active_table.hash = md->ima.inactive_table.hash;
409 md->ima.active_table.hash_len = md->ima.inactive_table.hash_len;
410 md->ima.inactive_table.hash = NULL;
411 md->ima.inactive_table.hash_len = 0;
414 if (md->ima.inactive_table.device_metadata) {
415 md->ima.active_table.device_metadata =
416 md->ima.inactive_table.device_metadata;
417 md->ima.active_table.device_metadata_len =
418 md->ima.inactive_table.device_metadata_len;
419 md->ima.active_table.num_targets = md->ima.inactive_table.num_targets;
420 md->ima.inactive_table.device_metadata = NULL;
421 md->ima.inactive_table.device_metadata_len = 0;
422 md->ima.inactive_table.num_targets = 0;
426 if (md->ima.active_table.device_metadata) {
427 memcpy(device_table_data + l, md->ima.active_table.device_metadata,
428 md->ima.active_table.device_metadata_len);
429 l += md->ima.active_table.device_metadata_len;
434 if (md->ima.active_table.hash) {
435 memcpy(device_table_data + l, active, active_len);
438 memcpy(device_table_data + l, md->ima.active_table.hash,
439 md->ima.active_table.hash_len);
440 l += md->ima.active_table.hash_len;
442 memcpy(device_table_data + l, ";", 1);
449 r = dm_ima_alloc_and_copy_name_uuid(md, &dev_name, &dev_uuid, noio);
453 scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN,
454 "%sname=%s,uuid=%s;device_resume=no_data;",
455 DM_IMA_VERSION_STR, dev_name, dev_uuid);
456 l += strlen(device_table_data);
460 capacity_len = strlen(capacity_str);
461 memcpy(device_table_data + l, capacity_str, capacity_len);
464 dm_ima_measure_data("dm_device_resume", device_table_data, l, noio);
470 kfree(device_table_data);
474 * Measure IMA data on remove.
476 void dm_ima_measure_on_device_remove(struct mapped_device *md, bool remove_all)
478 char *device_table_data, *dev_name = NULL, *dev_uuid = NULL, *capacity_str = NULL;
479 char active_table_str[] = "active_table_hash=";
480 char inactive_table_str[] = "inactive_table_hash=";
481 char device_active_str[] = "device_active_metadata=";
482 char device_inactive_str[] = "device_inactive_metadata=";
483 char remove_all_str[] = "remove_all=";
484 unsigned int active_table_len = strlen(active_table_str);
485 unsigned int inactive_table_len = strlen(inactive_table_str);
486 unsigned int device_active_len = strlen(device_active_str);
487 unsigned int device_inactive_len = strlen(device_inactive_str);
488 unsigned int remove_all_len = strlen(remove_all_str);
489 unsigned int capacity_len = 0;
495 device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN*2, GFP_KERNEL, noio);
496 if (!device_table_data)
499 r = dm_ima_alloc_and_copy_capacity_str(md, &capacity_str, noio);
501 kfree(device_table_data);
505 memcpy(device_table_data + l, DM_IMA_VERSION_STR, md->ima.dm_version_str_len);
506 l += md->ima.dm_version_str_len;
508 if (md->ima.active_table.device_metadata) {
509 memcpy(device_table_data + l, device_active_str, device_active_len);
510 l += device_active_len;
512 memcpy(device_table_data + l, md->ima.active_table.device_metadata,
513 md->ima.active_table.device_metadata_len);
514 l += md->ima.active_table.device_metadata_len;
519 if (md->ima.inactive_table.device_metadata) {
520 memcpy(device_table_data + l, device_inactive_str, device_inactive_len);
521 l += device_inactive_len;
523 memcpy(device_table_data + l, md->ima.inactive_table.device_metadata,
524 md->ima.inactive_table.device_metadata_len);
525 l += md->ima.inactive_table.device_metadata_len;
530 if (md->ima.active_table.hash) {
531 memcpy(device_table_data + l, active_table_str, active_table_len);
532 l += active_table_len;
534 memcpy(device_table_data + l, md->ima.active_table.hash,
535 md->ima.active_table.hash_len);
536 l += md->ima.active_table.hash_len;
538 memcpy(device_table_data + l, ",", 1);
544 if (md->ima.inactive_table.hash) {
545 memcpy(device_table_data + l, inactive_table_str, inactive_table_len);
546 l += inactive_table_len;
548 memcpy(device_table_data + l, md->ima.inactive_table.hash,
549 md->ima.inactive_table.hash_len);
550 l += md->ima.inactive_table.hash_len;
552 memcpy(device_table_data + l, ",", 1);
558 * In case both active and inactive tables, and corresponding
559 * device metadata is cleared/missing - record the name and uuid
560 * in IMA measurements.
563 if (dm_ima_alloc_and_copy_name_uuid(md, &dev_name, &dev_uuid, noio))
566 scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN,
567 "%sname=%s,uuid=%s;device_remove=no_data;",
568 DM_IMA_VERSION_STR, dev_name, dev_uuid);
569 l += strlen(device_table_data);
572 memcpy(device_table_data + l, remove_all_str, remove_all_len);
574 memcpy(device_table_data + l, remove_all ? "y;" : "n;", 2);
577 capacity_len = strlen(capacity_str);
578 memcpy(device_table_data + l, capacity_str, capacity_len);
581 dm_ima_measure_data("dm_device_remove", device_table_data, l, noio);
584 kfree(device_table_data);
587 kfree(md->ima.active_table.device_metadata);
589 if (md->ima.active_table.device_metadata !=
590 md->ima.inactive_table.device_metadata)
591 kfree(md->ima.inactive_table.device_metadata);
593 kfree(md->ima.active_table.hash);
595 if (md->ima.active_table.hash != md->ima.inactive_table.hash)
596 kfree(md->ima.inactive_table.hash);
598 dm_ima_reset_data(md);
605 * Measure ima data on table clear.
607 void dm_ima_measure_on_table_clear(struct mapped_device *md, bool new_map)
609 unsigned int l = 0, capacity_len = 0;
610 char *device_table_data = NULL, *dev_name = NULL, *dev_uuid = NULL, *capacity_str = NULL;
611 char inactive_str[] = "inactive_table_hash=";
612 unsigned int inactive_len = strlen(inactive_str);
617 device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN, GFP_KERNEL, noio);
618 if (!device_table_data)
621 r = dm_ima_alloc_and_copy_capacity_str(md, &capacity_str, noio);
625 memcpy(device_table_data + l, DM_IMA_VERSION_STR, md->ima.dm_version_str_len);
626 l += md->ima.dm_version_str_len;
628 if (md->ima.inactive_table.device_metadata_len &&
629 md->ima.inactive_table.hash_len) {
630 memcpy(device_table_data + l, md->ima.inactive_table.device_metadata,
631 md->ima.inactive_table.device_metadata_len);
632 l += md->ima.inactive_table.device_metadata_len;
634 memcpy(device_table_data + l, inactive_str, inactive_len);
637 memcpy(device_table_data + l, md->ima.inactive_table.hash,
638 md->ima.inactive_table.hash_len);
640 l += md->ima.inactive_table.hash_len;
642 memcpy(device_table_data + l, ";", 1);
649 if (dm_ima_alloc_and_copy_name_uuid(md, &dev_name, &dev_uuid, noio))
652 scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN,
653 "%sname=%s,uuid=%s;table_clear=no_data;",
654 DM_IMA_VERSION_STR, dev_name, dev_uuid);
655 l += strlen(device_table_data);
658 capacity_len = strlen(capacity_str);
659 memcpy(device_table_data + l, capacity_str, capacity_len);
662 dm_ima_measure_data("dm_table_clear", device_table_data, l, noio);
665 if (md->ima.inactive_table.hash &&
666 md->ima.inactive_table.hash != md->ima.active_table.hash)
667 kfree(md->ima.inactive_table.hash);
669 md->ima.inactive_table.hash = NULL;
670 md->ima.inactive_table.hash_len = 0;
672 if (md->ima.inactive_table.device_metadata &&
673 md->ima.inactive_table.device_metadata != md->ima.active_table.device_metadata)
674 kfree(md->ima.inactive_table.device_metadata);
676 md->ima.inactive_table.device_metadata = NULL;
677 md->ima.inactive_table.device_metadata_len = 0;
678 md->ima.inactive_table.num_targets = 0;
680 if (md->ima.active_table.hash) {
681 md->ima.inactive_table.hash = md->ima.active_table.hash;
682 md->ima.inactive_table.hash_len = md->ima.active_table.hash_len;
685 if (md->ima.active_table.device_metadata) {
686 md->ima.inactive_table.device_metadata =
687 md->ima.active_table.device_metadata;
688 md->ima.inactive_table.device_metadata_len =
689 md->ima.active_table.device_metadata_len;
690 md->ima.inactive_table.num_targets =
691 md->ima.active_table.num_targets;
700 kfree(device_table_data);
704 * Measure IMA data on device rename.
706 void dm_ima_measure_on_device_rename(struct mapped_device *md)
708 char *old_device_data = NULL, *new_device_data = NULL, *combined_device_data = NULL;
709 char *new_dev_name = NULL, *new_dev_uuid = NULL, *capacity_str = NULL;
713 if (dm_ima_alloc_and_copy_device_data(md, &new_device_data,
714 md->ima.active_table.num_targets, noio))
717 if (dm_ima_alloc_and_copy_name_uuid(md, &new_dev_name, &new_dev_uuid, noio))
720 combined_device_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN * 2, GFP_KERNEL, noio);
721 if (!combined_device_data)
724 r = dm_ima_alloc_and_copy_capacity_str(md, &capacity_str, noio);
728 old_device_data = md->ima.active_table.device_metadata;
730 md->ima.active_table.device_metadata = new_device_data;
731 md->ima.active_table.device_metadata_len = strlen(new_device_data);
733 scnprintf(combined_device_data, DM_IMA_DEVICE_BUF_LEN * 2,
734 "%s%snew_name=%s,new_uuid=%s;%s", DM_IMA_VERSION_STR, old_device_data,
735 new_dev_name, new_dev_uuid, capacity_str);
737 dm_ima_measure_data("dm_device_rename", combined_device_data, strlen(combined_device_data),
743 kfree(new_device_data);
746 kfree(combined_device_data);
747 kfree(old_device_data);