1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2021 Microsoft Corporation 4 * 5 * Author: Tushar Sugandhi <tusharsu@linux.microsoft.com> 6 * 7 * Enables IMA measurements for DM targets 8 */ 9 10 #include "dm-core.h" 11 #include "dm-ima.h" 12 13 #include <linux/ima.h> 14 #include <linux/sched/mm.h> 15 #include <crypto/sha2.h> 16 17 #define DM_MSG_PREFIX "ima" 18 19 /* 20 * Internal function to prefix separator characters in input buffer with escape 21 * character, so that they don't interfere with the construction of key-value pairs, 22 * and clients can split the key1=val1,key2=val2,key3=val3; pairs properly. 23 */ 24 static void fix_separator_chars(char *buf) 25 { 26 int l = strlen(buf); 27 int i, j, sp = 0; 28 29 for (i = 0; i < l; i++) 30 if (buf[i] == '\\' || buf[i] == ';' || buf[i] == '=' || buf[i] == ',') 31 sp++; 32 33 if (!sp) 34 return; 35 36 buf[l + sp] = '\0'; 37 for (i = l-1, j = i+sp; i >= 0; i--) { 38 buf[j--] = buf[i]; 39 if (buf[i] == '\\' || buf[i] == ';' || buf[i] == '=' || buf[i] == ',') 40 buf[j--] = '\\'; 41 } 42 } 43 44 static void fix_context_strings(struct dm_ima_context *context) 45 { 46 fix_separator_chars(context->dev_name); 47 fix_separator_chars(context->dev_uuid); 48 } 49 50 /* 51 * Internal function to allocate memory for IMA measurements. 52 */ 53 static void *dm_ima_alloc(size_t len, bool noio) 54 { 55 unsigned int noio_flag; 56 void *ptr; 57 58 if (noio) 59 noio_flag = memalloc_noio_save(); 60 61 ptr = kzalloc(len, GFP_KERNEL); 62 63 if (noio) 64 memalloc_noio_restore(noio_flag); 65 66 return ptr; 67 } 68 69 void dm_ima_init(struct mapped_device *md) 70 { 71 md->ima.update_idx = 0; 72 md->ima.measure_idx = 0; 73 init_waitqueue_head(&md->ima.ima_wq); 74 spin_lock_init(&md->ima.ima_lock); 75 } 76 77 void dm_ima_alloc_context(struct dm_ima_context **context, bool noio) 78 { 79 *context = dm_ima_alloc(sizeof(struct dm_ima_context), noio); 80 } 81 82 void dm_ima_free_context(struct dm_ima_context *context) 83 { 84 if (likely(context)) { 85 kfree(context->table.device_metadata); 86 kfree(context->table.hash); 87 kfree(context); 88 } 89 } 90 91 static void wait_to_measure(struct dm_ima_measurements *ima, 92 unsigned int update_idx) 93 { 94 spin_lock_irq(&ima->ima_lock); 95 wait_event_lock_irq(ima->ima_wq, 96 ima->measure_idx == update_idx, 97 ima->ima_lock); 98 spin_unlock_irq(&ima->ima_lock); 99 } 100 101 static void wake_next_measure(struct dm_ima_measurements *ima) 102 { 103 spin_lock_irq(&ima->ima_lock); 104 ima->measure_idx++; 105 spin_unlock_irq(&ima->ima_lock); 106 wake_up_all(&ima->ima_wq); 107 } 108 109 /* 110 * Helper function for swapping the table, to make sure that the 111 * correct table metadata is saved and restored. 112 */ 113 void dm_ima_context_table_op(struct mapped_device *md, 114 struct dm_ima_context *context, 115 enum dm_ima_table_op op) 116 { 117 struct dm_ima_measurements *ima = &md->ima; 118 119 if (unlikely(!context)) 120 return; 121 122 wait_to_measure(ima, context->update_idx); 123 124 if (op == DM_IMA_TABLE_SAVE) { 125 context->table = ima->inactive_table; 126 memset(&ima->inactive_table, 0, sizeof(ima->inactive_table)); 127 } else { 128 ima->inactive_table = context->table; 129 memset(&context->table, 0, sizeof(context->table)); 130 } 131 132 wake_next_measure(ima); 133 } 134 135 /* 136 * Internal function to copy device data for IMA measurements. 137 */ 138 static void dm_ima_copy_device_data(struct mapped_device *md, char *device_data, 139 struct dm_ima_context *context, 140 unsigned int num_targets) 141 { 142 memset(device_data, 0, DM_IMA_DEVICE_BUF_LEN); 143 scnprintf(device_data, DM_IMA_DEVICE_BUF_LEN, 144 "name=%s,uuid=%s,major=%d,minor=%d,minor_count=%d,num_targets=%u;", 145 context->dev_name, context->dev_uuid, md->disk->major, 146 md->disk->first_minor, md->disk->minors, num_targets); 147 148 } 149 150 /* 151 * Internal wrapper function to call IMA to measure DM data. 152 */ 153 static void dm_ima_measure_data(const char *event_name, const void *buf, size_t buf_len, 154 bool noio) 155 { 156 unsigned int noio_flag; 157 158 if (noio) 159 noio_flag = memalloc_noio_save(); 160 161 ima_measure_critical_data(DM_NAME, event_name, buf, buf_len, 162 false, NULL, 0); 163 164 if (noio) 165 memalloc_noio_restore(noio_flag); 166 } 167 168 static sector_t dm_ima_capacity(struct mapped_device *md) 169 { 170 return (md->ima.active_table.device_metadata) ? 171 md->ima.active_table.capacity : get_capacity(md->disk); 172 } 173 174 /* 175 * Build up the IMA data for each target, and finally measure. 176 */ 177 void dm_ima_measure_on_table_load(struct dm_table *table, 178 struct dm_ima_context *context) 179 { 180 size_t device_data_buf_len, target_metadata_buf_len, target_data_buf_len, l = 0; 181 char *target_metadata_buf = NULL, *target_data_buf = NULL, *digest_buf = NULL; 182 char *ima_buf = NULL, *device_data_buf = NULL; 183 status_type_t type = STATUSTYPE_IMA; 184 size_t cur_total_buf_len = 0; 185 unsigned int num_targets, i; 186 struct sha256_ctx hash_ctx; 187 u8 digest[SHA256_DIGEST_SIZE]; 188 bool noio = false; 189 char table_load_event_name[] = "dm_table_load"; 190 191 if (unlikely(!context)) 192 return; 193 194 wait_to_measure(&table->md->ima, context->update_idx); 195 196 ima_buf = dm_ima_alloc(DM_IMA_MEASUREMENT_BUF_LEN, noio); 197 if (!ima_buf) 198 goto error; 199 200 target_metadata_buf = dm_ima_alloc(DM_IMA_TARGET_METADATA_BUF_LEN, noio); 201 if (!target_metadata_buf) 202 goto error; 203 204 target_data_buf = dm_ima_alloc(DM_IMA_TARGET_DATA_BUF_LEN, noio); 205 if (!target_data_buf) 206 goto error; 207 208 num_targets = table->num_targets; 209 210 device_data_buf = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN, noio); 211 if (!device_data_buf) 212 goto error; 213 214 fix_context_strings(context); 215 dm_ima_copy_device_data(table->md, device_data_buf, context, 216 num_targets); 217 218 sha256_init(&hash_ctx); 219 220 memcpy(ima_buf + l, DM_IMA_VERSION_STR, strlen(DM_IMA_VERSION_STR)); 221 l += strlen(DM_IMA_VERSION_STR); 222 223 device_data_buf_len = strlen(device_data_buf); 224 memcpy(ima_buf + l, device_data_buf, device_data_buf_len); 225 l += device_data_buf_len; 226 227 for (i = 0; i < num_targets; i++) { 228 struct dm_target *ti = dm_table_get_target(table, i); 229 230 /* 231 * First retrieve the target metadata. 232 */ 233 target_metadata_buf_len = 234 scnprintf(target_metadata_buf, 235 DM_IMA_TARGET_METADATA_BUF_LEN, 236 "target_index=%d,target_begin=%llu,target_len=%llu,", 237 i, ti->begin, ti->len); 238 239 /* 240 * Then retrieve the actual target data. 241 */ 242 if (ti->type->status) 243 ti->type->status(ti, type, 0, target_data_buf, 244 DM_IMA_TARGET_DATA_BUF_LEN); 245 else 246 target_data_buf[0] = '\0'; 247 248 target_data_buf_len = strlen(target_data_buf); 249 250 /* 251 * Check if the total data can fit into the IMA buffer. 252 */ 253 cur_total_buf_len = l + target_metadata_buf_len + target_data_buf_len; 254 255 /* 256 * IMA measurements for DM targets are best-effort. 257 * If the total data buffered so far, including the current target, 258 * is too large to fit into DM_IMA_MEASUREMENT_BUF_LEN, measure what 259 * we have in the current buffer, and continue measuring the remaining 260 * targets by prefixing the device metadata again. 261 */ 262 if (unlikely(cur_total_buf_len >= DM_IMA_MEASUREMENT_BUF_LEN)) { 263 dm_ima_measure_data(table_load_event_name, ima_buf, l, noio); 264 sha256_update(&hash_ctx, (const u8 *)ima_buf, l); 265 266 memset(ima_buf, 0, DM_IMA_MEASUREMENT_BUF_LEN); 267 l = 0; 268 269 /* 270 * Each new "dm_table_load" entry in IMA log should have device data 271 * prefix, so that multiple records from the same "dm_table_load" for 272 * a given device can be linked together. 273 */ 274 memcpy(ima_buf + l, DM_IMA_VERSION_STR, strlen(DM_IMA_VERSION_STR)); 275 l += strlen(DM_IMA_VERSION_STR); 276 277 memcpy(ima_buf + l, device_data_buf, device_data_buf_len); 278 l += device_data_buf_len; 279 } 280 281 /* 282 * Fill-in all the target metadata, so that multiple targets for the same 283 * device can be linked together. 284 */ 285 memcpy(ima_buf + l, target_metadata_buf, target_metadata_buf_len); 286 l += target_metadata_buf_len; 287 288 memcpy(ima_buf + l, target_data_buf, target_data_buf_len); 289 l += target_data_buf_len; 290 } 291 292 dm_ima_measure_data(table_load_event_name, ima_buf, l, noio); 293 sha256_update(&hash_ctx, (const u8 *)ima_buf, l); 294 295 /* 296 * Finalize the table hash, and store it in table->md->ima.inactive_table.hash, 297 * so that the table data can be verified against the future device state change 298 * events, e.g. resume, rename, remove, table-clear etc. 299 */ 300 sha256_final(&hash_ctx, digest); 301 302 digest_buf = kasprintf(GFP_KERNEL, "sha256:%*phN", SHA256_DIGEST_SIZE, 303 digest); 304 if (!digest_buf) 305 goto error; 306 307 kfree(table->md->ima.inactive_table.hash); 308 table->md->ima.inactive_table.hash = digest_buf; 309 table->md->ima.inactive_table.hash_len = strlen(digest_buf); 310 table->md->ima.inactive_table.num_targets = num_targets; 311 table->md->ima.inactive_table.capacity = dm_table_get_size(table); 312 313 314 kfree(table->md->ima.inactive_table.device_metadata); 315 table->md->ima.inactive_table.device_metadata = device_data_buf; 316 table->md->ima.inactive_table.device_metadata_len = device_data_buf_len; 317 318 goto exit; 319 error: 320 kfree(digest_buf); 321 kfree(device_data_buf); 322 exit: 323 kfree(ima_buf); 324 kfree(target_metadata_buf); 325 kfree(target_data_buf); 326 327 wake_next_measure(&table->md->ima); 328 } 329 330 /* 331 * Measure IMA data on device resume. 332 */ 333 void dm_ima_measure_on_device_resume(struct mapped_device *md, bool swap, 334 struct dm_ima_context *context) 335 { 336 char *device_table_data = NULL; 337 char active[] = "active_table_hash="; 338 unsigned int active_len = strlen(active); 339 unsigned int l = 0; 340 bool noio = true; 341 bool nodata = true; 342 343 if (unlikely(!context)) 344 return; 345 346 wait_to_measure(&md->ima, context->update_idx); 347 348 if (swap) { 349 kfree(md->ima.active_table.hash); 350 kfree(md->ima.active_table.device_metadata); 351 md->ima.active_table = context->table; 352 memset(&context->table, 0, sizeof(context->table)); 353 if (md->ima.active_table.device_metadata) { 354 /* 355 * A rename could have happened while the swap was 356 * going on. In that case, the saved table info would 357 * still have the old name. Update the metadata to be 358 * sure that it has the current name 359 */ 360 struct dm_ima_device_table_metadata *table = &md->ima.active_table; 361 fix_context_strings(context); 362 dm_ima_copy_device_data(md, table->device_metadata, 363 context, table->num_targets); 364 table->device_metadata_len = strlen(table->device_metadata); 365 } 366 } 367 368 device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN, noio); 369 if (!device_table_data) 370 goto error; 371 372 memcpy(device_table_data + l, DM_IMA_VERSION_STR, strlen(DM_IMA_VERSION_STR)); 373 l += strlen(DM_IMA_VERSION_STR); 374 375 if (md->ima.active_table.device_metadata) { 376 memcpy(device_table_data + l, md->ima.active_table.device_metadata, 377 md->ima.active_table.device_metadata_len); 378 l += md->ima.active_table.device_metadata_len; 379 380 nodata = false; 381 } 382 383 if (md->ima.active_table.hash) { 384 memcpy(device_table_data + l, active, active_len); 385 l += active_len; 386 387 memcpy(device_table_data + l, md->ima.active_table.hash, 388 md->ima.active_table.hash_len); 389 l += md->ima.active_table.hash_len; 390 391 memcpy(device_table_data + l, ";", 1); 392 l++; 393 394 nodata = false; 395 } 396 397 if (nodata) { 398 fix_context_strings(context); 399 l = scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN, 400 "%sname=%s,uuid=%s;device_resume=no_data;", 401 DM_IMA_VERSION_STR, context->dev_name, 402 context->dev_uuid); 403 } 404 l += scnprintf(device_table_data + l, DM_IMA_DEVICE_BUF_LEN - l, 405 "current_device_capacity=%llu;", dm_ima_capacity(md)); 406 407 dm_ima_measure_data("dm_device_resume", device_table_data, l, noio); 408 409 error: 410 kfree(device_table_data); 411 412 wake_next_measure(&md->ima); 413 } 414 415 /* 416 * Measure IMA data on remove. 417 */ 418 void dm_ima_measure_on_device_remove(struct mapped_device *md, bool remove_all, 419 struct dm_ima_context *context, 420 unsigned int idx) 421 { 422 char *device_table_data; 423 char active_table_str[] = "active_table_hash="; 424 char inactive_table_str[] = "inactive_table_hash="; 425 char device_active_str[] = "device_active_metadata="; 426 char device_inactive_str[] = "device_inactive_metadata="; 427 unsigned int active_table_len = strlen(active_table_str); 428 unsigned int inactive_table_len = strlen(inactive_table_str); 429 unsigned int device_active_len = strlen(device_active_str); 430 unsigned int device_inactive_len = strlen(device_inactive_str); 431 unsigned int l = 0; 432 bool noio = true; 433 bool nodata = true; 434 435 wait_to_measure(&md->ima, idx); 436 437 if (unlikely(!context)) 438 goto exit; 439 440 device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN*2, noio); 441 if (!device_table_data) 442 goto exit; 443 444 memcpy(device_table_data + l, DM_IMA_VERSION_STR, strlen(DM_IMA_VERSION_STR)); 445 l += strlen(DM_IMA_VERSION_STR); 446 447 if (md->ima.active_table.device_metadata) { 448 memcpy(device_table_data + l, device_active_str, device_active_len); 449 l += device_active_len; 450 451 memcpy(device_table_data + l, md->ima.active_table.device_metadata, 452 md->ima.active_table.device_metadata_len); 453 l += md->ima.active_table.device_metadata_len; 454 455 nodata = false; 456 } 457 458 if (md->ima.inactive_table.device_metadata) { 459 memcpy(device_table_data + l, device_inactive_str, device_inactive_len); 460 l += device_inactive_len; 461 462 memcpy(device_table_data + l, md->ima.inactive_table.device_metadata, 463 md->ima.inactive_table.device_metadata_len); 464 l += md->ima.inactive_table.device_metadata_len; 465 466 nodata = false; 467 } 468 469 if (md->ima.active_table.hash) { 470 memcpy(device_table_data + l, active_table_str, active_table_len); 471 l += active_table_len; 472 473 memcpy(device_table_data + l, md->ima.active_table.hash, 474 md->ima.active_table.hash_len); 475 l += md->ima.active_table.hash_len; 476 477 memcpy(device_table_data + l, ",", 1); 478 l++; 479 480 nodata = false; 481 } 482 483 if (md->ima.inactive_table.hash) { 484 memcpy(device_table_data + l, inactive_table_str, inactive_table_len); 485 l += inactive_table_len; 486 487 memcpy(device_table_data + l, md->ima.inactive_table.hash, 488 md->ima.inactive_table.hash_len); 489 l += md->ima.inactive_table.hash_len; 490 491 memcpy(device_table_data + l, ",", 1); 492 l++; 493 494 nodata = false; 495 } 496 /* 497 * In case both active and inactive tables, and corresponding 498 * device metadata is cleared/missing - record the name and uuid 499 * in IMA measurements. 500 */ 501 if (nodata) { 502 fix_context_strings(context); 503 l = scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN, 504 "%sname=%s,uuid=%s;device_remove=no_data;", 505 DM_IMA_VERSION_STR, context->dev_name, 506 context->dev_uuid); 507 } 508 509 l += scnprintf(device_table_data + l, (DM_IMA_DEVICE_BUF_LEN * 2) - l, 510 "remove_all=%c;current_device_capacity=%llu;", 511 remove_all ? 'y' : 'n', dm_ima_capacity(md)); 512 513 dm_ima_measure_data("dm_device_remove", device_table_data, l, noio); 514 515 kfree(device_table_data); 516 exit: 517 kfree(md->ima.active_table.device_metadata); 518 kfree(md->ima.inactive_table.device_metadata); 519 520 kfree(md->ima.active_table.hash); 521 kfree(md->ima.inactive_table.hash); 522 523 memset(&md->ima.active_table, 0, sizeof(md->ima.active_table)); 524 memset(&md->ima.inactive_table, 0, sizeof(md->ima.inactive_table)); 525 526 wake_next_measure(&md->ima); 527 } 528 529 /* 530 * Measure ima data on table clear. 531 */ 532 void dm_ima_measure_on_table_clear(struct mapped_device *md, 533 struct dm_ima_context *context) 534 { 535 unsigned int l = 0; 536 char *device_table_data = NULL; 537 char inactive_str[] = "inactive_table_hash="; 538 unsigned int inactive_len = strlen(inactive_str); 539 bool noio = true; 540 bool nodata = true; 541 542 if (unlikely(!context)) 543 return; 544 545 wait_to_measure(&md->ima, context->update_idx); 546 547 device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN, noio); 548 if (!device_table_data) 549 goto error; 550 551 memcpy(device_table_data + l, DM_IMA_VERSION_STR, strlen(DM_IMA_VERSION_STR)); 552 l += strlen(DM_IMA_VERSION_STR); 553 554 if (md->ima.inactive_table.device_metadata_len && 555 md->ima.inactive_table.hash_len) { 556 memcpy(device_table_data + l, md->ima.inactive_table.device_metadata, 557 md->ima.inactive_table.device_metadata_len); 558 l += md->ima.inactive_table.device_metadata_len; 559 560 memcpy(device_table_data + l, inactive_str, inactive_len); 561 l += inactive_len; 562 563 memcpy(device_table_data + l, md->ima.inactive_table.hash, 564 md->ima.inactive_table.hash_len); 565 566 l += md->ima.inactive_table.hash_len; 567 568 memcpy(device_table_data + l, ";", 1); 569 l++; 570 571 nodata = false; 572 } 573 574 if (nodata) { 575 fix_context_strings(context); 576 l = scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN, 577 "%sname=%s,uuid=%s;table_clear=no_data;", 578 DM_IMA_VERSION_STR, context->dev_name, 579 context->dev_uuid); 580 } 581 582 l += scnprintf(device_table_data + l, DM_IMA_DEVICE_BUF_LEN - l, 583 "current_device_capacity=%llu;", dm_ima_capacity(md)); 584 585 dm_ima_measure_data("dm_table_clear", device_table_data, l, noio); 586 587 error: 588 kfree(md->ima.inactive_table.hash); 589 kfree(md->ima.inactive_table.device_metadata); 590 memset(&md->ima.inactive_table, 0, sizeof(md->ima.inactive_table)); 591 592 kfree(device_table_data); 593 594 wake_next_measure(&md->ima); 595 } 596 597 /* 598 * Measure IMA data on device rename. 599 */ 600 void dm_ima_measure_on_device_rename(struct mapped_device *md, 601 struct dm_ima_context *context) 602 { 603 char *old_device_data = NULL; 604 char *combined_device_data = NULL; 605 bool noio = true; 606 int len; 607 struct dm_ima_device_table_metadata *table; 608 609 if (unlikely(!context)) 610 return; 611 612 wait_to_measure(&md->ima, context->update_idx); 613 614 fix_context_strings(context); 615 616 combined_device_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN * 2, noio); 617 if (!combined_device_data) 618 goto exit; 619 620 if (md->ima.active_table.device_metadata) 621 old_device_data = md->ima.active_table.device_metadata; 622 else if (md->ima.inactive_table.device_metadata) 623 old_device_data = md->ima.inactive_table.device_metadata; 624 else 625 old_device_data = "device_rename=no_data;"; 626 len = scnprintf(combined_device_data, DM_IMA_DEVICE_BUF_LEN * 2, 627 "%s%snew_name=%s,new_uuid=%s;current_device_capacity=%llu;", 628 DM_IMA_VERSION_STR, old_device_data, context->dev_name, 629 context->dev_uuid, dm_ima_capacity(md)); 630 631 dm_ima_measure_data("dm_device_rename", combined_device_data, len, noio); 632 kfree(combined_device_data); 633 634 exit: 635 if (md->ima.active_table.device_metadata) { 636 table = &md->ima.active_table; 637 dm_ima_copy_device_data(md, table->device_metadata, context, 638 table->num_targets); 639 table->device_metadata_len = strlen(table->device_metadata); 640 } 641 642 if (md->ima.inactive_table.device_metadata) { 643 table = &md->ima.inactive_table; 644 dm_ima_copy_device_data(md, table->device_metadata, context, 645 table->num_targets); 646 table->device_metadata_len = strlen(table->device_metadata); 647 } 648 649 wake_next_measure(&md->ima); 650 } 651