fs_mgr_verity.c revision a88fb24ab43eec9710a0d4d15aedb6d4bc51a2ec
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 VERITY_STATE_HEADER 0x83c0ae9d 51#define VERITY_STATE_VERSION 1 52 53#define VERITY_KMSG_RESTART "dm-verity device corrupted" 54#define VERITY_KMSG_BUFSIZE 1024 55 56struct verity_state { 57 uint32_t header; 58 uint32_t version; 59 uint32_t size; 60 int32_t mode; 61}; 62 63extern struct fs_info info; 64 65static RSAPublicKey *load_key(char *path) 66{ 67 FILE *f; 68 RSAPublicKey *key; 69 70 key = malloc(sizeof(RSAPublicKey)); 71 if (!key) { 72 ERROR("Can't malloc key\n"); 73 return NULL; 74 } 75 76 f = fopen(path, "r"); 77 if (!f) { 78 ERROR("Can't open '%s'\n", path); 79 free(key); 80 return NULL; 81 } 82 83 if (!fread(key, sizeof(*key), 1, f)) { 84 ERROR("Could not read key!"); 85 fclose(f); 86 free(key); 87 return NULL; 88 } 89 90 if (key->len != RSANUMWORDS) { 91 ERROR("Invalid key length %d\n", key->len); 92 fclose(f); 93 free(key); 94 return NULL; 95 } 96 97 fclose(f); 98 return key; 99} 100 101static int verify_table(char *signature, char *table, int table_length) 102{ 103 RSAPublicKey *key; 104 uint8_t hash_buf[SHA_DIGEST_SIZE]; 105 int retval = -1; 106 107 // Hash the table 108 SHA_hash((uint8_t*)table, table_length, hash_buf); 109 110 // Now get the public key from the keyfile 111 key = load_key(VERITY_TABLE_RSA_KEY); 112 if (!key) { 113 ERROR("Couldn't load verity keys"); 114 goto out; 115 } 116 117 // verify the result 118 if (!RSA_verify(key, 119 (uint8_t*) signature, 120 RSANUMBYTES, 121 (uint8_t*) hash_buf, 122 SHA_DIGEST_SIZE)) { 123 ERROR("Couldn't verify table."); 124 goto out; 125 } 126 127 retval = 0; 128 129out: 130 free(key); 131 return retval; 132} 133 134static int get_target_device_size(char *blk_device, uint64_t *device_size) 135{ 136 int data_device; 137 struct ext4_super_block sb; 138 struct fs_info info; 139 140 info.len = 0; /* Only len is set to 0 to ask the device for real size. */ 141 142 data_device = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC)); 143 if (data_device == -1) { 144 ERROR("Error opening block device (%s)", strerror(errno)); 145 return -1; 146 } 147 148 if (TEMP_FAILURE_RETRY(lseek64(data_device, 1024, SEEK_SET)) < 0) { 149 ERROR("Error seeking to superblock"); 150 TEMP_FAILURE_RETRY(close(data_device)); 151 return -1; 152 } 153 154 if (TEMP_FAILURE_RETRY(read(data_device, &sb, sizeof(sb))) != sizeof(sb)) { 155 ERROR("Error reading superblock"); 156 TEMP_FAILURE_RETRY(close(data_device)); 157 return -1; 158 } 159 160 ext4_parse_sb(&sb, &info); 161 *device_size = info.len; 162 163 TEMP_FAILURE_RETRY(close(data_device)); 164 return 0; 165} 166 167static int read_verity_metadata(char *block_device, char **signature, char **table) 168{ 169 unsigned magic_number; 170 unsigned table_length; 171 uint64_t device_length; 172 int protocol_version; 173 int device; 174 int retval = FS_MGR_SETUP_VERITY_FAIL; 175 *signature = 0; 176 *table = 0; 177 178 device = TEMP_FAILURE_RETRY(open(block_device, O_RDONLY | O_CLOEXEC)); 179 if (device == -1) { 180 ERROR("Could not open block device %s (%s).\n", block_device, strerror(errno)); 181 goto out; 182 } 183 184 // find the start of the verity metadata 185 if (get_target_device_size(block_device, &device_length) < 0) { 186 ERROR("Could not get target device size.\n"); 187 goto out; 188 } 189 if (TEMP_FAILURE_RETRY(lseek64(device, device_length, SEEK_SET)) < 0) { 190 ERROR("Could not seek to start of verity metadata block.\n"); 191 goto out; 192 } 193 194 // check the magic number 195 if (TEMP_FAILURE_RETRY(read(device, &magic_number, sizeof(magic_number))) != 196 sizeof(magic_number)) { 197 ERROR("Couldn't read magic number!\n"); 198 goto out; 199 } 200 201#ifdef ALLOW_ADBD_DISABLE_VERITY 202 if (magic_number == VERITY_METADATA_MAGIC_DISABLE) { 203 retval = FS_MGR_SETUP_VERITY_DISABLED; 204 INFO("Attempt to cleanly disable verity - only works in USERDEBUG"); 205 goto out; 206 } 207#endif 208 209 if (magic_number != VERITY_METADATA_MAGIC_NUMBER) { 210 ERROR("Couldn't find verity metadata at offset %"PRIu64"!\n", 211 device_length); 212 goto out; 213 } 214 215 // check the protocol version 216 if (TEMP_FAILURE_RETRY(read(device, &protocol_version, 217 sizeof(protocol_version))) != sizeof(protocol_version)) { 218 ERROR("Couldn't read verity metadata protocol version!\n"); 219 goto out; 220 } 221 if (protocol_version != 0) { 222 ERROR("Got unknown verity metadata protocol version %d!\n", protocol_version); 223 goto out; 224 } 225 226 // get the signature 227 *signature = (char*) malloc(RSANUMBYTES); 228 if (!*signature) { 229 ERROR("Couldn't allocate memory for signature!\n"); 230 goto out; 231 } 232 if (TEMP_FAILURE_RETRY(read(device, *signature, RSANUMBYTES)) != RSANUMBYTES) { 233 ERROR("Couldn't read signature from verity metadata!\n"); 234 goto out; 235 } 236 237 // get the size of the table 238 if (TEMP_FAILURE_RETRY(read(device, &table_length, sizeof(table_length))) != 239 sizeof(table_length)) { 240 ERROR("Couldn't get the size of the verity table from metadata!\n"); 241 goto out; 242 } 243 244 // get the table + null terminator 245 *table = malloc(table_length + 1); 246 if (!*table) { 247 ERROR("Couldn't allocate memory for verity table!\n"); 248 goto out; 249 } 250 if (TEMP_FAILURE_RETRY(read(device, *table, table_length)) != 251 (ssize_t)table_length) { 252 ERROR("Couldn't read the verity table from metadata!\n"); 253 goto out; 254 } 255 256 (*table)[table_length] = 0; 257 retval = FS_MGR_SETUP_VERITY_SUCCESS; 258 259out: 260 if (device != -1) 261 TEMP_FAILURE_RETRY(close(device)); 262 263 if (retval != FS_MGR_SETUP_VERITY_SUCCESS) { 264 free(*table); 265 free(*signature); 266 *table = 0; 267 *signature = 0; 268 } 269 270 return retval; 271} 272 273static void verity_ioctl_init(struct dm_ioctl *io, char *name, unsigned flags) 274{ 275 memset(io, 0, DM_BUF_SIZE); 276 io->data_size = DM_BUF_SIZE; 277 io->data_start = sizeof(struct dm_ioctl); 278 io->version[0] = 4; 279 io->version[1] = 0; 280 io->version[2] = 0; 281 io->flags = flags | DM_READONLY_FLAG; 282 if (name) { 283 strlcpy(io->name, name, sizeof(io->name)); 284 } 285} 286 287static int create_verity_device(struct dm_ioctl *io, char *name, int fd) 288{ 289 verity_ioctl_init(io, name, 1); 290 if (ioctl(fd, DM_DEV_CREATE, io)) { 291 ERROR("Error creating device mapping (%s)", strerror(errno)); 292 return -1; 293 } 294 return 0; 295} 296 297static int get_verity_device_name(struct dm_ioctl *io, char *name, int fd, char **dev_name) 298{ 299 verity_ioctl_init(io, name, 0); 300 if (ioctl(fd, DM_DEV_STATUS, io)) { 301 ERROR("Error fetching verity device number (%s)", strerror(errno)); 302 return -1; 303 } 304 int dev_num = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); 305 if (asprintf(dev_name, "/dev/block/dm-%u", dev_num) < 0) { 306 ERROR("Error getting verity block device name (%s)", strerror(errno)); 307 return -1; 308 } 309 return 0; 310} 311 312static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, int fd, char *table, 313 int mode) 314{ 315 char *verity_params; 316 char *buffer = (char*) io; 317 size_t bufsize; 318 uint64_t device_size = 0; 319 320 if (get_target_device_size(blockdev, &device_size) < 0) { 321 return -1; 322 } 323 324 verity_ioctl_init(io, name, DM_STATUS_TABLE_FLAG); 325 326 struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)]; 327 328 // set tgt arguments here 329 io->target_count = 1; 330 tgt->status=0; 331 tgt->sector_start=0; 332 tgt->length=device_size/512; 333 strcpy(tgt->target_type, "verity"); 334 335 // build the verity params here 336 verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); 337 bufsize = DM_BUF_SIZE - (verity_params - buffer); 338 339 if (mode == VERITY_MODE_EIO) { 340 // allow operation with older dm-verity drivers that are unaware 341 // of the mode parameter by omitting it; this also means that we 342 // cannot use logging mode with these drivers, they always cause 343 // an I/O error for corrupted blocks 344 strcpy(verity_params, table); 345 } else if (snprintf(verity_params, bufsize, "%s %d", table, mode) < 0) { 346 return -1; 347 } 348 349 // set next target boundary 350 verity_params += strlen(verity_params) + 1; 351 verity_params = (char*) (((unsigned long)verity_params + 7) & ~8); 352 tgt->next = verity_params - buffer; 353 354 // send the ioctl to load the verity table 355 if (ioctl(fd, DM_TABLE_LOAD, io)) { 356 ERROR("Error loading verity table (%s)", strerror(errno)); 357 return -1; 358 } 359 360 return 0; 361} 362 363static int resume_verity_table(struct dm_ioctl *io, char *name, int fd) 364{ 365 verity_ioctl_init(io, name, 0); 366 if (ioctl(fd, DM_DEV_SUSPEND, io)) { 367 ERROR("Error activating verity device (%s)", strerror(errno)); 368 return -1; 369 } 370 return 0; 371} 372 373static int test_access(char *device) { 374 int tries = 25; 375 while (tries--) { 376 if (!access(device, F_OK) || errno != ENOENT) { 377 return 0; 378 } 379 usleep(40 * 1000); 380 } 381 return -1; 382} 383 384static int set_verified_property(char *name) { 385 int ret; 386 char *key; 387 ret = asprintf(&key, "partition.%s.verified", name); 388 if (ret < 0) { 389 ERROR("Error formatting verified property\n"); 390 return ret; 391 } 392 ret = PROP_NAME_MAX - strlen(key); 393 if (ret < 0) { 394 ERROR("Verified property name is too long\n"); 395 free(key); 396 return -1; 397 } 398 ret = property_set(key, "1"); 399 if (ret < 0) 400 ERROR("Error setting verified property %s: %d\n", key, ret); 401 free(key); 402 return ret; 403} 404 405static int check_verity_restart(const char *fname) 406{ 407 char buffer[VERITY_KMSG_BUFSIZE + 1]; 408 int fd; 409 int rc = 0; 410 ssize_t size; 411 struct stat s; 412 413 fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC)); 414 415 if (fd == -1) { 416 if (errno != ENOENT) { 417 ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); 418 } 419 goto out; 420 } 421 422 if (fstat(fd, &s) == -1) { 423 ERROR("Failed to fstat %s (%s)\n", fname, strerror(errno)); 424 goto out; 425 } 426 427 size = VERITY_KMSG_BUFSIZE; 428 429 if (size > s.st_size) { 430 size = s.st_size; 431 } 432 433 if (lseek(fd, s.st_size - size, SEEK_SET) == -1) { 434 ERROR("Failed to lseek %zu %s (%s)\n", s.st_size - size, fname, 435 strerror(errno)); 436 goto out; 437 } 438 439 if (TEMP_FAILURE_RETRY(read(fd, buffer, size)) != size) { 440 ERROR("Failed to read %zd bytes from %s (%s)\n", size, fname, 441 strerror(errno)); 442 goto out; 443 } 444 445 buffer[size] = '\0'; 446 447 if (strstr(buffer, VERITY_KMSG_RESTART) != NULL) { 448 rc = 1; 449 } 450 451out: 452 if (fd != -1) { 453 TEMP_FAILURE_RETRY(close(fd)); 454 } 455 456 return rc; 457} 458 459static int was_verity_restart() 460{ 461 static const char *files[] = { 462 "/sys/fs/pstore/console-ramoops", 463 "/proc/last_kmsg", 464 NULL 465 }; 466 int i; 467 468 for (i = 0; files[i]; ++i) { 469 if (check_verity_restart(files[i])) { 470 return 1; 471 } 472 } 473 474 return 0; 475} 476 477static int write_verity_state(const char *fname, off64_t offset, int32_t mode) 478{ 479 int fd; 480 int rc = -1; 481 482 struct verity_state s = { 483 VERITY_STATE_HEADER, 484 VERITY_STATE_VERSION, 485 sizeof(struct verity_state), 486 mode 487 }; 488 489 fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC)); 490 491 if (fd == -1) { 492 ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); 493 goto out; 494 } 495 496 if (TEMP_FAILURE_RETRY(lseek64(fd, offset, SEEK_SET)) < 0) { 497 ERROR("Failed to seek %s to %" PRIu64 " (%s)\n", fname, offset, strerror(errno)); 498 goto out; 499 } 500 501 if (TEMP_FAILURE_RETRY(write(fd, &s, sizeof(s))) != sizeof(s)) { 502 ERROR("Failed to write %zu bytes to %s (%s)\n", sizeof(s), fname, strerror(errno)); 503 goto out; 504 } 505 506 rc = 0; 507 508out: 509 if (fd != -1) { 510 TEMP_FAILURE_RETRY(close(fd)); 511 } 512 513 return rc; 514} 515 516static int get_verity_state_location(char *location, off64_t *offset) 517{ 518 char state_off[PROPERTY_VALUE_MAX]; 519 520 if (property_get("ro.verity.state.location", location, NULL) <= 0) { 521 return -1; 522 } 523 524 if (*location != '/' || access(location, R_OK | W_OK) == -1) { 525 ERROR("Failed to access verity state %s (%s)\n", location, strerror(errno)); 526 return -1; 527 } 528 529 *offset = 0; 530 531 if (property_get("ro.verity.state.offset", state_off, NULL) > 0) { 532 *offset = strtoll(state_off, NULL, 0); 533 534 if (errno == ERANGE || errno == EINVAL) { 535 ERROR("Invalid value in ro.verity.state.offset (%s)\n", state_off); 536 return -1; 537 } 538 } 539 540 return 0; 541} 542 543int fs_mgr_load_verity_state(int *mode) 544{ 545 char fname[PROPERTY_VALUE_MAX]; 546 int fd = -1; 547 int rc = -1; 548 off64_t offset = 0; 549 struct verity_state s; 550 551 if (get_verity_state_location(fname, &offset) < 0) { 552 /* location for dm-verity state is not specified, fall back to 553 * default behavior: return -EIO for corrupted blocks */ 554 *mode = VERITY_MODE_EIO; 555 rc = 0; 556 goto out; 557 } 558 559 if (was_verity_restart()) { 560 /* device was restarted after dm-verity detected a corrupted 561 * block, so switch to logging mode */ 562 *mode = VERITY_MODE_LOGGING; 563 rc = write_verity_state(fname, offset, *mode); 564 goto out; 565 } 566 567 fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC)); 568 569 if (fd == -1) { 570 ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); 571 goto out; 572 } 573 574 if (TEMP_FAILURE_RETRY(lseek64(fd, offset, SEEK_SET)) < 0) { 575 ERROR("Failed to seek %s to %" PRIu64 " (%s)\n", fname, offset, strerror(errno)); 576 goto out; 577 } 578 579 if (TEMP_FAILURE_RETRY(read(fd, &s, sizeof(s))) != sizeof(s)) { 580 ERROR("Failed to read %zu bytes from %s (%s)\n", sizeof(s), fname, strerror(errno)); 581 goto out; 582 } 583 584 if (s.header != VERITY_STATE_HEADER) { 585 goto out; 586 } 587 588 if (s.version != VERITY_STATE_VERSION) { 589 ERROR("Unsupported verity state version (%u)\n", s.version); 590 goto out; 591 } 592 593 if (s.size != sizeof(s)) { 594 ERROR("Unexpected verity state size (%u)\n", s.size); 595 goto out; 596 } 597 598 if (s.mode < VERITY_MODE_EIO || 599 s.mode > VERITY_MODE_LAST) { 600 ERROR("Unsupported verity mode (%u)\n", s.mode); 601 goto out; 602 } 603 604 *mode = s.mode; 605 rc = 0; 606 607out: 608 if (fd != -1) { 609 TEMP_FAILURE_RETRY(close(fd)); 610 } 611 612 return rc; 613} 614 615int fs_mgr_update_verity_state() 616{ 617 _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE]; 618 char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; 619 char *mount_point; 620 char propbuf[PROPERTY_VALUE_MAX]; 621 char state_loc[PROPERTY_VALUE_MAX]; 622 char *status; 623 int fd = -1; 624 int i; 625 int rc = -1; 626 off64_t offset = 0; 627 struct dm_ioctl *io = (struct dm_ioctl *) buffer; 628 struct fstab *fstab = NULL; 629 630 if (get_verity_state_location(state_loc, &offset) < 0) { 631 goto out; 632 } 633 634 fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)); 635 636 if (fd == -1) { 637 ERROR("Error opening device mapper (%s)\n", strerror(errno)); 638 goto out; 639 } 640 641 property_get("ro.hardware", propbuf, ""); 642 snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); 643 644 fstab = fs_mgr_read_fstab(fstab_filename); 645 646 if (!fstab) { 647 ERROR("Failed to read %s\n", fstab_filename); 648 goto out; 649 } 650 651 for (i = 0; i < fstab->num_entries; i++) { 652 if (!fs_mgr_is_verified(&fstab->recs[i])) { 653 continue; 654 } 655 656 mount_point = basename(fstab->recs[i].mount_point); 657 verity_ioctl_init(io, mount_point, 0); 658 659 if (ioctl(fd, DM_TABLE_STATUS, io)) { 660 ERROR("Failed to query DM_TABLE_STATUS for %s (%s)\n", mount_point, 661 strerror(errno)); 662 goto out; 663 } 664 665 status = &buffer[io->data_start + sizeof(struct dm_target_spec)]; 666 667 if (*status == 'C') { 668 rc = write_verity_state(state_loc, offset, VERITY_MODE_LOGGING); 669 goto out; 670 } 671 } 672 673 /* Don't overwrite possible previous state if there's no corruption. */ 674 rc = 0; 675 676out: 677 if (fstab) { 678 fs_mgr_free_fstab(fstab); 679 } 680 681 if (fd) { 682 TEMP_FAILURE_RETRY(close(fd)); 683 } 684 685 return rc; 686} 687 688int fs_mgr_setup_verity(struct fstab_rec *fstab) { 689 690 int retval = FS_MGR_SETUP_VERITY_FAIL; 691 int fd = -1; 692 int mode; 693 694 char *verity_blk_name = 0; 695 char *verity_table = 0; 696 char *verity_table_signature = 0; 697 698 _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE]; 699 struct dm_ioctl *io = (struct dm_ioctl *) buffer; 700 char *mount_point = basename(fstab->mount_point); 701 702 // set the dm_ioctl flags 703 io->flags |= 1; 704 io->target_count = 1; 705 706 // check to ensure that the verity device is ext4 707 // TODO: support non-ext4 filesystems 708 if (strcmp(fstab->fs_type, "ext4")) { 709 ERROR("Cannot verify non-ext4 device (%s)", fstab->fs_type); 710 return retval; 711 } 712 713 // read the verity block at the end of the block device 714 // send error code up the chain so we can detect attempts to disable verity 715 retval = read_verity_metadata(fstab->blk_device, 716 &verity_table_signature, 717 &verity_table); 718 if (retval < 0) { 719 goto out; 720 } 721 722 retval = FS_MGR_SETUP_VERITY_FAIL; 723 724 // get the device mapper fd 725 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { 726 ERROR("Error opening device mapper (%s)", strerror(errno)); 727 goto out; 728 } 729 730 // create the device 731 if (create_verity_device(io, mount_point, fd) < 0) { 732 ERROR("Couldn't create verity device!"); 733 goto out; 734 } 735 736 // get the name of the device file 737 if (get_verity_device_name(io, mount_point, fd, &verity_blk_name) < 0) { 738 ERROR("Couldn't get verity device number!"); 739 goto out; 740 } 741 742 // verify the signature on the table 743 if (verify_table(verity_table_signature, 744 verity_table, 745 strlen(verity_table)) < 0) { 746 goto out; 747 } 748 749 if (fs_mgr_load_verity_state(&mode) < 0) { 750 mode = VERITY_MODE_RESTART; /* default dm-verity mode */ 751 } 752 753 // load the verity mapping table 754 if (load_verity_table(io, mount_point, fstab->blk_device, fd, verity_table, 755 mode) < 0) { 756 goto out; 757 } 758 759 // activate the device 760 if (resume_verity_table(io, mount_point, fd) < 0) { 761 goto out; 762 } 763 764 // mark the underlying block device as read-only 765 fs_mgr_set_blk_ro(fstab->blk_device); 766 767 // assign the new verity block device as the block device 768 free(fstab->blk_device); 769 fstab->blk_device = verity_blk_name; 770 verity_blk_name = 0; 771 772 // make sure we've set everything up properly 773 if (test_access(fstab->blk_device) < 0) { 774 goto out; 775 } 776 777 if (mode == VERITY_MODE_LOGGING) { 778 retval = FS_MGR_SETUP_VERITY_SUCCESS; 779 } else { 780 // set the property indicating that the partition is verified 781 retval = set_verified_property(mount_point); 782 } 783 784out: 785 if (fd != -1) { 786 close(fd); 787 } 788 789 free(verity_table); 790 free(verity_table_signature); 791 free(verity_blk_name); 792 793 return retval; 794} 795