fs_mgr_verity.c revision 7b97c7a3fa0f1bdae5b45a70f625ff48f9dab0c1
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <inttypes.h> 18#include <stdio.h> 19#include <stdlib.h> 20#include <string.h> 21#include <unistd.h> 22#include <fcntl.h> 23#include <ctype.h> 24#include <sys/mount.h> 25#include <sys/stat.h> 26#include <errno.h> 27#include <sys/types.h> 28#include <sys/wait.h> 29#include <libgen.h> 30#include <time.h> 31 32#include <private/android_filesystem_config.h> 33#include <cutils/properties.h> 34#include <logwrap/logwrap.h> 35 36#include "mincrypt/rsa.h" 37#include "mincrypt/sha.h" 38#include "mincrypt/sha256.h" 39 40#include "ext4_sb.h" 41 42#include "fs_mgr_priv.h" 43#include "fs_mgr_priv_verity.h" 44 45#define FSTAB_PREFIX "/fstab." 46 47#define VERITY_METADATA_SIZE 32768 48#define VERITY_TABLE_RSA_KEY "/verity_key" 49 50#define METADATA_MAGIC 0x01564c54 51#define METADATA_TAG_MAX_LENGTH 63 52#define METADATA_EOD "eod" 53 54#define VERITY_STATE_TAG "verity_state" 55#define VERITY_STATE_HEADER 0x83c0ae9d 56#define VERITY_STATE_VERSION 1 57 58#define VERITY_KMSG_RESTART "dm-verity device corrupted" 59#define VERITY_KMSG_BUFSIZE 1024 60 61#define __STRINGIFY(x) #x 62#define STRINGIFY(x) __STRINGIFY(x) 63 64struct verity_state { 65 uint32_t header; 66 uint32_t version; 67 int32_t mode; 68}; 69 70extern struct fs_info info; 71 72static RSAPublicKey *load_key(char *path) 73{ 74 FILE *f; 75 RSAPublicKey *key; 76 77 key = malloc(sizeof(RSAPublicKey)); 78 if (!key) { 79 ERROR("Can't malloc key\n"); 80 return NULL; 81 } 82 83 f = fopen(path, "r"); 84 if (!f) { 85 ERROR("Can't open '%s'\n", path); 86 free(key); 87 return NULL; 88 } 89 90 if (!fread(key, sizeof(*key), 1, f)) { 91 ERROR("Could not read key!"); 92 fclose(f); 93 free(key); 94 return NULL; 95 } 96 97 if (key->len != RSANUMWORDS) { 98 ERROR("Invalid key length %d\n", key->len); 99 fclose(f); 100 free(key); 101 return NULL; 102 } 103 104 fclose(f); 105 return key; 106} 107 108static int verify_table(char *signature, char *table, int table_length) 109{ 110 RSAPublicKey *key; 111 uint8_t hash_buf[SHA256_DIGEST_SIZE]; 112 int retval = -1; 113 114 // Hash the table 115 SHA256_hash((uint8_t*)table, table_length, hash_buf); 116 117 // Now get the public key from the keyfile 118 key = load_key(VERITY_TABLE_RSA_KEY); 119 if (!key) { 120 ERROR("Couldn't load verity keys"); 121 goto out; 122 } 123 124 // verify the result 125 if (!RSA_verify(key, 126 (uint8_t*) signature, 127 RSANUMBYTES, 128 (uint8_t*) hash_buf, 129 SHA256_DIGEST_SIZE)) { 130 ERROR("Couldn't verify table."); 131 goto out; 132 } 133 134 retval = 0; 135 136out: 137 free(key); 138 return retval; 139} 140 141static int get_target_device_size(char *blk_device, uint64_t *device_size) 142{ 143 int data_device; 144 struct ext4_super_block sb; 145 struct fs_info info; 146 147 info.len = 0; /* Only len is set to 0 to ask the device for real size. */ 148 149 data_device = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC)); 150 if (data_device == -1) { 151 ERROR("Error opening block device (%s)", strerror(errno)); 152 return -1; 153 } 154 155 if (TEMP_FAILURE_RETRY(lseek64(data_device, 1024, SEEK_SET)) < 0) { 156 ERROR("Error seeking to superblock"); 157 TEMP_FAILURE_RETRY(close(data_device)); 158 return -1; 159 } 160 161 if (TEMP_FAILURE_RETRY(read(data_device, &sb, sizeof(sb))) != sizeof(sb)) { 162 ERROR("Error reading superblock"); 163 TEMP_FAILURE_RETRY(close(data_device)); 164 return -1; 165 } 166 167 ext4_parse_sb(&sb, &info); 168 *device_size = info.len; 169 170 TEMP_FAILURE_RETRY(close(data_device)); 171 return 0; 172} 173 174static int read_verity_metadata(char *block_device, char **signature, char **table) 175{ 176 unsigned magic_number; 177 unsigned table_length; 178 uint64_t device_length; 179 int protocol_version; 180 int device; 181 int retval = FS_MGR_SETUP_VERITY_FAIL; 182 *signature = 0; 183 *table = 0; 184 185 device = TEMP_FAILURE_RETRY(open(block_device, O_RDONLY | O_CLOEXEC)); 186 if (device == -1) { 187 ERROR("Could not open block device %s (%s).\n", block_device, strerror(errno)); 188 goto out; 189 } 190 191 // find the start of the verity metadata 192 if (get_target_device_size(block_device, &device_length) < 0) { 193 ERROR("Could not get target device size.\n"); 194 goto out; 195 } 196 if (TEMP_FAILURE_RETRY(lseek64(device, device_length, SEEK_SET)) < 0) { 197 ERROR("Could not seek to start of verity metadata block.\n"); 198 goto out; 199 } 200 201 // check the magic number 202 if (TEMP_FAILURE_RETRY(read(device, &magic_number, sizeof(magic_number))) != 203 sizeof(magic_number)) { 204 ERROR("Couldn't read magic number!\n"); 205 goto out; 206 } 207 208#ifdef ALLOW_ADBD_DISABLE_VERITY 209 if (magic_number == VERITY_METADATA_MAGIC_DISABLE) { 210 retval = FS_MGR_SETUP_VERITY_DISABLED; 211 INFO("Attempt to cleanly disable verity - only works in USERDEBUG"); 212 goto out; 213 } 214#endif 215 216 if (magic_number != VERITY_METADATA_MAGIC_NUMBER) { 217 ERROR("Couldn't find verity metadata at offset %"PRIu64"!\n", 218 device_length); 219 goto out; 220 } 221 222 // check the protocol version 223 if (TEMP_FAILURE_RETRY(read(device, &protocol_version, 224 sizeof(protocol_version))) != sizeof(protocol_version)) { 225 ERROR("Couldn't read verity metadata protocol version!\n"); 226 goto out; 227 } 228 if (protocol_version != 0) { 229 ERROR("Got unknown verity metadata protocol version %d!\n", protocol_version); 230 goto out; 231 } 232 233 // get the signature 234 *signature = (char*) malloc(RSANUMBYTES); 235 if (!*signature) { 236 ERROR("Couldn't allocate memory for signature!\n"); 237 goto out; 238 } 239 if (TEMP_FAILURE_RETRY(read(device, *signature, RSANUMBYTES)) != RSANUMBYTES) { 240 ERROR("Couldn't read signature from verity metadata!\n"); 241 goto out; 242 } 243 244 // get the size of the table 245 if (TEMP_FAILURE_RETRY(read(device, &table_length, sizeof(table_length))) != 246 sizeof(table_length)) { 247 ERROR("Couldn't get the size of the verity table from metadata!\n"); 248 goto out; 249 } 250 251 // get the table + null terminator 252 *table = malloc(table_length + 1); 253 if (!*table) { 254 ERROR("Couldn't allocate memory for verity table!\n"); 255 goto out; 256 } 257 if (TEMP_FAILURE_RETRY(read(device, *table, table_length)) != 258 (ssize_t)table_length) { 259 ERROR("Couldn't read the verity table from metadata!\n"); 260 goto out; 261 } 262 263 (*table)[table_length] = 0; 264 retval = FS_MGR_SETUP_VERITY_SUCCESS; 265 266out: 267 if (device != -1) 268 TEMP_FAILURE_RETRY(close(device)); 269 270 if (retval != FS_MGR_SETUP_VERITY_SUCCESS) { 271 free(*table); 272 free(*signature); 273 *table = 0; 274 *signature = 0; 275 } 276 277 return retval; 278} 279 280static void verity_ioctl_init(struct dm_ioctl *io, char *name, unsigned flags) 281{ 282 memset(io, 0, DM_BUF_SIZE); 283 io->data_size = DM_BUF_SIZE; 284 io->data_start = sizeof(struct dm_ioctl); 285 io->version[0] = 4; 286 io->version[1] = 0; 287 io->version[2] = 0; 288 io->flags = flags | DM_READONLY_FLAG; 289 if (name) { 290 strlcpy(io->name, name, sizeof(io->name)); 291 } 292} 293 294static int create_verity_device(struct dm_ioctl *io, char *name, int fd) 295{ 296 verity_ioctl_init(io, name, 1); 297 if (ioctl(fd, DM_DEV_CREATE, io)) { 298 ERROR("Error creating device mapping (%s)", strerror(errno)); 299 return -1; 300 } 301 return 0; 302} 303 304static int get_verity_device_name(struct dm_ioctl *io, char *name, int fd, char **dev_name) 305{ 306 verity_ioctl_init(io, name, 0); 307 if (ioctl(fd, DM_DEV_STATUS, io)) { 308 ERROR("Error fetching verity device number (%s)", strerror(errno)); 309 return -1; 310 } 311 int dev_num = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); 312 if (asprintf(dev_name, "/dev/block/dm-%u", dev_num) < 0) { 313 ERROR("Error getting verity block device name (%s)", strerror(errno)); 314 return -1; 315 } 316 return 0; 317} 318 319static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, int fd, char *table, 320 int mode) 321{ 322 char *verity_params; 323 char *buffer = (char*) io; 324 size_t bufsize; 325 uint64_t device_size = 0; 326 327 if (get_target_device_size(blockdev, &device_size) < 0) { 328 return -1; 329 } 330 331 verity_ioctl_init(io, name, DM_STATUS_TABLE_FLAG); 332 333 struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)]; 334 335 // set tgt arguments here 336 io->target_count = 1; 337 tgt->status=0; 338 tgt->sector_start=0; 339 tgt->length=device_size/512; 340 strcpy(tgt->target_type, "verity"); 341 342 // build the verity params here 343 verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); 344 bufsize = DM_BUF_SIZE - (verity_params - buffer); 345 346 if (mode == VERITY_MODE_EIO) { 347 // allow operation with older dm-verity drivers that are unaware 348 // of the mode parameter by omitting it; this also means that we 349 // cannot use logging mode with these drivers, they always cause 350 // an I/O error for corrupted blocks 351 strcpy(verity_params, table); 352 } else if (snprintf(verity_params, bufsize, "%s %d", table, mode) < 0) { 353 return -1; 354 } 355 356 // set next target boundary 357 verity_params += strlen(verity_params) + 1; 358 verity_params = (char*) (((unsigned long)verity_params + 7) & ~8); 359 tgt->next = verity_params - buffer; 360 361 // send the ioctl to load the verity table 362 if (ioctl(fd, DM_TABLE_LOAD, io)) { 363 ERROR("Error loading verity table (%s)", strerror(errno)); 364 return -1; 365 } 366 367 return 0; 368} 369 370static int resume_verity_table(struct dm_ioctl *io, char *name, int fd) 371{ 372 verity_ioctl_init(io, name, 0); 373 if (ioctl(fd, DM_DEV_SUSPEND, io)) { 374 ERROR("Error activating verity device (%s)", strerror(errno)); 375 return -1; 376 } 377 return 0; 378} 379 380static int test_access(char *device) { 381 int tries = 25; 382 while (tries--) { 383 if (!access(device, F_OK) || errno != ENOENT) { 384 return 0; 385 } 386 usleep(40 * 1000); 387 } 388 return -1; 389} 390 391static int check_verity_restart(const char *fname) 392{ 393 char buffer[VERITY_KMSG_BUFSIZE + 1]; 394 int fd; 395 int rc = 0; 396 ssize_t size; 397 struct stat s; 398 399 fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC)); 400 401 if (fd == -1) { 402 if (errno != ENOENT) { 403 ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); 404 } 405 goto out; 406 } 407 408 if (fstat(fd, &s) == -1) { 409 ERROR("Failed to fstat %s (%s)\n", fname, strerror(errno)); 410 goto out; 411 } 412 413 size = VERITY_KMSG_BUFSIZE; 414 415 if (size > s.st_size) { 416 size = s.st_size; 417 } 418 419 if (lseek(fd, s.st_size - size, SEEK_SET) == -1) { 420 ERROR("Failed to lseek %jd %s (%s)\n", (intmax_t)(s.st_size - size), fname, 421 strerror(errno)); 422 goto out; 423 } 424 425 if (TEMP_FAILURE_RETRY(read(fd, buffer, size)) != size) { 426 ERROR("Failed to read %zd bytes from %s (%s)\n", size, fname, 427 strerror(errno)); 428 goto out; 429 } 430 431 buffer[size] = '\0'; 432 433 if (strstr(buffer, VERITY_KMSG_RESTART) != NULL) { 434 rc = 1; 435 } 436 437out: 438 if (fd != -1) { 439 TEMP_FAILURE_RETRY(close(fd)); 440 } 441 442 return rc; 443} 444 445static int was_verity_restart() 446{ 447 static const char *files[] = { 448 "/sys/fs/pstore/console-ramoops", 449 "/proc/last_kmsg", 450 NULL 451 }; 452 int i; 453 454 for (i = 0; files[i]; ++i) { 455 if (check_verity_restart(files[i])) { 456 return 1; 457 } 458 } 459 460 return 0; 461} 462 463static int metadata_add(FILE *fp, long start, const char *tag, 464 unsigned int length, off64_t *offset) 465{ 466 if (fseek(fp, start, SEEK_SET) < 0 || 467 fprintf(fp, "%s %u\n", tag, length) < 0) { 468 return -1; 469 } 470 471 *offset = ftell(fp); 472 473 if (fseek(fp, length, SEEK_CUR) < 0 || 474 fprintf(fp, METADATA_EOD " 0\n") < 0) { 475 return -1; 476 } 477 478 return 0; 479} 480 481static int metadata_find(const char *fname, const char *stag, 482 unsigned int slength, off64_t *offset) 483{ 484 FILE *fp = NULL; 485 char tag[METADATA_TAG_MAX_LENGTH + 1]; 486 int rc = -1; 487 int n; 488 long start = 0x4000; /* skip cryptfs metadata area */ 489 uint32_t magic; 490 unsigned int length = 0; 491 492 if (!fname) { 493 return -1; 494 } 495 496 fp = fopen(fname, "r+"); 497 498 if (!fp) { 499 ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); 500 goto out; 501 } 502 503 /* check magic */ 504 if (fseek(fp, start, SEEK_SET) < 0 || 505 fread(&magic, sizeof(magic), 1, fp) != 1) { 506 ERROR("Failed to read magic from %s (%s)\n", fname, strerror(errno)); 507 goto out; 508 } 509 510 if (magic != METADATA_MAGIC) { 511 magic = METADATA_MAGIC; 512 513 if (fseek(fp, start, SEEK_SET) < 0 || 514 fwrite(&magic, sizeof(magic), 1, fp) != 1) { 515 ERROR("Failed to write magic to %s (%s)\n", fname, strerror(errno)); 516 goto out; 517 } 518 519 rc = metadata_add(fp, start + sizeof(magic), stag, slength, offset); 520 if (rc < 0) { 521 ERROR("Failed to add metadata to %s: %s\n", fname, strerror(errno)); 522 } 523 524 goto out; 525 } 526 527 start += sizeof(magic); 528 529 while (1) { 530 n = fscanf(fp, "%" STRINGIFY(METADATA_TAG_MAX_LENGTH) "s %u\n", 531 tag, &length); 532 533 if (n == 2 && strcmp(tag, METADATA_EOD)) { 534 /* found a tag */ 535 start = ftell(fp); 536 537 if (!strcmp(tag, stag) && length == slength) { 538 *offset = start; 539 rc = 0; 540 goto out; 541 } 542 543 start += length; 544 545 if (fseek(fp, length, SEEK_CUR) < 0) { 546 ERROR("Failed to seek %s (%s)\n", fname, strerror(errno)); 547 goto out; 548 } 549 } else { 550 rc = metadata_add(fp, start, stag, slength, offset); 551 if (rc < 0) { 552 ERROR("Failed to write metadata to %s: %s\n", fname, 553 strerror(errno)); 554 } 555 goto out; 556 } 557 } 558 559out: 560 if (fp) { 561 fflush(fp); 562 fclose(fp); 563 } 564 565 return rc; 566} 567 568static int write_verity_state(const char *fname, off64_t offset, int32_t mode) 569{ 570 int fd; 571 int rc = -1; 572 struct verity_state s = { VERITY_STATE_HEADER, VERITY_STATE_VERSION, mode }; 573 574 fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC)); 575 576 if (fd == -1) { 577 ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); 578 goto out; 579 } 580 581 if (TEMP_FAILURE_RETRY(pwrite64(fd, &s, sizeof(s), offset)) != sizeof(s)) { 582 ERROR("Failed to write %zu bytes to %s to offset %" PRIu64 " (%s)\n", 583 sizeof(s), fname, offset, strerror(errno)); 584 goto out; 585 } 586 587 rc = 0; 588 589out: 590 if (fd != -1) { 591 TEMP_FAILURE_RETRY(close(fd)); 592 } 593 594 return rc; 595} 596 597static int load_verity_state(struct fstab_rec *fstab, int *mode) 598{ 599 int fd = -1; 600 int rc = -1; 601 off64_t offset = 0; 602 struct verity_state s; 603 604 if (metadata_find(fstab->verity_loc, VERITY_STATE_TAG, sizeof(s), 605 &offset) < 0) { 606 /* fall back to stateless behavior */ 607 *mode = VERITY_MODE_EIO; 608 rc = 0; 609 goto out; 610 } 611 612 if (was_verity_restart()) { 613 /* device was restarted after dm-verity detected a corrupted 614 * block, so switch to logging mode */ 615 *mode = VERITY_MODE_LOGGING; 616 rc = write_verity_state(fstab->verity_loc, offset, *mode); 617 goto out; 618 } 619 620 fd = TEMP_FAILURE_RETRY(open(fstab->verity_loc, O_RDONLY | O_CLOEXEC)); 621 622 if (fd == -1) { 623 ERROR("Failed to open %s (%s)\n", fstab->verity_loc, strerror(errno)); 624 goto out; 625 } 626 627 if (TEMP_FAILURE_RETRY(pread64(fd, &s, sizeof(s), offset)) != sizeof(s)) { 628 ERROR("Failed to read %zu bytes from %s offset %" PRIu64 " (%s)\n", 629 sizeof(s), fstab->verity_loc, offset, strerror(errno)); 630 goto out; 631 } 632 633 if (s.header != VERITY_STATE_HEADER) { 634 /* space allocated, but no state written. write default state */ 635 *mode = VERITY_MODE_DEFAULT; 636 rc = write_verity_state(fstab->verity_loc, offset, *mode); 637 goto out; 638 } 639 640 if (s.version != VERITY_STATE_VERSION) { 641 ERROR("Unsupported verity state version (%u)\n", s.version); 642 goto out; 643 } 644 645 if (s.mode < VERITY_MODE_EIO || 646 s.mode > VERITY_MODE_LAST) { 647 ERROR("Unsupported verity mode (%u)\n", s.mode); 648 goto out; 649 } 650 651 *mode = s.mode; 652 rc = 0; 653 654out: 655 if (fd != -1) { 656 TEMP_FAILURE_RETRY(close(fd)); 657 } 658 659 return rc; 660} 661 662int fs_mgr_load_verity_state(int *mode) 663{ 664 char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; 665 char propbuf[PROPERTY_VALUE_MAX]; 666 int rc = -1; 667 int i; 668 struct fstab *fstab = NULL; 669 670 *mode = VERITY_MODE_DEFAULT; 671 672 property_get("ro.hardware", propbuf, ""); 673 snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); 674 675 fstab = fs_mgr_read_fstab(fstab_filename); 676 677 if (!fstab) { 678 ERROR("Failed to read %s\n", fstab_filename); 679 goto out; 680 } 681 682 for (i = 0; i < fstab->num_entries; i++) { 683 if (!fs_mgr_is_verified(&fstab->recs[i])) { 684 continue; 685 } 686 687 rc = load_verity_state(&fstab->recs[i], mode); 688 if (rc < 0) { 689 continue; 690 } 691 692 /* if any of the verified partitions are in logging mode, return */ 693 if (*mode == VERITY_MODE_LOGGING) { 694 rc = 0; 695 goto out; 696 } 697 } 698 699 /* if there were multiple partitions, all in non-logging mode, return the 700 * state of the last one */ 701 rc = 0; 702 703out: 704 if (fstab) { 705 fs_mgr_free_fstab(fstab); 706 } 707 708 return rc; 709} 710 711int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) 712{ 713 _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE]; 714 char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; 715 char *mount_point; 716 char propbuf[PROPERTY_VALUE_MAX]; 717 char *status; 718 int fd = -1; 719 int i; 720 int rc = -1; 721 off64_t offset = 0; 722 struct dm_ioctl *io = (struct dm_ioctl *) buffer; 723 struct fstab *fstab = NULL; 724 725 fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)); 726 727 if (fd == -1) { 728 ERROR("Error opening device mapper (%s)\n", strerror(errno)); 729 goto out; 730 } 731 732 property_get("ro.hardware", propbuf, ""); 733 snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); 734 735 fstab = fs_mgr_read_fstab(fstab_filename); 736 737 if (!fstab) { 738 ERROR("Failed to read %s\n", fstab_filename); 739 goto out; 740 } 741 742 for (i = 0; i < fstab->num_entries; i++) { 743 if (!fs_mgr_is_verified(&fstab->recs[i])) { 744 continue; 745 } 746 747 if (metadata_find(fstab->recs[i].verity_loc, VERITY_STATE_TAG, 748 sizeof(struct verity_state), &offset) < 0) { 749 continue; 750 } 751 752 mount_point = basename(fstab->recs[i].mount_point); 753 verity_ioctl_init(io, mount_point, 0); 754 755 if (ioctl(fd, DM_TABLE_STATUS, io)) { 756 ERROR("Failed to query DM_TABLE_STATUS for %s (%s)\n", mount_point, 757 strerror(errno)); 758 goto out; 759 } 760 761 status = &buffer[io->data_start + sizeof(struct dm_target_spec)]; 762 763 if (*status == 'C') { 764 rc = write_verity_state(fstab->recs[i].verity_loc, offset, 765 VERITY_MODE_LOGGING); 766 767 if (rc == -1) { 768 goto out; 769 } 770 } 771 772 if (callback) { 773 callback(&fstab->recs[i], mount_point, *status); 774 } 775 } 776 777 /* Don't overwrite possible previous state if there's no corruption. */ 778 rc = 0; 779 780out: 781 if (fstab) { 782 fs_mgr_free_fstab(fstab); 783 } 784 785 if (fd) { 786 TEMP_FAILURE_RETRY(close(fd)); 787 } 788 789 return rc; 790} 791 792int fs_mgr_setup_verity(struct fstab_rec *fstab) { 793 794 int retval = FS_MGR_SETUP_VERITY_FAIL; 795 int fd = -1; 796 int mode; 797 798 char *verity_blk_name = 0; 799 char *verity_table = 0; 800 char *verity_table_signature = 0; 801 802 _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE]; 803 struct dm_ioctl *io = (struct dm_ioctl *) buffer; 804 char *mount_point = basename(fstab->mount_point); 805 806 // set the dm_ioctl flags 807 io->flags |= 1; 808 io->target_count = 1; 809 810 // check to ensure that the verity device is ext4 811 // TODO: support non-ext4 filesystems 812 if (strcmp(fstab->fs_type, "ext4")) { 813 ERROR("Cannot verify non-ext4 device (%s)", fstab->fs_type); 814 return retval; 815 } 816 817 // read the verity block at the end of the block device 818 // send error code up the chain so we can detect attempts to disable verity 819 retval = read_verity_metadata(fstab->blk_device, 820 &verity_table_signature, 821 &verity_table); 822 if (retval < 0) { 823 goto out; 824 } 825 826 retval = FS_MGR_SETUP_VERITY_FAIL; 827 828 // get the device mapper fd 829 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { 830 ERROR("Error opening device mapper (%s)", strerror(errno)); 831 goto out; 832 } 833 834 // create the device 835 if (create_verity_device(io, mount_point, fd) < 0) { 836 ERROR("Couldn't create verity device!"); 837 goto out; 838 } 839 840 // get the name of the device file 841 if (get_verity_device_name(io, mount_point, fd, &verity_blk_name) < 0) { 842 ERROR("Couldn't get verity device number!"); 843 goto out; 844 } 845 846 // verify the signature on the table 847 if (verify_table(verity_table_signature, 848 verity_table, 849 strlen(verity_table)) < 0) { 850 goto out; 851 } 852 853 if (load_verity_state(fstab, &mode) < 0) { 854 /* if accessing or updating the state failed, switch to the default 855 * safe mode. This makes sure the device won't end up in an endless 856 * restart loop, and no corrupted data will be exposed to userspace 857 * without a warning. */ 858 mode = VERITY_MODE_EIO; 859 } 860 861 INFO("Enabling dm-verity for %s (mode %d)\n", mount_point, mode); 862 863 // load the verity mapping table 864 if (load_verity_table(io, mount_point, fstab->blk_device, fd, verity_table, 865 mode) < 0) { 866 goto out; 867 } 868 869 // activate the device 870 if (resume_verity_table(io, mount_point, fd) < 0) { 871 goto out; 872 } 873 874 // mark the underlying block device as read-only 875 fs_mgr_set_blk_ro(fstab->blk_device); 876 877 // assign the new verity block device as the block device 878 free(fstab->blk_device); 879 fstab->blk_device = verity_blk_name; 880 verity_blk_name = 0; 881 882 // make sure we've set everything up properly 883 if (test_access(fstab->blk_device) < 0) { 884 goto out; 885 } 886 887 retval = FS_MGR_SETUP_VERITY_SUCCESS; 888 889out: 890 if (fd != -1) { 891 close(fd); 892 } 893 894 free(verity_table); 895 free(verity_table_signature); 896 free(verity_blk_name); 897 898 return retval; 899} 900