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/* TO DO: 18 * 1. Re-direct fsck output to the kernel log? 19 * 20 */ 21 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25#include <unistd.h> 26#include <fcntl.h> 27#include <ctype.h> 28#include <sys/mount.h> 29#include <sys/stat.h> 30#include <errno.h> 31#include <sys/types.h> 32#include <sys/wait.h> 33#include <libgen.h> 34#include <time.h> 35 36#include <private/android_filesystem_config.h> 37#include <cutils/partition_utils.h> 38#include <cutils/properties.h> 39 40#include "fs_mgr_priv.h" 41 42#define KEY_LOC_PROP "ro.crypto.keyfile.userdata" 43#define KEY_IN_FOOTER "footer" 44 45#define E2FSCK_BIN "/system/bin/e2fsck" 46 47struct flag_list { 48 const char *name; 49 unsigned flag; 50}; 51 52static struct flag_list mount_flags[] = { 53 { "noatime", MS_NOATIME }, 54 { "noexec", MS_NOEXEC }, 55 { "nosuid", MS_NOSUID }, 56 { "nodev", MS_NODEV }, 57 { "nodiratime", MS_NODIRATIME }, 58 { "ro", MS_RDONLY }, 59 { "rw", 0 }, 60 { "remount", MS_REMOUNT }, 61 { "bind", MS_BIND }, 62 { "rec", MS_REC }, 63 { "unbindable", MS_UNBINDABLE }, 64 { "private", MS_PRIVATE }, 65 { "slave", MS_SLAVE }, 66 { "shared", MS_SHARED }, 67 { "defaults", 0 }, 68 { 0, 0 }, 69}; 70 71static struct flag_list fs_mgr_flags[] = { 72 { "wait", MF_WAIT }, 73 { "check", MF_CHECK }, 74 { "encryptable=",MF_CRYPT }, 75 { "defaults", 0 }, 76 { 0, 0 }, 77}; 78 79/* 80 * gettime() - returns the time in seconds of the system's monotonic clock or 81 * zero on error. 82 */ 83static time_t gettime(void) 84{ 85 struct timespec ts; 86 int ret; 87 88 ret = clock_gettime(CLOCK_MONOTONIC, &ts); 89 if (ret < 0) { 90 ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno)); 91 return 0; 92 } 93 94 return ts.tv_sec; 95} 96 97static int wait_for_file(const char *filename, int timeout) 98{ 99 struct stat info; 100 time_t timeout_time = gettime() + timeout; 101 int ret = -1; 102 103 while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0)) 104 usleep(10000); 105 106 return ret; 107} 108 109static int parse_flags(char *flags, struct flag_list *fl, char **key_loc, 110 char *fs_options, int fs_options_len) 111{ 112 int f = 0; 113 int i; 114 char *p; 115 char *savep; 116 117 /* initialize key_loc to null, if we find an MF_CRYPT flag, 118 * then we'll set key_loc to the proper value */ 119 if (key_loc) { 120 *key_loc = NULL; 121 } 122 /* initialize fs_options to the null string */ 123 if (fs_options && (fs_options_len > 0)) { 124 fs_options[0] = '\0'; 125 } 126 127 p = strtok_r(flags, ",", &savep); 128 while (p) { 129 /* Look for the flag "p" in the flag list "fl" 130 * If not found, the loop exits with fl[i].name being null. 131 */ 132 for (i = 0; fl[i].name; i++) { 133 if (!strncmp(p, fl[i].name, strlen(fl[i].name))) { 134 f |= fl[i].flag; 135 if ((fl[i].flag == MF_CRYPT) && key_loc) { 136 /* The encryptable flag is followed by an = and the 137 * location of the keys. Get it and return it. 138 */ 139 *key_loc = strdup(strchr(p, '=') + 1); 140 } 141 break; 142 } 143 } 144 145 if (!fl[i].name) { 146 if (fs_options) { 147 /* It's not a known flag, so it must be a filesystem specific 148 * option. Add it to fs_options if it was passed in. 149 */ 150 strlcat(fs_options, p, fs_options_len); 151 strlcat(fs_options, ",", fs_options_len); 152 } else { 153 /* fs_options was not passed in, so if the flag is unknown 154 * it's an error. 155 */ 156 ERROR("Warning: unknown flag %s\n", p); 157 } 158 } 159 p = strtok_r(NULL, ",", &savep); 160 } 161 162out: 163 if (fs_options && fs_options[0]) { 164 /* remove the last trailing comma from the list of options */ 165 fs_options[strlen(fs_options) - 1] = '\0'; 166 } 167 168 return f; 169} 170 171/* Read a line of text till the next newline character. 172 * If no newline is found before the buffer is full, continue reading till a new line is seen, 173 * then return an empty buffer. This effectively ignores lines that are too long. 174 * On EOF, return null. 175 */ 176static char *getline(char *buf, int size, FILE *file) 177{ 178 int cnt = 0; 179 int eof = 0; 180 int eol = 0; 181 int c; 182 183 if (size < 1) { 184 return NULL; 185 } 186 187 while (cnt < (size - 1)) { 188 c = getc(file); 189 if (c == EOF) { 190 eof = 1; 191 break; 192 } 193 194 *(buf + cnt) = c; 195 cnt++; 196 197 if (c == '\n') { 198 eol = 1; 199 break; 200 } 201 } 202 203 /* Null terminate what we've read */ 204 *(buf + cnt) = '\0'; 205 206 if (eof) { 207 if (cnt) { 208 return buf; 209 } else { 210 return NULL; 211 } 212 } else if (eol) { 213 return buf; 214 } else { 215 /* The line is too long. Read till a newline or EOF. 216 * If EOF, return null, if newline, return an empty buffer. 217 */ 218 while(1) { 219 c = getc(file); 220 if (c == EOF) { 221 return NULL; 222 } else if (c == '\n') { 223 *buf = '\0'; 224 return buf; 225 } 226 } 227 } 228} 229 230static struct fstab_rec *read_fstab(char *fstab_path) 231{ 232 FILE *fstab_file; 233 int cnt, entries; 234 int len; 235 char line[256]; 236 const char *delim = " \t"; 237 char *save_ptr, *p; 238 struct fstab_rec *fstab; 239 char *key_loc; 240#define FS_OPTIONS_LEN 1024 241 char tmp_fs_options[FS_OPTIONS_LEN]; 242 243 fstab_file = fopen(fstab_path, "r"); 244 if (!fstab_file) { 245 ERROR("Cannot open file %s\n", fstab_path); 246 return 0; 247 } 248 249 entries = 0; 250 while (getline(line, sizeof(line), fstab_file)) { 251 /* if the last character is a newline, shorten the string by 1 byte */ 252 len = strlen(line); 253 if (line[len - 1] == '\n') { 254 line[len - 1] = '\0'; 255 } 256 /* Skip any leading whitespace */ 257 p = line; 258 while (isspace(*p)) { 259 p++; 260 } 261 /* ignore comments or empty lines */ 262 if (*p == '#' || *p == '\0') 263 continue; 264 entries++; 265 } 266 267 if (!entries) { 268 ERROR("No entries found in fstab\n"); 269 return 0; 270 } 271 272 fstab = calloc(entries + 1, sizeof(struct fstab_rec)); 273 274 fseek(fstab_file, 0, SEEK_SET); 275 276 cnt = 0; 277 while (getline(line, sizeof(line), fstab_file)) { 278 /* if the last character is a newline, shorten the string by 1 byte */ 279 len = strlen(line); 280 if (line[len - 1] == '\n') { 281 line[len - 1] = '\0'; 282 } 283 284 /* Skip any leading whitespace */ 285 p = line; 286 while (isspace(*p)) { 287 p++; 288 } 289 /* ignore comments or empty lines */ 290 if (*p == '#' || *p == '\0') 291 continue; 292 293 /* If a non-comment entry is greater than the size we allocated, give an 294 * error and quit. This can happen in the unlikely case the file changes 295 * between the two reads. 296 */ 297 if (cnt >= entries) { 298 ERROR("Tried to process more entries than counted\n"); 299 break; 300 } 301 302 if (!(p = strtok_r(line, delim, &save_ptr))) { 303 ERROR("Error parsing mount source\n"); 304 return 0; 305 } 306 fstab[cnt].blk_dev = strdup(p); 307 308 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 309 ERROR("Error parsing mnt_point\n"); 310 return 0; 311 } 312 fstab[cnt].mnt_point = strdup(p); 313 314 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 315 ERROR("Error parsing fs_type\n"); 316 return 0; 317 } 318 fstab[cnt].type = strdup(p); 319 320 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 321 ERROR("Error parsing mount_flags\n"); 322 return 0; 323 } 324 tmp_fs_options[0] = '\0'; 325 fstab[cnt].flags = parse_flags(p, mount_flags, 0, tmp_fs_options, FS_OPTIONS_LEN); 326 327 /* fs_options are optional */ 328 if (tmp_fs_options[0]) { 329 fstab[cnt].fs_options = strdup(tmp_fs_options); 330 } else { 331 fstab[cnt].fs_options = NULL; 332 } 333 334 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 335 ERROR("Error parsing fs_mgr_options\n"); 336 return 0; 337 } 338 fstab[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, &key_loc, 0, 0); 339 fstab[cnt].key_loc = key_loc; 340 341 cnt++; 342 } 343 fclose(fstab_file); 344 345 return fstab; 346} 347 348static void free_fstab(struct fstab_rec *fstab) 349{ 350 int i = 0; 351 352 while (fstab[i].blk_dev) { 353 /* Free the pointers return by strdup(3) */ 354 free(fstab[i].blk_dev); 355 free(fstab[i].mnt_point); 356 free(fstab[i].type); 357 free(fstab[i].fs_options); 358 free(fstab[i].key_loc); 359 360 i++; 361 } 362 363 /* Free the actual fstab array created by calloc(3) */ 364 free(fstab); 365} 366 367static void check_fs(char *blk_dev, char *type, char *target) 368{ 369 pid_t pid; 370 int status; 371 int ret; 372 long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID; 373 char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro"; 374 375 /* Check for the types of filesystems we know how to check */ 376 if (!strcmp(type, "ext2") || !strcmp(type, "ext3") || !strcmp(type, "ext4")) { 377 /* 378 * First try to mount and unmount the filesystem. We do this because 379 * the kernel is more efficient than e2fsck in running the journal and 380 * processing orphaned inodes, and on at least one device with a 381 * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes 382 * to do what the kernel does in about a second. 383 * 384 * After mounting and unmounting the filesystem, run e2fsck, and if an 385 * error is recorded in the filesystem superblock, e2fsck will do a full 386 * check. Otherwise, it does nothing. If the kernel cannot mount the 387 * filesytsem due to an error, e2fsck is still run to do a full check 388 * fix the filesystem. 389 */ 390 ret = mount(blk_dev, target, type, tmpmnt_flags, tmpmnt_opts); 391 if (! ret) { 392 umount(target); 393 } 394 395 INFO("Running %s on %s\n", E2FSCK_BIN, blk_dev); 396 pid = fork(); 397 if (pid > 0) { 398 /* Parent, wait for the child to return */ 399 waitpid(pid, &status, 0); 400 } else if (pid == 0) { 401 /* child, run checker */ 402 execlp(E2FSCK_BIN, E2FSCK_BIN, "-y", blk_dev, (char *)NULL); 403 404 /* Only gets here on error */ 405 ERROR("Cannot run fs_mgr binary %s\n", E2FSCK_BIN); 406 } else { 407 /* No need to check for error in fork, we can't really handle it now */ 408 ERROR("Fork failed trying to run %s\n", E2FSCK_BIN); 409 } 410 } 411 412 return; 413} 414 415static void remove_trailing_slashes(char *n) 416{ 417 int len; 418 419 len = strlen(n) - 1; 420 while ((*(n + len) == '/') && len) { 421 *(n + len) = '\0'; 422 len--; 423 } 424} 425 426static int fs_match(char *in1, char *in2) 427{ 428 char *n1; 429 char *n2; 430 int ret; 431 432 n1 = strdup(in1); 433 n2 = strdup(in2); 434 435 remove_trailing_slashes(n1); 436 remove_trailing_slashes(n2); 437 438 ret = !strcmp(n1, n2); 439 440 free(n1); 441 free(n2); 442 443 return ret; 444} 445 446int fs_mgr_mount_all(char *fstab_file) 447{ 448 int i = 0; 449 int encrypted = 0; 450 int ret = -1; 451 int mret; 452 struct fstab_rec *fstab = 0; 453 454 if (!(fstab = read_fstab(fstab_file))) { 455 return ret; 456 } 457 458 for (i = 0; fstab[i].blk_dev; i++) { 459 if (fstab[i].fs_mgr_flags & MF_WAIT) { 460 wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT); 461 } 462 463 if (fstab[i].fs_mgr_flags & MF_CHECK) { 464 check_fs(fstab[i].blk_dev, fstab[i].type, fstab[i].mnt_point); 465 } 466 467 mret = mount(fstab[i].blk_dev, fstab[i].mnt_point, fstab[i].type, 468 fstab[i].flags, fstab[i].fs_options); 469 if (!mret) { 470 /* Success! Go get the next one */ 471 continue; 472 } 473 474 /* mount(2) returned an error, check if it's encrypted and deal with it */ 475 if ((fstab[i].fs_mgr_flags & MF_CRYPT) && !partition_wiped(fstab[i].blk_dev)) { 476 /* Need to mount a tmpfs at this mountpoint for now, and set 477 * properties that vold will query later for decrypting 478 */ 479 if (mount("tmpfs", fstab[i].mnt_point, "tmpfs", 480 MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) { 481 ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n", 482 fstab[i].mnt_point); 483 goto out; 484 } 485 encrypted = 1; 486 } else { 487 ERROR("Cannot mount filesystem on %s at %s\n", 488 fstab[i].blk_dev, fstab[i].mnt_point); 489 goto out; 490 } 491 } 492 493 if (encrypted) { 494 ret = 1; 495 } else { 496 ret = 0; 497 } 498 499out: 500 free_fstab(fstab); 501 return ret; 502} 503 504/* If tmp_mnt_point is non-null, mount the filesystem there. This is for the 505 * tmp mount we do to check the user password 506 */ 507int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point) 508{ 509 int i = 0; 510 int ret = -1; 511 struct fstab_rec *fstab = 0; 512 char *m; 513 514 if (!(fstab = read_fstab(fstab_file))) { 515 return ret; 516 } 517 518 for (i = 0; fstab[i].blk_dev; i++) { 519 if (!fs_match(fstab[i].mnt_point, n_name)) { 520 continue; 521 } 522 523 /* We found our match */ 524 /* First check the filesystem if requested */ 525 if (fstab[i].fs_mgr_flags & MF_WAIT) { 526 wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT); 527 } 528 529 if (fstab[i].fs_mgr_flags & MF_CHECK) { 530 check_fs(fstab[i].blk_dev, fstab[i].type, fstab[i].mnt_point); 531 } 532 533 /* Now mount it where requested */ 534 if (tmp_mnt_point) { 535 m = tmp_mnt_point; 536 } else { 537 m = fstab[i].mnt_point; 538 } 539 if (mount(n_blk_dev, m, fstab[i].type, 540 fstab[i].flags, fstab[i].fs_options)) { 541 ERROR("Cannot mount filesystem on %s at %s\n", 542 n_blk_dev, m); 543 goto out; 544 } else { 545 ret = 0; 546 goto out; 547 } 548 } 549 550 /* We didn't find a match, say so and return an error */ 551 ERROR("Cannot find mount point %s in fstab\n", fstab[i].mnt_point); 552 553out: 554 free_fstab(fstab); 555 return ret; 556} 557 558/* 559 * mount a tmpfs filesystem at the given point. 560 * return 0 on success, non-zero on failure. 561 */ 562int fs_mgr_do_tmpfs_mount(char *n_name) 563{ 564 int ret; 565 566 ret = mount("tmpfs", n_name, "tmpfs", 567 MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS); 568 if (ret < 0) { 569 ERROR("Cannot mount tmpfs filesystem at %s\n", n_name); 570 return -1; 571 } 572 573 /* Success */ 574 return 0; 575} 576 577int fs_mgr_unmount_all(char *fstab_file) 578{ 579 int i = 0; 580 int ret = 0; 581 struct fstab_rec *fstab = 0; 582 583 if (!(fstab = read_fstab(fstab_file))) { 584 return -1; 585 } 586 587 while (fstab[i].blk_dev) { 588 if (umount(fstab[i].mnt_point)) { 589 ERROR("Cannot unmount filesystem at %s\n", fstab[i].mnt_point); 590 ret = -1; 591 } 592 i++; 593 } 594 595 free_fstab(fstab); 596 return ret; 597} 598/* 599 * key_loc must be at least PROPERTY_VALUE_MAX bytes long 600 * 601 * real_blk_dev must be at least PROPERTY_VALUE_MAX bytes long 602 */ 603int fs_mgr_get_crypt_info(char *fstab_file, char *key_loc, char *real_blk_dev, int size) 604{ 605 int i = 0; 606 struct fstab_rec *fstab = 0; 607 608 if (!(fstab = read_fstab(fstab_file))) { 609 return -1; 610 } 611 /* Initialize return values to null strings */ 612 if (key_loc) { 613 *key_loc = '\0'; 614 } 615 if (real_blk_dev) { 616 *real_blk_dev = '\0'; 617 } 618 619 /* Look for the encryptable partition to find the data */ 620 for (i = 0; fstab[i].blk_dev; i++) { 621 if (!(fstab[i].fs_mgr_flags & MF_CRYPT)) { 622 continue; 623 } 624 625 /* We found a match */ 626 if (key_loc) { 627 strlcpy(key_loc, fstab[i].key_loc, size); 628 } 629 if (real_blk_dev) { 630 strlcpy(real_blk_dev, fstab[i].blk_dev, size); 631 } 632 break; 633 } 634 635 free_fstab(fstab); 636 return 0; 637} 638 639