fs_mgr.c revision bfa7d0822b2811d667fba1b326fd54a083fd5a95
1/* 2 * Copyright (C) 2012 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 <stdio.h> 18#include <stdlib.h> 19#include <string.h> 20#include <unistd.h> 21#include <fcntl.h> 22#include <ctype.h> 23#include <sys/mount.h> 24#include <sys/stat.h> 25#include <errno.h> 26#include <sys/types.h> 27#include <sys/wait.h> 28#include <libgen.h> 29#include <time.h> 30#include <sys/swap.h> 31 32#include <linux/loop.h> 33#include <private/android_filesystem_config.h> 34#include <cutils/partition_utils.h> 35#include <cutils/properties.h> 36#include <logwrap/logwrap.h> 37 38#include "mincrypt/rsa.h" 39#include "mincrypt/sha.h" 40#include "mincrypt/sha256.h" 41 42#include "fs_mgr_priv.h" 43#include "fs_mgr_priv_verity.h" 44 45#define KEY_LOC_PROP "ro.crypto.keyfile.userdata" 46#define KEY_IN_FOOTER "footer" 47 48#define E2FSCK_BIN "/system/bin/e2fsck" 49#define MKSWAP_BIN "/system/bin/mkswap" 50 51#define FSCK_LOG_FILE "/dev/fscklogs/log" 52 53#define ZRAM_CONF_DEV "/sys/block/zram0/disksize" 54 55#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) 56 57struct flag_list { 58 const char *name; 59 unsigned flag; 60}; 61 62static struct flag_list mount_flags[] = { 63 { "noatime", MS_NOATIME }, 64 { "noexec", MS_NOEXEC }, 65 { "nosuid", MS_NOSUID }, 66 { "nodev", MS_NODEV }, 67 { "nodiratime", MS_NODIRATIME }, 68 { "ro", MS_RDONLY }, 69 { "rw", 0 }, 70 { "remount", MS_REMOUNT }, 71 { "bind", MS_BIND }, 72 { "rec", MS_REC }, 73 { "unbindable", MS_UNBINDABLE }, 74 { "private", MS_PRIVATE }, 75 { "slave", MS_SLAVE }, 76 { "shared", MS_SHARED }, 77 { "defaults", 0 }, 78 { 0, 0 }, 79}; 80 81static struct flag_list fs_mgr_flags[] = { 82 { "wait", MF_WAIT }, 83 { "check", MF_CHECK }, 84 { "encryptable=",MF_CRYPT }, 85 { "nonremovable",MF_NONREMOVABLE }, 86 { "voldmanaged=",MF_VOLDMANAGED}, 87 { "length=", MF_LENGTH }, 88 { "recoveryonly",MF_RECOVERYONLY }, 89 { "swapprio=", MF_SWAPPRIO }, 90 { "zramsize=", MF_ZRAMSIZE }, 91 { "verify", MF_VERIFY }, 92 { "noemulatedsd", MF_NOEMULATEDSD }, 93 { "defaults", 0 }, 94 { 0, 0 }, 95}; 96 97struct fs_mgr_flag_values { 98 char *key_loc; 99 long long part_length; 100 char *label; 101 int partnum; 102 int swap_prio; 103 unsigned int zram_size; 104}; 105 106/* 107 * gettime() - returns the time in seconds of the system's monotonic clock or 108 * zero on error. 109 */ 110static time_t gettime(void) 111{ 112 struct timespec ts; 113 int ret; 114 115 ret = clock_gettime(CLOCK_MONOTONIC, &ts); 116 if (ret < 0) { 117 ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno)); 118 return 0; 119 } 120 121 return ts.tv_sec; 122} 123 124static int wait_for_file(const char *filename, int timeout) 125{ 126 struct stat info; 127 time_t timeout_time = gettime() + timeout; 128 int ret = -1; 129 130 while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0)) 131 usleep(10000); 132 133 return ret; 134} 135 136static int parse_flags(char *flags, struct flag_list *fl, 137 struct fs_mgr_flag_values *flag_vals, 138 char *fs_options, int fs_options_len) 139{ 140 int f = 0; 141 int i; 142 char *p; 143 char *savep; 144 145 /* initialize flag values. If we find a relevant flag, we'll 146 * update the value */ 147 if (flag_vals) { 148 memset(flag_vals, 0, sizeof(*flag_vals)); 149 flag_vals->partnum = -1; 150 flag_vals->swap_prio = -1; /* negative means it wasn't specified. */ 151 } 152 153 /* initialize fs_options to the null string */ 154 if (fs_options && (fs_options_len > 0)) { 155 fs_options[0] = '\0'; 156 } 157 158 p = strtok_r(flags, ",", &savep); 159 while (p) { 160 /* Look for the flag "p" in the flag list "fl" 161 * If not found, the loop exits with fl[i].name being null. 162 */ 163 for (i = 0; fl[i].name; i++) { 164 if (!strncmp(p, fl[i].name, strlen(fl[i].name))) { 165 f |= fl[i].flag; 166 if ((fl[i].flag == MF_CRYPT) && flag_vals) { 167 /* The encryptable flag is followed by an = and the 168 * location of the keys. Get it and return it. 169 */ 170 flag_vals->key_loc = strdup(strchr(p, '=') + 1); 171 } else if ((fl[i].flag == MF_LENGTH) && flag_vals) { 172 /* The length flag is followed by an = and the 173 * size of the partition. Get it and return it. 174 */ 175 flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0); 176 } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) { 177 /* The voldmanaged flag is followed by an = and the 178 * label, a colon and the partition number or the 179 * word "auto", e.g. 180 * voldmanaged=sdcard:3 181 * Get and return them. 182 */ 183 char *label_start; 184 char *label_end; 185 char *part_start; 186 187 label_start = strchr(p, '=') + 1; 188 label_end = strchr(p, ':'); 189 if (label_end) { 190 flag_vals->label = strndup(label_start, 191 (int) (label_end - label_start)); 192 part_start = strchr(p, ':') + 1; 193 if (!strcmp(part_start, "auto")) { 194 flag_vals->partnum = -1; 195 } else { 196 flag_vals->partnum = strtol(part_start, NULL, 0); 197 } 198 } else { 199 ERROR("Warning: voldmanaged= flag malformed\n"); 200 } 201 } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) { 202 flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0); 203 } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) { 204 flag_vals->zram_size = strtoll(strchr(p, '=') + 1, NULL, 0); 205 } 206 break; 207 } 208 } 209 210 if (!fl[i].name) { 211 if (fs_options) { 212 /* It's not a known flag, so it must be a filesystem specific 213 * option. Add it to fs_options if it was passed in. 214 */ 215 strlcat(fs_options, p, fs_options_len); 216 strlcat(fs_options, ",", fs_options_len); 217 } else { 218 /* fs_options was not passed in, so if the flag is unknown 219 * it's an error. 220 */ 221 ERROR("Warning: unknown flag %s\n", p); 222 } 223 } 224 p = strtok_r(NULL, ",", &savep); 225 } 226 227out: 228 if (fs_options && fs_options[0]) { 229 /* remove the last trailing comma from the list of options */ 230 fs_options[strlen(fs_options) - 1] = '\0'; 231 } 232 233 return f; 234} 235 236struct fstab *fs_mgr_read_fstab(const char *fstab_path) 237{ 238 FILE *fstab_file; 239 int cnt, entries; 240 ssize_t len; 241 size_t alloc_len = 0; 242 char *line = NULL; 243 const char *delim = " \t"; 244 char *save_ptr, *p; 245 struct fstab *fstab = NULL; 246 struct fstab_rec *recs; 247 struct fs_mgr_flag_values flag_vals; 248#define FS_OPTIONS_LEN 1024 249 char tmp_fs_options[FS_OPTIONS_LEN]; 250 251 fstab_file = fopen(fstab_path, "r"); 252 if (!fstab_file) { 253 ERROR("Cannot open file %s\n", fstab_path); 254 return 0; 255 } 256 257 entries = 0; 258 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) { 259 /* if the last character is a newline, shorten the string by 1 byte */ 260 if (line[len - 1] == '\n') { 261 line[len - 1] = '\0'; 262 } 263 /* Skip any leading whitespace */ 264 p = line; 265 while (isspace(*p)) { 266 p++; 267 } 268 /* ignore comments or empty lines */ 269 if (*p == '#' || *p == '\0') 270 continue; 271 entries++; 272 } 273 274 if (!entries) { 275 ERROR("No entries found in fstab\n"); 276 goto err; 277 } 278 279 /* Allocate and init the fstab structure */ 280 fstab = calloc(1, sizeof(struct fstab)); 281 fstab->num_entries = entries; 282 fstab->fstab_filename = strdup(fstab_path); 283 fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec)); 284 285 fseek(fstab_file, 0, SEEK_SET); 286 287 cnt = 0; 288 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) { 289 /* if the last character is a newline, shorten the string by 1 byte */ 290 if (line[len - 1] == '\n') { 291 line[len - 1] = '\0'; 292 } 293 294 /* Skip any leading whitespace */ 295 p = line; 296 while (isspace(*p)) { 297 p++; 298 } 299 /* ignore comments or empty lines */ 300 if (*p == '#' || *p == '\0') 301 continue; 302 303 /* If a non-comment entry is greater than the size we allocated, give an 304 * error and quit. This can happen in the unlikely case the file changes 305 * between the two reads. 306 */ 307 if (cnt >= entries) { 308 ERROR("Tried to process more entries than counted\n"); 309 break; 310 } 311 312 if (!(p = strtok_r(line, delim, &save_ptr))) { 313 ERROR("Error parsing mount source\n"); 314 goto err; 315 } 316 fstab->recs[cnt].blk_device = strdup(p); 317 318 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 319 ERROR("Error parsing mount_point\n"); 320 goto err; 321 } 322 fstab->recs[cnt].mount_point = strdup(p); 323 324 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 325 ERROR("Error parsing fs_type\n"); 326 goto err; 327 } 328 fstab->recs[cnt].fs_type = strdup(p); 329 330 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 331 ERROR("Error parsing mount_flags\n"); 332 goto err; 333 } 334 tmp_fs_options[0] = '\0'; 335 fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL, 336 tmp_fs_options, FS_OPTIONS_LEN); 337 338 /* fs_options are optional */ 339 if (tmp_fs_options[0]) { 340 fstab->recs[cnt].fs_options = strdup(tmp_fs_options); 341 } else { 342 fstab->recs[cnt].fs_options = NULL; 343 } 344 345 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 346 ERROR("Error parsing fs_mgr_options\n"); 347 goto err; 348 } 349 fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, 350 &flag_vals, NULL, 0); 351 fstab->recs[cnt].key_loc = flag_vals.key_loc; 352 fstab->recs[cnt].length = flag_vals.part_length; 353 fstab->recs[cnt].label = flag_vals.label; 354 fstab->recs[cnt].partnum = flag_vals.partnum; 355 fstab->recs[cnt].swap_prio = flag_vals.swap_prio; 356 fstab->recs[cnt].zram_size = flag_vals.zram_size; 357 cnt++; 358 } 359 fclose(fstab_file); 360 free(line); 361 return fstab; 362 363err: 364 fclose(fstab_file); 365 free(line); 366 if (fstab) 367 fs_mgr_free_fstab(fstab); 368 return NULL; 369} 370 371void fs_mgr_free_fstab(struct fstab *fstab) 372{ 373 int i; 374 375 if (!fstab) { 376 return; 377 } 378 379 for (i = 0; i < fstab->num_entries; i++) { 380 /* Free the pointers return by strdup(3) */ 381 free(fstab->recs[i].blk_device); 382 free(fstab->recs[i].mount_point); 383 free(fstab->recs[i].fs_type); 384 free(fstab->recs[i].fs_options); 385 free(fstab->recs[i].key_loc); 386 free(fstab->recs[i].label); 387 } 388 389 /* Free the fstab_recs array created by calloc(3) */ 390 free(fstab->recs); 391 392 /* Free the fstab filename */ 393 free(fstab->fstab_filename); 394 395 /* Free fstab */ 396 free(fstab); 397} 398 399static void check_fs(char *blk_device, char *fs_type, char *target) 400{ 401 int status; 402 int ret; 403 long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID; 404 char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro"; 405 char *e2fsck_argv[] = { 406 E2FSCK_BIN, 407 "-y", 408 blk_device 409 }; 410 411 /* Check for the types of filesystems we know how to check */ 412 if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) { 413 /* 414 * First try to mount and unmount the filesystem. We do this because 415 * the kernel is more efficient than e2fsck in running the journal and 416 * processing orphaned inodes, and on at least one device with a 417 * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes 418 * to do what the kernel does in about a second. 419 * 420 * After mounting and unmounting the filesystem, run e2fsck, and if an 421 * error is recorded in the filesystem superblock, e2fsck will do a full 422 * check. Otherwise, it does nothing. If the kernel cannot mount the 423 * filesytsem due to an error, e2fsck is still run to do a full check 424 * fix the filesystem. 425 */ 426 ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts); 427 if (!ret) { 428 umount(target); 429 } 430 431 INFO("Running %s on %s\n", E2FSCK_BIN, blk_device); 432 433 ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, 434 &status, true, LOG_KLOG | LOG_FILE, 435 true, FSCK_LOG_FILE); 436 437 if (ret < 0) { 438 /* No need to check for error in fork, we can't really handle it now */ 439 ERROR("Failed trying to run %s\n", E2FSCK_BIN); 440 } 441 } 442 443 return; 444} 445 446static void remove_trailing_slashes(char *n) 447{ 448 int len; 449 450 len = strlen(n) - 1; 451 while ((*(n + len) == '/') && len) { 452 *(n + len) = '\0'; 453 len--; 454 } 455} 456 457/* 458 * Mark the given block device as read-only, using the BLKROSET ioctl. 459 * Return 0 on success, and -1 on error. 460 */ 461static void fs_set_blk_ro(const char *blockdev) 462{ 463 int fd; 464 int ON = 1; 465 466 fd = open(blockdev, O_RDONLY); 467 if (fd < 0) { 468 // should never happen 469 return; 470 } 471 472 ioctl(fd, BLKROSET, &ON); 473 close(fd); 474} 475 476/* 477 * __mount(): wrapper around the mount() system call which also 478 * sets the underlying block device to read-only if the mount is read-only. 479 * See "man 2 mount" for return values. 480 */ 481static int __mount(const char *source, const char *target, 482 const char *filesystemtype, unsigned long mountflags, 483 const void *data) 484{ 485 int ret = mount(source, target, filesystemtype, mountflags, data); 486 487 if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { 488 fs_set_blk_ro(source); 489 } 490 491 return ret; 492} 493 494static int fs_match(char *in1, char *in2) 495{ 496 char *n1; 497 char *n2; 498 int ret; 499 500 n1 = strdup(in1); 501 n2 = strdup(in2); 502 503 remove_trailing_slashes(n1); 504 remove_trailing_slashes(n2); 505 506 ret = !strcmp(n1, n2); 507 508 free(n1); 509 free(n2); 510 511 return ret; 512} 513 514int fs_mgr_mount_all(struct fstab *fstab) 515{ 516 int i = 0; 517 int encrypted = 0; 518 int ret = -1; 519 int mret; 520 521 if (!fstab) { 522 return ret; 523 } 524 525 for (i = 0; i < fstab->num_entries; i++) { 526 /* Don't mount entries that are managed by vold */ 527 if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { 528 continue; 529 } 530 531 /* Skip swap and raw partition entries such as boot, recovery, etc */ 532 if (!strcmp(fstab->recs[i].fs_type, "swap") || 533 !strcmp(fstab->recs[i].fs_type, "emmc") || 534 !strcmp(fstab->recs[i].fs_type, "mtd")) { 535 continue; 536 } 537 538 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 539 wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); 540 } 541 542 if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { 543 check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type, 544 fstab->recs[i].mount_point); 545 } 546 547 if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) { 548 if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { 549 ERROR("Could not set up verified partition, skipping!"); 550 continue; 551 } 552 } 553 554 mret = __mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, 555 fstab->recs[i].fs_type, fstab->recs[i].flags, 556 fstab->recs[i].fs_options); 557 558 if (!mret) { 559 /* Success! Go get the next one */ 560 continue; 561 } 562 563 /* mount(2) returned an error, check if it's encrypted and deal with it */ 564 if ((fstab->recs[i].fs_mgr_flags & MF_CRYPT) && 565 !partition_wiped(fstab->recs[i].blk_device)) { 566 /* Need to mount a tmpfs at this mountpoint for now, and set 567 * properties that vold will query later for decrypting 568 */ 569 if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs", 570 MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) { 571 ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n", 572 fstab->recs[i].mount_point); 573 goto out; 574 } 575 encrypted = 1; 576 } else { 577 ERROR("Cannot mount filesystem on %s at %s\n", 578 fstab->recs[i].blk_device, fstab->recs[i].mount_point); 579 goto out; 580 } 581 } 582 583 if (encrypted) { 584 ret = 1; 585 } else { 586 ret = 0; 587 } 588 589out: 590 return ret; 591} 592 593/* If tmp_mount_point is non-null, mount the filesystem there. This is for the 594 * tmp mount we do to check the user password 595 */ 596int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device, 597 char *tmp_mount_point) 598{ 599 int i = 0; 600 int ret = -1; 601 char *m; 602 603 if (!fstab) { 604 return ret; 605 } 606 607 for (i = 0; i < fstab->num_entries; i++) { 608 if (!fs_match(fstab->recs[i].mount_point, n_name)) { 609 continue; 610 } 611 612 /* We found our match */ 613 /* If this swap or a raw partition, report an error */ 614 if (!strcmp(fstab->recs[i].fs_type, "swap") || 615 !strcmp(fstab->recs[i].fs_type, "emmc") || 616 !strcmp(fstab->recs[i].fs_type, "mtd")) { 617 ERROR("Cannot mount filesystem of type %s on %s\n", 618 fstab->recs[i].fs_type, n_blk_device); 619 goto out; 620 } 621 622 /* First check the filesystem if requested */ 623 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 624 wait_for_file(n_blk_device, WAIT_TIMEOUT); 625 } 626 627 if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { 628 check_fs(n_blk_device, fstab->recs[i].fs_type, 629 fstab->recs[i].mount_point); 630 } 631 632 if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) { 633 if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { 634 ERROR("Could not set up verified partition, skipping!"); 635 continue; 636 } 637 } 638 639 /* Now mount it where requested */ 640 if (tmp_mount_point) { 641 m = tmp_mount_point; 642 } else { 643 m = fstab->recs[i].mount_point; 644 } 645 if (__mount(n_blk_device, m, fstab->recs[i].fs_type, 646 fstab->recs[i].flags, fstab->recs[i].fs_options)) { 647 ERROR("Cannot mount filesystem on %s at %s\n", 648 n_blk_device, m); 649 goto out; 650 } else { 651 ret = 0; 652 goto out; 653 } 654 } 655 656 /* We didn't find a match, say so and return an error */ 657 ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); 658 659out: 660 return ret; 661} 662 663/* 664 * mount a tmpfs filesystem at the given point. 665 * return 0 on success, non-zero on failure. 666 */ 667int fs_mgr_do_tmpfs_mount(char *n_name) 668{ 669 int ret; 670 671 ret = mount("tmpfs", n_name, "tmpfs", 672 MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS); 673 if (ret < 0) { 674 ERROR("Cannot mount tmpfs filesystem at %s\n", n_name); 675 return -1; 676 } 677 678 /* Success */ 679 return 0; 680} 681 682int fs_mgr_unmount_all(struct fstab *fstab) 683{ 684 int i = 0; 685 int ret = 0; 686 687 if (!fstab) { 688 return -1; 689 } 690 691 while (fstab->recs[i].blk_device) { 692 if (umount(fstab->recs[i].mount_point)) { 693 ERROR("Cannot unmount filesystem at %s\n", fstab->recs[i].mount_point); 694 ret = -1; 695 } 696 i++; 697 } 698 699 return ret; 700} 701 702/* This must be called after mount_all, because the mkswap command needs to be 703 * available. 704 */ 705int fs_mgr_swapon_all(struct fstab *fstab) 706{ 707 int i = 0; 708 int flags = 0; 709 int err = 0; 710 int ret = 0; 711 int status; 712 char *mkswap_argv[2] = { 713 MKSWAP_BIN, 714 NULL 715 }; 716 717 if (!fstab) { 718 return -1; 719 } 720 721 for (i = 0; i < fstab->num_entries; i++) { 722 /* Skip non-swap entries */ 723 if (strcmp(fstab->recs[i].fs_type, "swap")) { 724 continue; 725 } 726 727 if (fstab->recs[i].zram_size > 0) { 728 /* A zram_size was specified, so we need to configure the 729 * device. There is no point in having multiple zram devices 730 * on a system (all the memory comes from the same pool) so 731 * we can assume the device number is 0. 732 */ 733 FILE *zram_fp; 734 735 zram_fp = fopen(ZRAM_CONF_DEV, "r+"); 736 if (zram_fp == NULL) { 737 ERROR("Unable to open zram conf device " ZRAM_CONF_DEV); 738 ret = -1; 739 continue; 740 } 741 fprintf(zram_fp, "%d\n", fstab->recs[i].zram_size); 742 fclose(zram_fp); 743 } 744 745 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 746 wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); 747 } 748 749 /* Initialize the swap area */ 750 mkswap_argv[1] = fstab->recs[i].blk_device; 751 err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv, 752 &status, true, LOG_KLOG, false, NULL); 753 if (err) { 754 ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device); 755 ret = -1; 756 continue; 757 } 758 759 /* If -1, then no priority was specified in fstab, so don't set 760 * SWAP_FLAG_PREFER or encode the priority */ 761 if (fstab->recs[i].swap_prio >= 0) { 762 flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) & 763 SWAP_FLAG_PRIO_MASK; 764 flags |= SWAP_FLAG_PREFER; 765 } else { 766 flags = 0; 767 } 768 err = swapon(fstab->recs[i].blk_device, flags); 769 if (err) { 770 ERROR("swapon failed for %s\n", fstab->recs[i].blk_device); 771 ret = -1; 772 } 773 } 774 775 return ret; 776} 777 778/* 779 * key_loc must be at least PROPERTY_VALUE_MAX bytes long 780 * 781 * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long 782 */ 783int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size) 784{ 785 int i = 0; 786 787 if (!fstab) { 788 return -1; 789 } 790 /* Initialize return values to null strings */ 791 if (key_loc) { 792 *key_loc = '\0'; 793 } 794 if (real_blk_device) { 795 *real_blk_device = '\0'; 796 } 797 798 /* Look for the encryptable partition to find the data */ 799 for (i = 0; i < fstab->num_entries; i++) { 800 /* Don't deal with vold managed enryptable partitions here */ 801 if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) { 802 continue; 803 } 804 if (!(fstab->recs[i].fs_mgr_flags & MF_CRYPT)) { 805 continue; 806 } 807 808 /* We found a match */ 809 if (key_loc) { 810 strlcpy(key_loc, fstab->recs[i].key_loc, size); 811 } 812 if (real_blk_device) { 813 strlcpy(real_blk_device, fstab->recs[i].blk_device, size); 814 } 815 break; 816 } 817 818 return 0; 819} 820 821/* Add an entry to the fstab, and return 0 on success or -1 on error */ 822int fs_mgr_add_entry(struct fstab *fstab, 823 const char *mount_point, const char *fs_type, 824 const char *blk_device, long long length) 825{ 826 struct fstab_rec *new_fstab_recs; 827 int n = fstab->num_entries; 828 829 new_fstab_recs = (struct fstab_rec *) 830 realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1)); 831 832 if (!new_fstab_recs) { 833 return -1; 834 } 835 836 /* A new entry was added, so initialize it */ 837 memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec)); 838 new_fstab_recs[n].mount_point = strdup(mount_point); 839 new_fstab_recs[n].fs_type = strdup(fs_type); 840 new_fstab_recs[n].blk_device = strdup(blk_device); 841 new_fstab_recs[n].length = 0; 842 843 /* Update the fstab struct */ 844 fstab->recs = new_fstab_recs; 845 fstab->num_entries++; 846 847 return 0; 848} 849 850struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path) 851{ 852 int i; 853 854 if (!fstab) { 855 return NULL; 856 } 857 858 for (i = 0; i < fstab->num_entries; i++) { 859 int len = strlen(fstab->recs[i].mount_point); 860 if (strncmp(path, fstab->recs[i].mount_point, len) == 0 && 861 (path[len] == '\0' || path[len] == '/')) { 862 return &fstab->recs[i]; 863 } 864 } 865 866 return NULL; 867} 868 869int fs_mgr_is_voldmanaged(struct fstab_rec *fstab) 870{ 871 return fstab->fs_mgr_flags & MF_VOLDMANAGED; 872} 873 874int fs_mgr_is_nonremovable(struct fstab_rec *fstab) 875{ 876 return fstab->fs_mgr_flags & MF_NONREMOVABLE; 877} 878 879int fs_mgr_is_encryptable(struct fstab_rec *fstab) 880{ 881 return fstab->fs_mgr_flags & MF_CRYPT; 882} 883 884int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab) 885{ 886 return fstab->fs_mgr_flags & MF_NOEMULATEDSD; 887} 888