Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: drivers/md/dm-verity.c

Issue 3026039: [RFC] CHROMIUM: Two patches for comments: EFI GUID boot for dm-verity (Closed) Base URL: http://src.chromium.org/git/kernel.git
Patch Set: fix desc. dont always wait Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | fs/partitions/efi.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Originally based on dm-crypt.c, 2 * Originally based on dm-crypt.c,
3 * Copyright (C) 2003 Christophe Saout <christophe@saout.de> 3 * Copyright (C) 2003 Christophe Saout <christophe@saout.de>
4 * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org> 4 * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
5 * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. 5 * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
6 * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org> 6 * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org>
7 * All Rights Reserved. 7 * All Rights Reserved.
8 * 8 *
9 * This file is released under the GPL. 9 * This file is released under the GPL.
10 * 10 *
11 * Implements a verifying transparent block device. 11 * Implements a verifying transparent block device.
12 * See Documentation/device-mapper/dm-verity.txt 12 * See Documentation/device-mapper/dm-verity.txt
13 */ 13 */
14 #include <linux/async.h>
14 #include <linux/backing-dev.h> 15 #include <linux/backing-dev.h>
15 #include <linux/bio.h> 16 #include <linux/bio.h>
16 #include <linux/blkdev.h> 17 #include <linux/blkdev.h>
17 #include <linux/completion.h> 18 #include <linux/completion.h>
18 #include <linux/crypto.h> 19 #include <linux/crypto.h>
19 #include <linux/delay.h> 20 #include <linux/delay.h>
21 #include <linux/device.h>
22 #ifdef CONFIG_EFI_PARTITION
23 # include <linux/efi.h>
24 #endif
20 #include <linux/err.h> 25 #include <linux/err.h>
26 #include <linux/genhd.h>
21 #include <linux/init.h> 27 #include <linux/init.h>
22 #include <linux/kernel.h> 28 #include <linux/kernel.h>
23 #include <linux/mempool.h> 29 #include <linux/mempool.h>
24 #include <linux/module.h> 30 #include <linux/module.h>
25 #include <linux/slab.h> 31 #include <linux/slab.h>
26 #include <linux/workqueue.h> 32 #include <linux/workqueue.h>
27 #include <linux/reboot.h> 33 #include <linux/reboot.h>
28 #include <asm/atomic.h> 34 #include <asm/atomic.h>
29 #include <linux/scatterlist.h> 35 #include <linux/scatterlist.h>
30 #include <asm/page.h> 36 #include <asm/page.h>
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 static int error_behavior = DM_VERITY_EIO; 120 static int error_behavior = DM_VERITY_EIO;
115 module_param(error_behavior, int, 0444); 121 module_param(error_behavior, int, 0444);
116 MODULE_PARM_DESC(error_behavior, "Behavior on error"); 122 MODULE_PARM_DESC(error_behavior, "Behavior on error");
117 123
118 124
119 /* Control whether the reads are optimized for sequential access by pre-reading 125 /* Control whether the reads are optimized for sequential access by pre-reading
120 * entries in the bht. 126 * entries in the bht.
121 */ 127 */
122 static int bht_readahead; 128 static int bht_readahead;
123 module_param(bht_readahead, int, 0644); 129 module_param(bht_readahead, int, 0644);
124 MODULE_PARM_DESC(bht_readahead, "number of entries to readahead in the bht"); 130 MODULE_PARM_DESC(bht_readahead, "Number of entries to readahead in the bht");
131
132 /* Controls whether verity_get_device will wait forever for a device. */
133 static int dev_wait;
134 module_param(dev_wait, bool, 0444);
135 MODULE_PARM_DESC(dev_wait, "Wait forever for a backing device")
125 136
126 /* Used for tracking pending bios as well as for exporting information via 137 /* Used for tracking pending bios as well as for exporting information via
127 * STATUSTYPE_INFO. 138 * STATUSTYPE_INFO.
128 */ 139 */
129 struct verity_stats { 140 struct verity_stats {
130 unsigned int pending_bio; 141 unsigned int pending_bio;
131 unsigned int io_queue; 142 unsigned int io_queue;
132 unsigned int verify_queue; 143 unsigned int verify_queue;
133 unsigned int average_requeues; 144 unsigned int average_requeues;
134 unsigned int total_requeues; 145 unsigned int total_requeues;
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 /* IO errors have to be propagated. */ 545 /* IO errors have to be propagated. */
535 if (error != -EIO && io) 546 if (error != -EIO && io)
536 io->error = 0; 547 io->error = 0;
537 } 548 }
538 return; 549 return;
539 default: 550 default:
540 break; 551 break;
541 } 552 }
542 } 553 }
543 554
555 /**
556 * efi_parse_hexbyte - Convert a ASCII hex number to a byte
557 * @src: Pointer to at least 2 characters to convert.
558 *
559 * Convert a two character ASCII hex string to a number.
560 * From ldm.c.
561 *
562 * Return: 0-255 Success, the byte was parsed correctly
563 * -1 Error, an invalid character was supplied
564 */
565 static int efi_hexbyte (const u8 *src)
566 {
567 unsigned int x; /* For correct wrapping */
568 int h;
569
570 /* high part */
571 if ((x = src[0] - '0') <= '9'-'0') h = x;
572 else if ((x = src[0] - 'a') <= 'f'-'a') h = x+10;
573 else if ((x = src[0] - 'A') <= 'F'-'A') h = x+10;
574 else return -1;
575 h <<= 4;
576
577 /* low part */
578 if ((x = src[1] - '0') <= '9'-'0') return h | x;
579 if ((x = src[1] - 'a') <= 'f'-'a') return h | (x+10);
580 if ((x = src[1] - 'A') <= 'F'-'A') return h | (x+10);
581 return -1;
582 }
583
584 /**
585 * efi_parse_guid - Convert GUID from ASCII to binary
586 * @src: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
587 * @dest: Memory block to hold binary GUID (16 bytes)
588 *
589 * N.B. The GUID need not be NULL terminated and no safety checks are performed.
590 *
591 * Return: 'true' @dest contains binary GUID
592 * 'false' @dest contents are undefined
593 */
594 static bool efi_parse_guid(const u8 *src, u8 *dest)
595 {
596 dest[3] = efi_hexbyte(src); src += 2;
597 dest[2] = efi_hexbyte(src); src += 2;
598 dest[1] = efi_hexbyte(src); src += 2;
599 dest[0] = efi_hexbyte(src); src += 2;
600 src += 1; /* - */
601 dest[5] = efi_hexbyte(src); src += 2;
602 dest[4] = efi_hexbyte(src); src += 2;
603 src += 1; /* - */
604 dest[7] = efi_hexbyte(src); src += 2;
605 dest[6] = efi_hexbyte(src); src += 2;
606 src += 1; /* - */
607 dest[8] = efi_hexbyte(src); src += 2;
608 dest[9] = efi_hexbyte(src); src += 2;
609 src += 1; /* - */
610 dest[10] = efi_hexbyte(src); src += 2;
611 dest[11] = efi_hexbyte(src); src += 2;
612 dest[12] = efi_hexbyte(src); src += 2;
613 dest[13] = efi_hexbyte(src); src += 2;
614 dest[14] = efi_hexbyte(src); src += 2;
615 dest[15] = efi_hexbyte(src); src += 2;
616 return true;
617 }
618
619 /**
620 * dm_get_efi_device: claim a device using its unique GUID
621 * @ti: current dm_target
622 * @guid_string: 36 byte GUID
623 * (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
624 * @dev_start: offset in sectors passed to dm_get_device
625 * @dev_len: length in sectors passed to dm_get_device
626 * @dm_dev: dm_dev to populate
627 *
628 * Wraps dm_get_device allowing it to use a unique partition GUID to
629 * find a given partition on any drive. This code is based on
630 * printk_all_partitions in that it walks all of the register block devices.
631 *
632 * N.B., guid_string is not checked for safety.
633 */
634 static int dm_get_efi_device(struct dm_target *ti,
635 const char *guid_string,
636 sector_t dev_start,
637 sector_t dev_len,
638 struct dm_dev **dm_dev)
639 {
640 #ifdef CONFIG_EFI_PARTITION
641 int part = 0;
642 efi_guid_t guid;
643 struct class_dev_iter iter;
644 struct device *dev;
645 dev_t devt = 0;
646 char devt_buf[BDEVT_SIZE];
647
648 DMDEBUG("dm_get_efi_device called");
649 if (!efi_parse_guid(guid_string, guid.b))
650 goto bad_guid;
651 DMDEBUG("GUID parsed");
652
653 /* Walks the block_class. Since we can't access gendisk's
654 * device_type, we just filter out entries with no devnode below.
655 */
656 class_dev_iter_init(&iter, &block_class, NULL, NULL);
657 while ((dev = class_dev_iter_next(&iter))) {
658 struct gendisk *disk = dev_to_disk(dev);
659 struct block_device *bdev = NULL;
660
661 DMDEBUG("Walking %u:%u", MAJOR(dev->devt), MINOR(dev->devt));
662
663 /*
664 * Don't show empty devices or things that have been
665 * surpressed
666 */
667 if (!disk || get_capacity(disk) == 0 ||
668 (disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
669 continue;
670
671 if (!disk->part_tbl) {
672 DMDEBUG("No partition table for %u:%u",
673 MAJOR(disk_devt(disk)),
674 MINOR(disk_devt(disk)));
675 continue;
676 }
677
678 /* We're walking all disk and partitions so just grab disks. */
679 bdev = bdget_disk(disk, 0);
680 if (!bdev) {
681 DMDEBUG("No bdev for %u:%u. Skipping",
682 MAJOR(dev->devt), MINOR(dev->devt));
683 continue;
684 }
685
686 /* Ensure we have a bd_disk. If nothing else has it opened,
687 * there's no guarantee it'll be populated.
688 */
689 int err = blkdev_get(bdev, FMODE_READ);
690 if (err < 0) {
691 DMDEBUG("Failed to blkdev_get: %d", err);
692 bdput(bdev);
693 continue;
694 }
695
696 DMDEBUG("find_efi_partition called for disk: %u:%u",
697 MAJOR(dev->devt), MINOR(dev->devt));
698 part = efi_find_partition(&guid, bdev);
699 /* Nb, it seems that calling bdput after blkdev_put
700 * isn't common. If the inode was only in use here,
701 * then it will end up I_CLEAR'd when bdput gets to it.
702 */
703 blkdev_put(bdev, FMODE_READ);
704 /* On match, create the dev node if possible.*/
705 if (part > 0) {
706 devt = MKDEV(MAJOR(dev->devt),
707 MINOR(dev->devt) + part);
708 DMDEBUG("found a part! (%d %u:%u)", part,
709 MAJOR(devt), MINOR(devt));
710 break;
711 }
712 }
713 class_dev_iter_exit(&iter);
714
715 if (part <= 0)
716 goto found_nothing;
717
718 /* Construct the dev name to pass to dm_get_device. This is roundabout
719 * EFI partition scanning isn't exactly fast so it doesn't seem like a
720 * bad tradeoff.
721 */
722 snprintf(devt_buf, sizeof(devt_buf), "%u:%u", MAJOR(devt), MINOR(devt));
723
724 /* TODO(wad) to make this generic we could also pass in the mode. */
725 if (dm_get_device(ti, devt_buf, dev_start, dev_len,
726 dm_table_get_mode(ti->table), dm_dev) == 0)
727 return 0;
728
729 ti->error = "Failed to acquire device";
730 DMDEBUG("Failed to acquire discovered device %s", devt_buf);
731 return -1;
732 bad_guid:
733 ti->error = "Bad GUID";
734 DMDEBUG("Supplied value '%s' is an invalid GUID", guid_string);
735 return -1;
736 found_nothing:
737 DMDEBUG("No matching partition for GUID: %s", guid_string);
738 ti->error = "No matching GUID";
739 #endif
740 return -1;
741 }
742
743 static int verity_get_device(struct dm_target *ti, const char *devname,
744 sector_t dev_start, sector_t dev_len,
745 struct dm_dev **dm_dev)
746 {
747 do {
748 /* Try the normal path first since if everything is ready, it
749 * will be the fastest.
750 */
751 if (!dm_get_device(ti, devname, dev_start, dev_len,
752 dm_table_get_mode(ti->table), dm_dev))
753 return 0;
754
755 /* Try the device by EFI GUID */
756 if (!dm_get_efi_device(ti, devname, dev_start, dev_len, dm_dev))
757 return 0;
758
759 /* No need to be too aggressive since this is a slow path. */
760 msleep(500);
761 } while (dev_wait && (driver_probe_done() != 0 || *dm_dev == NULL));
762 async_synchronize_full();
763 return -1;
764 }
765
766
544 /*----------------------------------------------------------------- 767 /*-----------------------------------------------------------------
545 * Reverse flow of requests into the device. 768 * Reverse flow of requests into the device.
546 * 769 *
547 * (Start at the bottom with verity_map and work your way upward). 770 * (Start at the bottom with verity_map and work your way upward).
548 *-----------------------------------------------------------------*/ 771 *-----------------------------------------------------------------*/
549 772
550 static void verity_inc_pending(struct dm_verity_io *io); 773 static void verity_inc_pending(struct dm_verity_io *io);
551 774
552 /* verity_dec_pending manages the lifetime of all dm_verity_io structs. 775 /* verity_dec_pending manages the lifetime of all dm_verity_io structs.
553 * Non-bug error handling is centralized through this interface and 776 * Non-bug error handling is centralized through this interface and
(...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after
1249 if (dm_bht_set_root_hexdigest(&vc->bht, argv[5])) { 1472 if (dm_bht_set_root_hexdigest(&vc->bht, argv[5])) {
1250 DMERR("root hexdigest error"); 1473 DMERR("root hexdigest error");
1251 goto bad_root_hexdigest; 1474 goto bad_root_hexdigest;
1252 } 1475 }
1253 dm_bht_set_read_cb(&vc->bht, kverityd_bht_read_callback); 1476 dm_bht_set_read_cb(&vc->bht, kverityd_bht_read_callback);
1254 dm_bht_set_entry_readahead(&vc->bht, bht_readahead); 1477 dm_bht_set_entry_readahead(&vc->bht, bht_readahead);
1255 1478
1256 /* arg0: device to verify */ 1479 /* arg0: device to verify */
1257 vc->start = 0; /* TODO: should this support a starting offset? */ 1480 vc->start = 0; /* TODO: should this support a starting offset? */
1258 /* We only ever grab the device in read-only mode. */ 1481 /* We only ever grab the device in read-only mode. */
1259 » ret = dm_get_device(ti, argv[0], vc->start, ti->len, 1482 » ret = verity_get_device(ti, argv[0], vc->start, ti->len, &vc->dev);
1260 » » » dm_table_get_mode(ti->table), &vc->dev);
1261 if (ret) { 1483 if (ret) {
1262 DMERR("Failed to acquire device '%s': %d", argv[0], ret); 1484 DMERR("Failed to acquire device '%s': %d", argv[0], ret);
1263 ti->error = "Device lookup failed"; 1485 ti->error = "Device lookup failed";
1264 goto bad_verity_dev; 1486 goto bad_verity_dev;
1265 } 1487 }
1266 1488
1267 if (PAGE_ALIGN(vc->start) != vc->start || 1489 if (PAGE_ALIGN(vc->start) != vc->start ||
1268 PAGE_ALIGN(to_bytes(ti->len)) != to_bytes(ti->len)) { 1490 PAGE_ALIGN(to_bytes(ti->len)) != to_bytes(ti->len)) {
1269 ti->error = "Device must be PAGE_SIZE divisble/aligned"; 1491 ti->error = "Device must be PAGE_SIZE divisble/aligned";
1270 goto bad_hash_start; 1492 goto bad_hash_start;
1271 } 1493 }
1272 1494
1273 /* arg2: offset to hash on the hash device */ 1495 /* arg2: offset to hash on the hash device */
1274 if (sscanf(argv[2], "%llu", &tmpull) != 1) { 1496 if (sscanf(argv[2], "%llu", &tmpull) != 1) {
1275 ti->error = 1497 ti->error =
1276 "Invalid hash_start supplied"; 1498 "Invalid hash_start supplied";
1277 goto bad_hash_start; 1499 goto bad_hash_start;
1278 } 1500 }
1279 vc->hash_start = (sector_t)(tmpull); 1501 vc->hash_start = (sector_t)(tmpull);
1280 1502
1281 /* arg1: device with hashes. 1503 /* arg1: device with hashes.
1282 * Note, arg1 == arg0 is okay as long as the size of 1504 * Note, arg1 == arg0 is okay as long as the size of
1283 * ti->len passed to device mapper does not include 1505 * ti->len passed to device mapper does not include
1284 * the hashes. 1506 * the hashes.
1285 */ 1507 */
1286 » if (dm_get_device(ti, argv[1], vc->hash_start, dm_bht_sectors(&vc->bht), 1508 » if (verity_get_device(ti, argv[1], vc->hash_start,
1287 » » » dm_table_get_mode(ti->table), &vc->hash_dev)) { 1509 » » » dm_bht_sectors(&vc->bht), &vc->hash_dev)) {
1288 ti->error = "Hash device lookup failed"; 1510 ti->error = "Hash device lookup failed";
1289 goto bad_hash_dev; 1511 goto bad_hash_dev;
1290 } 1512 }
1291 1513
1292 /* We leave the validity on the hash device open until the 1514 /* We leave the validity on the hash device open until the
1293 * next arg. Then we go ahead and try to read in all the bundle 1515 * next arg. Then we go ahead and try to read in all the bundle
1294 * hashes which live after the block hashes. If it fails, then 1516 * hashes which live after the block hashes. If it fails, then
1295 * the hash offset was wrong. 1517 * the hash offset was wrong.
1296 */ 1518 */
1297 1519
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
1549 dm_unregister_target(&verity_target); 1771 dm_unregister_target(&verity_target);
1550 kmem_cache_destroy(_verity_io_pool); 1772 kmem_cache_destroy(_verity_io_pool);
1551 } 1773 }
1552 1774
1553 module_init(dm_verity_init); 1775 module_init(dm_verity_init);
1554 module_exit(dm_verity_exit); 1776 module_exit(dm_verity_exit);
1555 1777
1556 MODULE_AUTHOR("The Chromium OS Authors <chromium-os-dev@chromium.org>"); 1778 MODULE_AUTHOR("The Chromium OS Authors <chromium-os-dev@chromium.org>");
1557 MODULE_DESCRIPTION(DM_NAME " target for transparent disk integrity checking"); 1779 MODULE_DESCRIPTION(DM_NAME " target for transparent disk integrity checking");
1558 MODULE_LICENSE("GPL"); 1780 MODULE_LICENSE("GPL");
OLDNEW
« no previous file with comments | « no previous file | fs/partitions/efi.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698