fs_mgr_verity.cpp revision 183ca56ce22fa59d8b1a1372051b28984d1ab91c
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 <ctype.h> 18#include <errno.h> 19#include <fcntl.h> 20#include <inttypes.h> 21#include <libgen.h> 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25#include <sys/mount.h> 26#include <sys/stat.h> 27#include <sys/types.h> 28#include <sys/wait.h> 29#include <time.h> 30#include <unistd.h> 31 32#include <android-base/file.h> 33#include <android-base/strings.h> 34#include <android-base/unique_fd.h> 35#include <crypto_utils/android_pubkey.h> 36#include <cutils/properties.h> 37#include <logwrap/logwrap.h> 38#include <openssl/obj_mac.h> 39#include <openssl/rsa.h> 40#include <openssl/sha.h> 41#include <private/android_filesystem_config.h> 42 43#include "fec/io.h" 44 45#include "fs_mgr.h" 46#include "fs_mgr_priv.h" 47#include "fs_mgr_priv_dm_ioctl.h" 48#include "fs_mgr_priv_verity.h" 49 50#define FSTAB_PREFIX "/fstab." 51 52#define VERITY_TABLE_RSA_KEY "/verity_key" 53#define VERITY_TABLE_HASH_IDX 8 54#define VERITY_TABLE_SALT_IDX 9 55 56#define VERITY_TABLE_OPT_RESTART "restart_on_corruption" 57#define VERITY_TABLE_OPT_LOGGING "ignore_corruption" 58#define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks" 59 60#define VERITY_TABLE_OPT_FEC_FORMAT \ 61 "use_fec_from_device %s fec_start %" PRIu64 " fec_blocks %" PRIu64 \ 62 " fec_roots %u " VERITY_TABLE_OPT_IGNZERO 63#define VERITY_TABLE_OPT_FEC_ARGS 9 64 65#define METADATA_MAGIC 0x01564c54 66#define METADATA_TAG_MAX_LENGTH 63 67#define METADATA_EOD "eod" 68 69#define VERITY_LASTSIG_TAG "verity_lastsig" 70 71#define VERITY_STATE_TAG "verity_state" 72#define VERITY_STATE_HEADER 0x83c0ae9d 73#define VERITY_STATE_VERSION 1 74 75#define VERITY_KMSG_RESTART "dm-verity device corrupted" 76#define VERITY_KMSG_BUFSIZE 1024 77 78#define READ_BUF_SIZE 4096 79 80#define __STRINGIFY(x) #x 81#define STRINGIFY(x) __STRINGIFY(x) 82 83struct verity_state { 84 uint32_t header; 85 uint32_t version; 86 int32_t mode; 87}; 88 89extern struct fs_info info; 90 91static RSA *load_key(const char *path) 92{ 93 uint8_t key_data[ANDROID_PUBKEY_ENCODED_SIZE]; 94 95 FILE* f = fopen(path, "r"); 96 if (!f) { 97 LERROR << "Can't open " << path; 98 return NULL; 99 } 100 101 if (!fread(key_data, sizeof(key_data), 1, f)) { 102 LERROR << "Could not read key!"; 103 fclose(f); 104 return NULL; 105 } 106 107 fclose(f); 108 109 RSA* key = NULL; 110 if (!android_pubkey_decode(key_data, sizeof(key_data), &key)) { 111 LERROR << "Could not parse key!"; 112 return NULL; 113 } 114 115 return key; 116} 117 118static int verify_table(const uint8_t *signature, size_t signature_size, 119 const char *table, uint32_t table_length) 120{ 121 RSA *key; 122 uint8_t hash_buf[SHA256_DIGEST_LENGTH]; 123 int retval = -1; 124 125 // Hash the table 126 SHA256((uint8_t*)table, table_length, hash_buf); 127 128 // Now get the public key from the keyfile 129 key = load_key(VERITY_TABLE_RSA_KEY); 130 if (!key) { 131 LERROR << "Couldn't load verity keys"; 132 goto out; 133 } 134 135 // verify the result 136 if (!RSA_verify(NID_sha256, hash_buf, sizeof(hash_buf), signature, 137 signature_size, key)) { 138 LERROR << "Couldn't verify table"; 139 goto out; 140 } 141 142 retval = 0; 143 144out: 145 RSA_free(key); 146 return retval; 147} 148 149static int verify_verity_signature(const struct fec_verity_metadata& verity) 150{ 151 if (verify_table(verity.signature, sizeof(verity.signature), 152 verity.table, verity.table_length) == 0 || 153 verify_table(verity.ecc_signature, sizeof(verity.ecc_signature), 154 verity.table, verity.table_length) == 0) { 155 return 0; 156 } 157 158 return -1; 159} 160 161static int invalidate_table(char *table, size_t table_length) 162{ 163 size_t n = 0; 164 size_t idx = 0; 165 size_t cleared = 0; 166 167 while (n < table_length) { 168 if (table[n++] == ' ') { 169 ++idx; 170 } 171 172 if (idx != VERITY_TABLE_HASH_IDX && idx != VERITY_TABLE_SALT_IDX) { 173 continue; 174 } 175 176 while (n < table_length && table[n] != ' ') { 177 table[n++] = '0'; 178 } 179 180 if (++cleared == 2) { 181 return 0; 182 } 183 } 184 185 return -1; 186} 187 188struct verity_table_params { 189 char *table; 190 int mode; 191 struct fec_ecc_metadata ecc; 192 const char *ecc_dev; 193}; 194 195typedef bool (*format_verity_table_func)(char *buf, const size_t bufsize, 196 const struct verity_table_params *params); 197 198static bool format_verity_table(char *buf, const size_t bufsize, 199 const struct verity_table_params *params) 200{ 201 const char *mode_flag = NULL; 202 int res = -1; 203 204 if (params->mode == VERITY_MODE_RESTART) { 205 mode_flag = VERITY_TABLE_OPT_RESTART; 206 } else if (params->mode == VERITY_MODE_LOGGING) { 207 mode_flag = VERITY_TABLE_OPT_LOGGING; 208 } 209 210 if (params->ecc.valid) { 211 if (mode_flag) { 212 res = snprintf(buf, bufsize, 213 "%s %u %s " VERITY_TABLE_OPT_FEC_FORMAT, 214 params->table, 1 + VERITY_TABLE_OPT_FEC_ARGS, mode_flag, params->ecc_dev, 215 params->ecc.start / FEC_BLOCKSIZE, params->ecc.blocks, params->ecc.roots); 216 } else { 217 res = snprintf(buf, bufsize, 218 "%s %u " VERITY_TABLE_OPT_FEC_FORMAT, 219 params->table, VERITY_TABLE_OPT_FEC_ARGS, params->ecc_dev, 220 params->ecc.start / FEC_BLOCKSIZE, params->ecc.blocks, params->ecc.roots); 221 } 222 } else if (mode_flag) { 223 res = snprintf(buf, bufsize, "%s 2 " VERITY_TABLE_OPT_IGNZERO " %s", params->table, 224 mode_flag); 225 } else { 226 res = snprintf(buf, bufsize, "%s 1 " VERITY_TABLE_OPT_IGNZERO, params->table); 227 } 228 229 if (res < 0 || (size_t)res >= bufsize) { 230 LERROR << "Error building verity table; insufficient buffer size?"; 231 return false; 232 } 233 234 return true; 235} 236 237static bool format_legacy_verity_table(char *buf, const size_t bufsize, 238 const struct verity_table_params *params) 239{ 240 int res; 241 242 if (params->mode == VERITY_MODE_EIO) { 243 res = strlcpy(buf, params->table, bufsize); 244 } else { 245 res = snprintf(buf, bufsize, "%s %d", params->table, params->mode); 246 } 247 248 if (res < 0 || (size_t)res >= bufsize) { 249 LERROR << "Error building verity table; insufficient buffer size?"; 250 return false; 251 } 252 253 return true; 254} 255 256static int load_verity_table(struct dm_ioctl *io, const std::string &name, 257 uint64_t device_size, int fd, 258 const struct verity_table_params *params, format_verity_table_func format) 259{ 260 char *verity_params; 261 char *buffer = (char*) io; 262 size_t bufsize; 263 264 fs_mgr_verity_ioctl_init(io, name, DM_STATUS_TABLE_FLAG); 265 266 struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)]; 267 268 // set tgt arguments 269 io->target_count = 1; 270 tgt->status = 0; 271 tgt->sector_start = 0; 272 tgt->length = device_size / 512; 273 strcpy(tgt->target_type, "verity"); 274 275 // build the verity params 276 verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); 277 bufsize = DM_BUF_SIZE - (verity_params - buffer); 278 279 if (!format(verity_params, bufsize, params)) { 280 LERROR << "Failed to format verity parameters"; 281 return -1; 282 } 283 284 LINFO << "loading verity table: '" << verity_params << "'"; 285 286 // set next target boundary 287 verity_params += strlen(verity_params) + 1; 288 verity_params = (char*)(((uintptr_t)verity_params + 7) & ~7); 289 tgt->next = verity_params - buffer; 290 291 // send the ioctl to load the verity table 292 if (ioctl(fd, DM_TABLE_LOAD, io)) { 293 PERROR << "Error loading verity table"; 294 return -1; 295 } 296 297 return 0; 298} 299 300static int check_verity_restart(const char *fname) 301{ 302 char buffer[VERITY_KMSG_BUFSIZE + 1]; 303 int fd; 304 int rc = 0; 305 ssize_t size; 306 struct stat s; 307 308 fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC)); 309 310 if (fd == -1) { 311 if (errno != ENOENT) { 312 PERROR << "Failed to open " << fname; 313 } 314 goto out; 315 } 316 317 if (fstat(fd, &s) == -1) { 318 PERROR << "Failed to fstat " << fname; 319 goto out; 320 } 321 322 size = VERITY_KMSG_BUFSIZE; 323 324 if (size > s.st_size) { 325 size = s.st_size; 326 } 327 328 if (lseek(fd, s.st_size - size, SEEK_SET) == -1) { 329 PERROR << "Failed to lseek " << (intmax_t)(s.st_size - size) << " " << fname; 330 goto out; 331 } 332 333 if (!android::base::ReadFully(fd, buffer, size)) { 334 PERROR << "Failed to read " << size << " bytes from " << fname; 335 goto out; 336 } 337 338 buffer[size] = '\0'; 339 340 if (strstr(buffer, VERITY_KMSG_RESTART) != NULL) { 341 rc = 1; 342 } 343 344out: 345 if (fd != -1) { 346 close(fd); 347 } 348 349 return rc; 350} 351 352static int was_verity_restart() 353{ 354 static const char *files[] = { 355 "/sys/fs/pstore/console-ramoops", 356 "/proc/last_kmsg", 357 NULL 358 }; 359 int i; 360 361 for (i = 0; files[i]; ++i) { 362 if (check_verity_restart(files[i])) { 363 return 1; 364 } 365 } 366 367 return 0; 368} 369 370static int metadata_add(FILE *fp, long start, const char *tag, 371 unsigned int length, off64_t *offset) 372{ 373 if (fseek(fp, start, SEEK_SET) < 0 || 374 fprintf(fp, "%s %u\n", tag, length) < 0) { 375 return -1; 376 } 377 378 *offset = ftell(fp); 379 380 if (fseek(fp, length, SEEK_CUR) < 0 || 381 fprintf(fp, METADATA_EOD " 0\n") < 0) { 382 return -1; 383 } 384 385 return 0; 386} 387 388static int metadata_find(const char *fname, const char *stag, 389 unsigned int slength, off64_t *offset) 390{ 391 FILE *fp = NULL; 392 char tag[METADATA_TAG_MAX_LENGTH + 1]; 393 int rc = -1; 394 int n; 395 long start = 0x4000; /* skip cryptfs metadata area */ 396 uint32_t magic; 397 unsigned int length = 0; 398 399 if (!fname) { 400 return -1; 401 } 402 403 fp = fopen(fname, "r+"); 404 405 if (!fp) { 406 PERROR << "Failed to open " << fname; 407 goto out; 408 } 409 410 /* check magic */ 411 if (fseek(fp, start, SEEK_SET) < 0 || 412 fread(&magic, sizeof(magic), 1, fp) != 1) { 413 PERROR << "Failed to read magic from " << fname; 414 goto out; 415 } 416 417 if (magic != METADATA_MAGIC) { 418 magic = METADATA_MAGIC; 419 420 if (fseek(fp, start, SEEK_SET) < 0 || 421 fwrite(&magic, sizeof(magic), 1, fp) != 1) { 422 PERROR << "Failed to write magic to " << fname; 423 goto out; 424 } 425 426 rc = metadata_add(fp, start + sizeof(magic), stag, slength, offset); 427 if (rc < 0) { 428 PERROR << "Failed to add metadata to " << fname; 429 } 430 431 goto out; 432 } 433 434 start += sizeof(magic); 435 436 while (1) { 437 n = fscanf(fp, "%" STRINGIFY(METADATA_TAG_MAX_LENGTH) "s %u\n", 438 tag, &length); 439 440 if (n == 2 && strcmp(tag, METADATA_EOD)) { 441 /* found a tag */ 442 start = ftell(fp); 443 444 if (!strcmp(tag, stag) && length == slength) { 445 *offset = start; 446 rc = 0; 447 goto out; 448 } 449 450 start += length; 451 452 if (fseek(fp, length, SEEK_CUR) < 0) { 453 PERROR << "Failed to seek " << fname; 454 goto out; 455 } 456 } else { 457 rc = metadata_add(fp, start, stag, slength, offset); 458 if (rc < 0) { 459 PERROR << "Failed to write metadata to " << fname; 460 } 461 goto out; 462 } 463 } 464 465out: 466 if (fp) { 467 fflush(fp); 468 fclose(fp); 469 } 470 471 return rc; 472} 473 474static int write_verity_state(const char *fname, off64_t offset, int32_t mode) 475{ 476 int fd; 477 int rc = -1; 478 struct verity_state s = { VERITY_STATE_HEADER, VERITY_STATE_VERSION, mode }; 479 480 fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC)); 481 482 if (fd == -1) { 483 PERROR << "Failed to open " << fname; 484 goto out; 485 } 486 487 if (TEMP_FAILURE_RETRY(pwrite64(fd, &s, sizeof(s), offset)) != sizeof(s)) { 488 PERROR << "Failed to write " << sizeof(s) << " bytes to " << fname 489 << " to offset " << offset; 490 goto out; 491 } 492 493 rc = 0; 494 495out: 496 if (fd != -1) { 497 close(fd); 498 } 499 500 return rc; 501} 502 503static int read_verity_state(const char *fname, off64_t offset, int *mode) 504{ 505 int fd = -1; 506 int rc = -1; 507 struct verity_state s; 508 509 fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC)); 510 511 if (fd == -1) { 512 PERROR << "Failed to open " << fname; 513 goto out; 514 } 515 516 if (TEMP_FAILURE_RETRY(pread64(fd, &s, sizeof(s), offset)) != sizeof(s)) { 517 PERROR << "Failed to read " << sizeof(s) << " bytes from " << fname 518 << " offset " << offset; 519 goto out; 520 } 521 522 if (s.header != VERITY_STATE_HEADER) { 523 /* space allocated, but no state written. write default state */ 524 *mode = VERITY_MODE_DEFAULT; 525 rc = write_verity_state(fname, offset, *mode); 526 goto out; 527 } 528 529 if (s.version != VERITY_STATE_VERSION) { 530 LERROR << "Unsupported verity state version (" << s.version << ")"; 531 goto out; 532 } 533 534 if (s.mode < VERITY_MODE_EIO || 535 s.mode > VERITY_MODE_LAST) { 536 LERROR << "Unsupported verity mode (" << s.mode << ")"; 537 goto out; 538 } 539 540 *mode = s.mode; 541 rc = 0; 542 543out: 544 if (fd != -1) { 545 close(fd); 546 } 547 548 return rc; 549} 550 551static int read_partition(const char *path, uint64_t size) 552{ 553 char buf[READ_BUF_SIZE]; 554 ssize_t size_read; 555 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))); 556 557 if (fd == -1) { 558 PERROR << "Failed to open " << path; 559 return -errno; 560 } 561 562 while (size) { 563 size_read = TEMP_FAILURE_RETRY(read(fd, buf, READ_BUF_SIZE)); 564 if (size_read == -1) { 565 PERROR << "Error in reading partition " << path; 566 return -errno; 567 } 568 size -= size_read; 569 } 570 571 return 0; 572} 573 574static int compare_last_signature(struct fstab_rec *fstab, int *match) 575{ 576 char tag[METADATA_TAG_MAX_LENGTH + 1]; 577 int fd = -1; 578 int rc = -1; 579 off64_t offset = 0; 580 struct fec_handle *f = NULL; 581 struct fec_verity_metadata verity; 582 uint8_t curr[SHA256_DIGEST_LENGTH]; 583 uint8_t prev[SHA256_DIGEST_LENGTH]; 584 585 *match = 1; 586 587 if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE, 588 FEC_DEFAULT_ROOTS) == -1) { 589 PERROR << "Failed to open '" << fstab->blk_device << "'"; 590 return rc; 591 } 592 593 // read verity metadata 594 if (fec_verity_get_metadata(f, &verity) == -1) { 595 PERROR << "Failed to get verity metadata '" << fstab->blk_device << "'"; 596 goto out; 597 } 598 599 SHA256(verity.signature, sizeof(verity.signature), curr); 600 601 if (snprintf(tag, sizeof(tag), VERITY_LASTSIG_TAG "_%s", 602 basename(fstab->mount_point)) >= (int)sizeof(tag)) { 603 LERROR << "Metadata tag name too long for " << fstab->mount_point; 604 goto out; 605 } 606 607 if (metadata_find(fstab->verity_loc, tag, SHA256_DIGEST_LENGTH, 608 &offset) < 0) { 609 goto out; 610 } 611 612 fd = TEMP_FAILURE_RETRY(open(fstab->verity_loc, O_RDWR | O_SYNC | O_CLOEXEC)); 613 614 if (fd == -1) { 615 PERROR << "Failed to open " << fstab->verity_loc; 616 goto out; 617 } 618 619 if (TEMP_FAILURE_RETRY(pread64(fd, prev, sizeof(prev), 620 offset)) != sizeof(prev)) { 621 PERROR << "Failed to read " << sizeof(prev) << " bytes from " 622 << fstab->verity_loc << " offset " << offset; 623 goto out; 624 } 625 626 *match = !memcmp(curr, prev, SHA256_DIGEST_LENGTH); 627 628 if (!*match) { 629 /* update current signature hash */ 630 if (TEMP_FAILURE_RETRY(pwrite64(fd, curr, sizeof(curr), 631 offset)) != sizeof(curr)) { 632 PERROR << "Failed to write " << sizeof(curr) << " bytes to " 633 << fstab->verity_loc << " offset " << offset; 634 goto out; 635 } 636 } 637 638 rc = 0; 639 640out: 641 fec_close(f); 642 return rc; 643} 644 645static int get_verity_state_offset(struct fstab_rec *fstab, off64_t *offset) 646{ 647 char tag[METADATA_TAG_MAX_LENGTH + 1]; 648 649 if (snprintf(tag, sizeof(tag), VERITY_STATE_TAG "_%s", 650 basename(fstab->mount_point)) >= (int)sizeof(tag)) { 651 LERROR << "Metadata tag name too long for " << fstab->mount_point; 652 return -1; 653 } 654 655 return metadata_find(fstab->verity_loc, tag, sizeof(struct verity_state), 656 offset); 657} 658 659static int load_verity_state(struct fstab_rec *fstab, int *mode) 660{ 661 char propbuf[PROPERTY_VALUE_MAX]; 662 int match = 0; 663 off64_t offset = 0; 664 665 /* unless otherwise specified, use EIO mode */ 666 *mode = VERITY_MODE_EIO; 667 668 /* use the kernel parameter if set */ 669 property_get("ro.boot.veritymode", propbuf, ""); 670 671 if (*propbuf != '\0') { 672 if (!strcmp(propbuf, "enforcing")) { 673 *mode = VERITY_MODE_DEFAULT; 674 } 675 return 0; 676 } 677 678 if (get_verity_state_offset(fstab, &offset) < 0) { 679 /* fall back to stateless behavior */ 680 return 0; 681 } 682 683 if (was_verity_restart()) { 684 /* device was restarted after dm-verity detected a corrupted 685 * block, so use EIO mode */ 686 return write_verity_state(fstab->verity_loc, offset, *mode); 687 } 688 689 if (!compare_last_signature(fstab, &match) && !match) { 690 /* partition has been reflashed, reset dm-verity state */ 691 *mode = VERITY_MODE_DEFAULT; 692 return write_verity_state(fstab->verity_loc, offset, *mode); 693 } 694 695 return read_verity_state(fstab->verity_loc, offset, mode); 696} 697 698int fs_mgr_load_verity_state(int *mode) 699{ 700 char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; 701 char propbuf[PROPERTY_VALUE_MAX]; 702 int rc = -1; 703 int i; 704 int current; 705 struct fstab *fstab = NULL; 706 707 /* return the default mode, unless any of the verified partitions are in 708 * logging mode, in which case return that */ 709 *mode = VERITY_MODE_DEFAULT; 710 711 property_get("ro.hardware", propbuf, ""); 712 snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); 713 714 fstab = fs_mgr_read_fstab(fstab_filename); 715 716 if (!fstab) { 717 LERROR << "Failed to read " << fstab_filename; 718 goto out; 719 } 720 721 for (i = 0; i < fstab->num_entries; i++) { 722 if (!fs_mgr_is_verified(&fstab->recs[i])) { 723 continue; 724 } 725 726 rc = load_verity_state(&fstab->recs[i], ¤t); 727 if (rc < 0) { 728 continue; 729 } 730 731 if (current != VERITY_MODE_DEFAULT) { 732 *mode = current; 733 break; 734 } 735 } 736 737 rc = 0; 738 739out: 740 if (fstab) { 741 fs_mgr_free_fstab(fstab); 742 } 743 744 return rc; 745} 746 747int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) 748{ 749 alignas(dm_ioctl) char buffer[DM_BUF_SIZE]; 750 bool system_root = false; 751 char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; 752 std::string mount_point; 753 char propbuf[PROPERTY_VALUE_MAX]; 754 const char *status; 755 int fd = -1; 756 int i; 757 int mode; 758 int rc = -1; 759 struct dm_ioctl *io = (struct dm_ioctl *) buffer; 760 struct fstab *fstab = NULL; 761 762 if (!callback) { 763 return -1; 764 } 765 766 if (fs_mgr_load_verity_state(&mode) == -1) { 767 return -1; 768 } 769 770 fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)); 771 772 if (fd == -1) { 773 PERROR << "Error opening device mapper"; 774 goto out; 775 } 776 777 property_get("ro.hardware", propbuf, ""); 778 snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); 779 780 property_get("ro.build.system_root_image", propbuf, ""); 781 system_root = !strcmp(propbuf, "true"); 782 783 fstab = fs_mgr_read_fstab(fstab_filename); 784 785 if (!fstab) { 786 LERROR << "Failed to read " << fstab_filename; 787 goto out; 788 } 789 790 for (i = 0; i < fstab->num_entries; i++) { 791 if (!fs_mgr_is_verified(&fstab->recs[i])) { 792 continue; 793 } 794 795 if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) { 796 mount_point = "system"; 797 } else { 798 mount_point = basename(fstab->recs[i].mount_point); 799 } 800 801 fs_mgr_verity_ioctl_init(io, mount_point, 0); 802 803 if (ioctl(fd, DM_TABLE_STATUS, io)) { 804 if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) { 805 status = "V"; 806 } else { 807 PERROR << "Failed to query DM_TABLE_STATUS for " 808 << mount_point.c_str(); 809 continue; 810 } 811 } 812 813 status = &buffer[io->data_start + sizeof(struct dm_target_spec)]; 814 815 if (*status == 'C' || *status == 'V') { 816 callback(&fstab->recs[i], mount_point.c_str(), mode, *status); 817 } 818 } 819 820 rc = 0; 821 822out: 823 if (fstab) { 824 fs_mgr_free_fstab(fstab); 825 } 826 827 if (fd) { 828 close(fd); 829 } 830 831 return rc; 832} 833 834static void update_verity_table_blk_device(char *blk_device, char **table) 835{ 836 std::string result, word; 837 auto tokens = android::base::Split(*table, " "); 838 839 for (const auto& token : tokens) { 840 if (android::base::StartsWith(token, "/dev/block/") && 841 android::base::StartsWith(blk_device, token.c_str())) { 842 word = blk_device; 843 } else { 844 word = token; 845 } 846 847 if (result.empty()) { 848 result = word; 849 } else { 850 result += " " + word; 851 } 852 } 853 854 if (result.empty()) { 855 return; 856 } 857 858 free(*table); 859 *table = strdup(result.c_str()); 860} 861 862int fs_mgr_setup_verity(struct fstab_rec *fstab, bool verify_dev) 863{ 864 int retval = FS_MGR_SETUP_VERITY_FAIL; 865 int fd = -1; 866 std::string verity_blk_name; 867 struct fec_handle *f = NULL; 868 struct fec_verity_metadata verity; 869 struct verity_table_params params = { .table = NULL }; 870 871 alignas(dm_ioctl) char buffer[DM_BUF_SIZE]; 872 struct dm_ioctl *io = (struct dm_ioctl *) buffer; 873 const std::string mount_point(basename(fstab->mount_point)); 874 bool verified_at_boot = false; 875 876 if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE, 877 FEC_DEFAULT_ROOTS) < 0) { 878 PERROR << "Failed to open '" << fstab->blk_device << "'"; 879 return retval; 880 } 881 882 // read verity metadata 883 if (fec_verity_get_metadata(f, &verity) < 0) { 884 PERROR << "Failed to get verity metadata '" << fstab->blk_device << "'"; 885 goto out; 886 } 887 888#ifdef ALLOW_ADBD_DISABLE_VERITY 889 if (verity.disabled) { 890 retval = FS_MGR_SETUP_VERITY_DISABLED; 891 LINFO << "Attempt to cleanly disable verity - only works in USERDEBUG"; 892 goto out; 893 } 894#endif 895 896 // read ecc metadata 897 if (fec_ecc_get_metadata(f, ¶ms.ecc) < 0) { 898 params.ecc.valid = false; 899 } 900 901 params.ecc_dev = fstab->blk_device; 902 903 // get the device mapper fd 904 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { 905 PERROR << "Error opening device mapper"; 906 goto out; 907 } 908 909 // create the device 910 if (!fs_mgr_create_verity_device(io, mount_point, fd)) { 911 LERROR << "Couldn't create verity device!"; 912 goto out; 913 } 914 915 // get the name of the device file 916 if (!fs_mgr_get_verity_device_name(io, mount_point, fd, &verity_blk_name)) { 917 LERROR << "Couldn't get verity device number!"; 918 goto out; 919 } 920 921 if (load_verity_state(fstab, ¶ms.mode) < 0) { 922 /* if accessing or updating the state failed, switch to the default 923 * safe mode. This makes sure the device won't end up in an endless 924 * restart loop, and no corrupted data will be exposed to userspace 925 * without a warning. */ 926 params.mode = VERITY_MODE_EIO; 927 } 928 929 if (!verity.table) { 930 goto out; 931 } 932 933 params.table = strdup(verity.table); 934 if (!params.table) { 935 goto out; 936 } 937 938 // verify the signature on the table 939 if (verify_verity_signature(verity) < 0) { 940 if (params.mode == VERITY_MODE_LOGGING) { 941 // the user has been warned, allow mounting without dm-verity 942 retval = FS_MGR_SETUP_VERITY_SUCCESS; 943 goto out; 944 } 945 946 // invalidate root hash and salt to trigger device-specific recovery 947 if (invalidate_table(params.table, verity.table_length) < 0) { 948 goto out; 949 } 950 } 951 952 LINFO << "Enabling dm-verity for " << mount_point.c_str() 953 << " (mode " << params.mode << ")"; 954 955 if (fstab->fs_mgr_flags & MF_SLOTSELECT) { 956 // Update the verity params using the actual block device path 957 update_verity_table_blk_device(fstab->blk_device, ¶ms.table); 958 } 959 960 // load the verity mapping table 961 if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms, 962 format_verity_table) == 0) { 963 goto loaded; 964 } 965 966 if (params.ecc.valid) { 967 // kernel may not support error correction, try without 968 LINFO << "Disabling error correction for " << mount_point.c_str(); 969 params.ecc.valid = false; 970 971 if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms, 972 format_verity_table) == 0) { 973 goto loaded; 974 } 975 } 976 977 // try the legacy format for backwards compatibility 978 if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms, 979 format_legacy_verity_table) == 0) { 980 goto loaded; 981 } 982 983 if (params.mode != VERITY_MODE_EIO) { 984 // as a last resort, EIO mode should always be supported 985 LINFO << "Falling back to EIO mode for " << mount_point.c_str(); 986 params.mode = VERITY_MODE_EIO; 987 988 if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms, 989 format_legacy_verity_table) == 0) { 990 goto loaded; 991 } 992 } 993 994 LERROR << "Failed to load verity table for " << mount_point.c_str(); 995 goto out; 996 997loaded: 998 999 // activate the device 1000 if (!fs_mgr_resume_verity_table(io, mount_point, fd)) { 1001 goto out; 1002 } 1003 1004 // mark the underlying block device as read-only 1005 fs_mgr_set_blk_ro(fstab->blk_device); 1006 1007 // Verify the entire partition in one go 1008 // If there is an error, allow it to mount as a normal verity partition. 1009 if (fstab->fs_mgr_flags & MF_VERIFYATBOOT) { 1010 LINFO << "Verifying partition " << fstab->blk_device << " at boot"; 1011 int err = read_partition(verity_blk_name.c_str(), verity.data_size); 1012 if (!err) { 1013 LINFO << "Verified verity partition " 1014 << fstab->blk_device << " at boot"; 1015 verified_at_boot = true; 1016 } 1017 } 1018 1019 // assign the new verity block device as the block device 1020 if (!verified_at_boot) { 1021 free(fstab->blk_device); 1022 fstab->blk_device = strdup(verity_blk_name.c_str()); 1023 } else if (!fs_mgr_destroy_verity_device(io, mount_point, fd)) { 1024 LERROR << "Failed to remove verity device " << mount_point.c_str(); 1025 goto out; 1026 } 1027 1028 // make sure we've set everything up properly 1029 if (verify_dev && fs_mgr_test_access(fstab->blk_device) < 0) { 1030 goto out; 1031 } 1032 1033 retval = FS_MGR_SETUP_VERITY_SUCCESS; 1034 1035out: 1036 if (fd != -1) { 1037 close(fd); 1038 } 1039 1040 fec_close(f); 1041 free(params.table); 1042 1043 return retval; 1044} 1045