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