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