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