1 /* 2 * Copyright (C) 2014 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 <dirent.h> 19 #include <errno.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <sys/mount.h> 24 #include <unistd.h> 25 26 #include <algorithm> 27 #include <utility> 28 #include <vector> 29 30 #include <android-base/file.h> 31 #include <android-base/stringprintf.h> 32 #include <android-base/strings.h> 33 34 #include "fs_mgr_priv.h" 35 36 const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android"); 37 38 struct fs_mgr_flag_values { 39 char *key_loc; 40 char* key_dir; 41 char *verity_loc; 42 char *sysfs_path; 43 long long part_length; 44 char *label; 45 int partnum; 46 int swap_prio; 47 int max_comp_streams; 48 unsigned int zram_size; 49 uint64_t reserved_size; 50 unsigned int file_contents_mode; 51 unsigned int file_names_mode; 52 unsigned int erase_blk_size; 53 unsigned int logical_blk_size; 54 }; 55 56 struct flag_list { 57 const char *name; 58 unsigned int flag; 59 }; 60 61 static struct flag_list mount_flags[] = { 62 { "noatime", MS_NOATIME }, 63 { "noexec", MS_NOEXEC }, 64 { "nosuid", MS_NOSUID }, 65 { "nodev", MS_NODEV }, 66 { "nodiratime", MS_NODIRATIME }, 67 { "ro", MS_RDONLY }, 68 { "rw", 0 }, 69 { "remount", MS_REMOUNT }, 70 { "bind", MS_BIND }, 71 { "rec", MS_REC }, 72 { "unbindable", MS_UNBINDABLE }, 73 { "private", MS_PRIVATE }, 74 { "slave", MS_SLAVE }, 75 { "shared", MS_SHARED }, 76 { "defaults", 0 }, 77 { 0, 0 }, 78 }; 79 80 static struct flag_list fs_mgr_flags[] = { 81 {"wait", MF_WAIT}, 82 {"check", MF_CHECK}, 83 {"encryptable=", MF_CRYPT}, 84 {"forceencrypt=", MF_FORCECRYPT}, 85 {"fileencryption=", MF_FILEENCRYPTION}, 86 {"forcefdeorfbe=", MF_FORCEFDEORFBE}, 87 {"keydirectory=", MF_KEYDIRECTORY}, 88 {"nonremovable", MF_NONREMOVABLE}, 89 {"voldmanaged=", MF_VOLDMANAGED}, 90 {"length=", MF_LENGTH}, 91 {"recoveryonly", MF_RECOVERYONLY}, 92 {"swapprio=", MF_SWAPPRIO}, 93 {"zramsize=", MF_ZRAMSIZE}, 94 {"max_comp_streams=", MF_MAX_COMP_STREAMS}, 95 {"verifyatboot", MF_VERIFYATBOOT}, 96 {"verify", MF_VERIFY}, 97 {"avb", MF_AVB}, 98 {"noemulatedsd", MF_NOEMULATEDSD}, 99 {"notrim", MF_NOTRIM}, 100 {"formattable", MF_FORMATTABLE}, 101 {"slotselect", MF_SLOTSELECT}, 102 {"nofail", MF_NOFAIL}, 103 {"latemount", MF_LATEMOUNT}, 104 {"reservedsize=", MF_RESERVEDSIZE}, 105 {"quota", MF_QUOTA}, 106 {"eraseblk=", MF_ERASEBLKSIZE}, 107 {"logicalblk=", MF_LOGICALBLKSIZE}, 108 {"sysfs_path=", MF_SYSFS}, 109 {"defaults", 0}, 110 {0, 0}, 111 }; 112 113 #define EM_AES_256_XTS 1 114 #define EM_ICE 2 115 #define EM_AES_256_CTS 3 116 #define EM_AES_256_HEH 4 117 #define EM_SPECK_128_256_XTS 5 118 #define EM_SPECK_128_256_CTS 6 119 120 static const struct flag_list file_contents_encryption_modes[] = { 121 {"aes-256-xts", EM_AES_256_XTS}, 122 {"speck128/256-xts", EM_SPECK_128_256_XTS}, 123 {"software", EM_AES_256_XTS}, /* alias for backwards compatibility */ 124 {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */ 125 {0, 0}, 126 }; 127 128 static const struct flag_list file_names_encryption_modes[] = { 129 {"aes-256-cts", EM_AES_256_CTS}, 130 {"aes-256-heh", EM_AES_256_HEH}, 131 {"speck128/256-cts", EM_SPECK_128_256_CTS}, 132 {0, 0}, 133 }; 134 135 static unsigned int encryption_mode_to_flag(const struct flag_list *list, 136 const char *mode, const char *type) 137 { 138 const struct flag_list *j; 139 140 for (j = list; j->name; ++j) { 141 if (!strcmp(mode, j->name)) { 142 return j->flag; 143 } 144 } 145 LERROR << "Unknown " << type << " encryption mode: " << mode; 146 return 0; 147 } 148 149 static const char *flag_to_encryption_mode(const struct flag_list *list, 150 unsigned int flag) 151 { 152 const struct flag_list *j; 153 154 for (j = list; j->name; ++j) { 155 if (flag == j->flag) { 156 return j->name; 157 } 158 } 159 return nullptr; 160 } 161 162 static uint64_t calculate_zram_size(unsigned int percentage) 163 { 164 uint64_t total; 165 166 total = sysconf(_SC_PHYS_PAGES); 167 total *= percentage; 168 total /= 100; 169 170 total *= sysconf(_SC_PAGESIZE); 171 172 return total; 173 } 174 175 static uint64_t parse_size(const char *arg) 176 { 177 char *endptr; 178 uint64_t size = strtoull(arg, &endptr, 10); 179 if (*endptr == 'k' || *endptr == 'K') 180 size *= 1024LL; 181 else if (*endptr == 'm' || *endptr == 'M') 182 size *= 1024LL * 1024LL; 183 else if (*endptr == 'g' || *endptr == 'G') 184 size *= 1024LL * 1024LL * 1024LL; 185 186 return size; 187 } 188 189 /* fills 'dt_value' with the underlying device tree value string without 190 * the trailing '\0'. Returns true if 'dt_value' has a valid string, 'false' 191 * otherwise. 192 */ 193 static bool read_dt_file(const std::string& file_name, std::string* dt_value) 194 { 195 if (android::base::ReadFileToString(file_name, dt_value)) { 196 if (!dt_value->empty()) { 197 // trim the trailing '\0' out, otherwise the comparison 198 // will produce false-negatives. 199 dt_value->resize(dt_value->size() - 1); 200 return true; 201 } 202 } 203 204 return false; 205 } 206 207 static int parse_flags(char *flags, struct flag_list *fl, 208 struct fs_mgr_flag_values *flag_vals, 209 char *fs_options, int fs_options_len) 210 { 211 int f = 0; 212 int i; 213 char *p; 214 char *savep; 215 216 /* initialize flag values. If we find a relevant flag, we'll 217 * update the value */ 218 if (flag_vals) { 219 memset(flag_vals, 0, sizeof(*flag_vals)); 220 flag_vals->partnum = -1; 221 flag_vals->swap_prio = -1; /* negative means it wasn't specified. */ 222 } 223 224 /* initialize fs_options to the null string */ 225 if (fs_options && (fs_options_len > 0)) { 226 fs_options[0] = '\0'; 227 } 228 229 p = strtok_r(flags, ",", &savep); 230 while (p) { 231 /* Look for the flag "p" in the flag list "fl" 232 * If not found, the loop exits with fl[i].name being null. 233 */ 234 for (i = 0; fl[i].name; i++) { 235 if (!strncmp(p, fl[i].name, strlen(fl[i].name))) { 236 f |= fl[i].flag; 237 if ((fl[i].flag == MF_CRYPT) && flag_vals) { 238 /* The encryptable flag is followed by an = and the 239 * location of the keys. Get it and return it. 240 */ 241 flag_vals->key_loc = strdup(strchr(p, '=') + 1); 242 } else if ((fl[i].flag == MF_VERIFY) && flag_vals) { 243 /* If the verify flag is followed by an = and the 244 * location for the verity state, get it and return it. 245 */ 246 char *start = strchr(p, '='); 247 if (start) { 248 flag_vals->verity_loc = strdup(start + 1); 249 } 250 } else if ((fl[i].flag == MF_FORCECRYPT) && flag_vals) { 251 /* The forceencrypt flag is followed by an = and the 252 * location of the keys. Get it and return it. 253 */ 254 flag_vals->key_loc = strdup(strchr(p, '=') + 1); 255 } else if ((fl[i].flag == MF_FORCEFDEORFBE) && flag_vals) { 256 /* The forcefdeorfbe flag is followed by an = and the 257 * location of the keys. Get it and return it. 258 */ 259 flag_vals->key_loc = strdup(strchr(p, '=') + 1); 260 flag_vals->file_contents_mode = EM_AES_256_XTS; 261 flag_vals->file_names_mode = EM_AES_256_CTS; 262 } else if ((fl[i].flag == MF_FILEENCRYPTION) && flag_vals) { 263 /* The fileencryption flag is followed by an = and 264 * the mode of contents encryption, then optionally a 265 * : and the mode of filenames encryption (defaults 266 * to aes-256-cts). Get it and return it. 267 */ 268 char *mode = strchr(p, '=') + 1; 269 char *colon = strchr(mode, ':'); 270 if (colon) { 271 *colon = '\0'; 272 } 273 flag_vals->file_contents_mode = 274 encryption_mode_to_flag(file_contents_encryption_modes, 275 mode, "file contents"); 276 if (colon) { 277 flag_vals->file_names_mode = 278 encryption_mode_to_flag(file_names_encryption_modes, 279 colon + 1, "file names"); 280 } else { 281 flag_vals->file_names_mode = EM_AES_256_CTS; 282 } 283 } else if ((fl[i].flag == MF_KEYDIRECTORY) && flag_vals) { 284 /* The metadata flag is followed by an = and the 285 * directory for the keys. Get it and return it. 286 */ 287 flag_vals->key_dir = strdup(strchr(p, '=') + 1); 288 } else if ((fl[i].flag == MF_LENGTH) && flag_vals) { 289 /* The length flag is followed by an = and the 290 * size of the partition. Get it and return it. 291 */ 292 flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0); 293 } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) { 294 /* The voldmanaged flag is followed by an = and the 295 * label, a colon and the partition number or the 296 * word "auto", e.g. 297 * voldmanaged=sdcard:3 298 * Get and return them. 299 */ 300 char *label_start; 301 char *label_end; 302 char *part_start; 303 304 label_start = strchr(p, '=') + 1; 305 label_end = strchr(p, ':'); 306 if (label_end) { 307 flag_vals->label = strndup(label_start, 308 (int) (label_end - label_start)); 309 part_start = strchr(p, ':') + 1; 310 if (!strcmp(part_start, "auto")) { 311 flag_vals->partnum = -1; 312 } else { 313 flag_vals->partnum = strtol(part_start, NULL, 0); 314 } 315 } else { 316 LERROR << "Warning: voldmanaged= flag malformed"; 317 } 318 } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) { 319 flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0); 320 } else if ((fl[i].flag == MF_MAX_COMP_STREAMS) && flag_vals) { 321 flag_vals->max_comp_streams = strtoll(strchr(p, '=') + 1, NULL, 0); 322 } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) { 323 int is_percent = !!strrchr(p, '%'); 324 unsigned int val = strtoll(strchr(p, '=') + 1, NULL, 0); 325 if (is_percent) 326 flag_vals->zram_size = calculate_zram_size(val); 327 else 328 flag_vals->zram_size = val; 329 } else if ((fl[i].flag == MF_RESERVEDSIZE) && flag_vals) { 330 /* The reserved flag is followed by an = and the 331 * reserved size of the partition. Get it and return it. 332 */ 333 flag_vals->reserved_size = parse_size(strchr(p, '=') + 1); 334 } else if ((fl[i].flag == MF_ERASEBLKSIZE) && flag_vals) { 335 /* The erase block size flag is followed by an = and the flash 336 * erase block size. Get it, check that it is a power of 2 and 337 * at least 4096, and return it. 338 */ 339 unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0); 340 if (val >= 4096 && (val & (val - 1)) == 0) 341 flag_vals->erase_blk_size = val; 342 } else if ((fl[i].flag == MF_LOGICALBLKSIZE) && flag_vals) { 343 /* The logical block size flag is followed by an = and the flash 344 * logical block size. Get it, check that it is a power of 2 and 345 * at least 4096, and return it. 346 */ 347 unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0); 348 if (val >= 4096 && (val & (val - 1)) == 0) 349 flag_vals->logical_blk_size = val; 350 } else if ((fl[i].flag == MF_SYSFS) && flag_vals) { 351 /* The path to trigger device gc by idle-maint of vold. */ 352 flag_vals->sysfs_path = strdup(strchr(p, '=') + 1); 353 } 354 break; 355 } 356 } 357 358 if (!fl[i].name) { 359 if (fs_options) { 360 /* It's not a known flag, so it must be a filesystem specific 361 * option. Add it to fs_options if it was passed in. 362 */ 363 strlcat(fs_options, p, fs_options_len); 364 strlcat(fs_options, ",", fs_options_len); 365 } else { 366 /* fs_options was not passed in, so if the flag is unknown 367 * it's an error. 368 */ 369 LERROR << "Warning: unknown flag " << p; 370 } 371 } 372 p = strtok_r(NULL, ",", &savep); 373 } 374 375 if (fs_options && fs_options[0]) { 376 /* remove the last trailing comma from the list of options */ 377 fs_options[strlen(fs_options) - 1] = '\0'; 378 } 379 380 return f; 381 } 382 383 static std::string init_android_dt_dir() { 384 std::string android_dt_dir; 385 // The platform may specify a custom Android DT path in kernel cmdline 386 if (!fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) { 387 // Fall back to the standard procfs-based path 388 android_dt_dir = kDefaultAndroidDtDir; 389 } 390 return android_dt_dir; 391 } 392 393 // FIXME: The same logic is duplicated in system/core/init/ 394 const std::string& get_android_dt_dir() { 395 // Set once and saves time for subsequent calls to this function 396 static const std::string kAndroidDtDir = init_android_dt_dir(); 397 return kAndroidDtDir; 398 } 399 400 static bool is_dt_fstab_compatible() { 401 std::string dt_value; 402 std::string file_name = get_android_dt_dir() + "/fstab/compatible"; 403 if (read_dt_file(file_name, &dt_value)) { 404 if (dt_value == "android,fstab") { 405 return true; 406 } 407 } 408 409 return false; 410 } 411 412 static std::string read_fstab_from_dt() { 413 if (!is_dt_compatible() || !is_dt_fstab_compatible()) { 414 return {}; 415 } 416 417 std::string fstabdir_name = get_android_dt_dir() + "/fstab"; 418 std::unique_ptr<DIR, int (*)(DIR*)> fstabdir(opendir(fstabdir_name.c_str()), closedir); 419 if (!fstabdir) return {}; 420 421 dirent* dp; 422 // Each element in fstab_dt_entries is <mount point, the line format in fstab file>. 423 std::vector<std::pair<std::string, std::string>> fstab_dt_entries; 424 while ((dp = readdir(fstabdir.get())) != NULL) { 425 // skip over name, compatible and . 426 if (dp->d_type != DT_DIR || dp->d_name[0] == '.') continue; 427 428 // create <dev> <mnt_point> <type> <mnt_flags> <fsmgr_flags>\n 429 std::vector<std::string> fstab_entry; 430 std::string file_name; 431 std::string value; 432 // skip a partition entry if the status property is present and not set to ok 433 file_name = android::base::StringPrintf("%s/%s/status", fstabdir_name.c_str(), dp->d_name); 434 if (read_dt_file(file_name, &value)) { 435 if (value != "okay" && value != "ok") { 436 LINFO << "dt_fstab: Skip disabled entry for partition " << dp->d_name; 437 continue; 438 } 439 } 440 441 file_name = android::base::StringPrintf("%s/%s/dev", fstabdir_name.c_str(), dp->d_name); 442 if (!read_dt_file(file_name, &value)) { 443 LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name; 444 return {}; 445 } 446 fstab_entry.push_back(value); 447 448 std::string mount_point; 449 file_name = 450 android::base::StringPrintf("%s/%s/mnt_point", fstabdir_name.c_str(), dp->d_name); 451 if (read_dt_file(file_name, &value)) { 452 LINFO << "dt_fstab: Using a specified mount point " << value << " for " << dp->d_name; 453 mount_point = value; 454 } else { 455 mount_point = android::base::StringPrintf("/%s", dp->d_name); 456 } 457 fstab_entry.push_back(mount_point); 458 459 file_name = android::base::StringPrintf("%s/%s/type", fstabdir_name.c_str(), dp->d_name); 460 if (!read_dt_file(file_name, &value)) { 461 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name; 462 return {}; 463 } 464 fstab_entry.push_back(value); 465 466 file_name = android::base::StringPrintf("%s/%s/mnt_flags", fstabdir_name.c_str(), dp->d_name); 467 if (!read_dt_file(file_name, &value)) { 468 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name; 469 return {}; 470 } 471 fstab_entry.push_back(value); 472 473 file_name = android::base::StringPrintf("%s/%s/fsmgr_flags", fstabdir_name.c_str(), dp->d_name); 474 if (!read_dt_file(file_name, &value)) { 475 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name; 476 return {}; 477 } 478 fstab_entry.push_back(value); 479 // Adds a fstab_entry to fstab_dt_entries, to be sorted by mount_point later. 480 fstab_dt_entries.emplace_back(mount_point, android::base::Join(fstab_entry, " ")); 481 } 482 483 // Sort fstab_dt entries, to ensure /vendor is mounted before /vendor/abc is attempted. 484 std::sort(fstab_dt_entries.begin(), fstab_dt_entries.end(), 485 [](const auto& a, const auto& b) { return a.first < b.first; }); 486 487 std::string fstab_result; 488 for (const auto& [_, dt_entry] : fstab_dt_entries) { 489 fstab_result += dt_entry + "\n"; 490 } 491 return fstab_result; 492 } 493 494 bool is_dt_compatible() { 495 std::string file_name = get_android_dt_dir() + "/compatible"; 496 std::string dt_value; 497 if (read_dt_file(file_name, &dt_value)) { 498 if (dt_value == "android,firmware") { 499 return true; 500 } 501 } 502 503 return false; 504 } 505 506 static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file) 507 { 508 int cnt, entries; 509 ssize_t len; 510 size_t alloc_len = 0; 511 char *line = NULL; 512 const char *delim = " \t"; 513 char *save_ptr, *p; 514 struct fstab *fstab = NULL; 515 struct fs_mgr_flag_values flag_vals; 516 #define FS_OPTIONS_LEN 1024 517 char tmp_fs_options[FS_OPTIONS_LEN]; 518 519 entries = 0; 520 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) { 521 /* if the last character is a newline, shorten the string by 1 byte */ 522 if (line[len - 1] == '\n') { 523 line[len - 1] = '\0'; 524 } 525 /* Skip any leading whitespace */ 526 p = line; 527 while (isspace(*p)) { 528 p++; 529 } 530 /* ignore comments or empty lines */ 531 if (*p == '#' || *p == '\0') 532 continue; 533 entries++; 534 } 535 536 if (!entries) { 537 LERROR << "No entries found in fstab"; 538 goto err; 539 } 540 541 /* Allocate and init the fstab structure */ 542 fstab = static_cast<struct fstab *>(calloc(1, sizeof(struct fstab))); 543 fstab->num_entries = entries; 544 fstab->recs = static_cast<struct fstab_rec *>( 545 calloc(fstab->num_entries, sizeof(struct fstab_rec))); 546 547 fseek(fstab_file, 0, SEEK_SET); 548 549 cnt = 0; 550 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) { 551 /* if the last character is a newline, shorten the string by 1 byte */ 552 if (line[len - 1] == '\n') { 553 line[len - 1] = '\0'; 554 } 555 556 /* Skip any leading whitespace */ 557 p = line; 558 while (isspace(*p)) { 559 p++; 560 } 561 /* ignore comments or empty lines */ 562 if (*p == '#' || *p == '\0') 563 continue; 564 565 /* If a non-comment entry is greater than the size we allocated, give an 566 * error and quit. This can happen in the unlikely case the file changes 567 * between the two reads. 568 */ 569 if (cnt >= entries) { 570 LERROR << "Tried to process more entries than counted"; 571 break; 572 } 573 574 if (!(p = strtok_r(line, delim, &save_ptr))) { 575 LERROR << "Error parsing mount source"; 576 goto err; 577 } 578 fstab->recs[cnt].blk_device = strdup(p); 579 580 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 581 LERROR << "Error parsing mount_point"; 582 goto err; 583 } 584 fstab->recs[cnt].mount_point = strdup(p); 585 586 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 587 LERROR << "Error parsing fs_type"; 588 goto err; 589 } 590 fstab->recs[cnt].fs_type = strdup(p); 591 592 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 593 LERROR << "Error parsing mount_flags"; 594 goto err; 595 } 596 tmp_fs_options[0] = '\0'; 597 fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL, 598 tmp_fs_options, FS_OPTIONS_LEN); 599 600 /* fs_options are optional */ 601 if (tmp_fs_options[0]) { 602 fstab->recs[cnt].fs_options = strdup(tmp_fs_options); 603 } else { 604 fstab->recs[cnt].fs_options = NULL; 605 } 606 607 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 608 LERROR << "Error parsing fs_mgr_options"; 609 goto err; 610 } 611 fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, 612 &flag_vals, NULL, 0); 613 fstab->recs[cnt].key_loc = flag_vals.key_loc; 614 fstab->recs[cnt].key_dir = flag_vals.key_dir; 615 fstab->recs[cnt].verity_loc = flag_vals.verity_loc; 616 fstab->recs[cnt].length = flag_vals.part_length; 617 fstab->recs[cnt].label = flag_vals.label; 618 fstab->recs[cnt].partnum = flag_vals.partnum; 619 fstab->recs[cnt].swap_prio = flag_vals.swap_prio; 620 fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams; 621 fstab->recs[cnt].zram_size = flag_vals.zram_size; 622 fstab->recs[cnt].reserved_size = flag_vals.reserved_size; 623 fstab->recs[cnt].file_contents_mode = flag_vals.file_contents_mode; 624 fstab->recs[cnt].file_names_mode = flag_vals.file_names_mode; 625 fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size; 626 fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size; 627 fstab->recs[cnt].sysfs_path = flag_vals.sysfs_path; 628 cnt++; 629 } 630 /* If an A/B partition, modify block device to be the real block device */ 631 if (!fs_mgr_update_for_slotselect(fstab)) { 632 LERROR << "Error updating for slotselect"; 633 goto err; 634 } 635 free(line); 636 return fstab; 637 638 err: 639 free(line); 640 if (fstab) 641 fs_mgr_free_fstab(fstab); 642 return NULL; 643 } 644 645 /* merges fstab entries from both a and b, then returns the merged result. 646 * note that the caller should only manage the return pointer without 647 * doing further memory management for the two inputs, i.e. only need to 648 * frees up memory of the return value without touching a and b. */ 649 static struct fstab *in_place_merge(struct fstab *a, struct fstab *b) 650 { 651 if (!a && !b) return nullptr; 652 if (!a) return b; 653 if (!b) return a; 654 655 int total_entries = a->num_entries + b->num_entries; 656 a->recs = static_cast<struct fstab_rec *>(realloc( 657 a->recs, total_entries * (sizeof(struct fstab_rec)))); 658 if (!a->recs) { 659 LERROR << __FUNCTION__ << "(): failed to allocate fstab recs"; 660 // If realloc() fails the original block is left untouched; 661 // it is not freed or moved. So we have to free both a and b here. 662 fs_mgr_free_fstab(a); 663 fs_mgr_free_fstab(b); 664 return nullptr; 665 } 666 667 for (int i = a->num_entries, j = 0; i < total_entries; i++, j++) { 668 // Copy the structs by assignment. 669 a->recs[i] = b->recs[j]; 670 } 671 672 // We can't call fs_mgr_free_fstab because a->recs still references the 673 // memory allocated by strdup. 674 free(b->recs); 675 free(b->fstab_filename); 676 free(b); 677 678 a->num_entries = total_entries; 679 return a; 680 } 681 682 /* Extracts <device>s from the by-name symlinks specified in a fstab: 683 * /dev/block/<type>/<device>/by-name/<partition> 684 * 685 * <type> can be: platform, pci or vbd. 686 * 687 * For example, given the following entries in the input fstab: 688 * /dev/block/platform/soc/1da4000.ufshc/by-name/system 689 * /dev/block/pci/soc.0/f9824900.sdhci/by-name/vendor 690 * it returns a set { "soc/1da4000.ufshc", "soc.0/f9824900.sdhci" }. 691 */ 692 static std::set<std::string> extract_boot_devices(const fstab& fstab) { 693 std::set<std::string> boot_devices; 694 695 for (int i = 0; i < fstab.num_entries; i++) { 696 std::string blk_device(fstab.recs[i].blk_device); 697 // Skips blk_device that doesn't conform to the format. 698 if (!android::base::StartsWith(blk_device, "/dev/block") || 699 android::base::StartsWith(blk_device, "/dev/block/by-name") || 700 android::base::StartsWith(blk_device, "/dev/block/bootdevice/by-name")) { 701 continue; 702 } 703 // Skips non-by_name blk_device. 704 // /dev/block/<type>/<device>/by-name/<partition> 705 // ^ slash_by_name 706 auto slash_by_name = blk_device.find("/by-name"); 707 if (slash_by_name == std::string::npos) continue; 708 blk_device.erase(slash_by_name); // erases /by-name/<partition> 709 710 // Erases /dev/block/, now we have <type>/<device> 711 blk_device.erase(0, std::string("/dev/block/").size()); 712 713 // <type>/<device> 714 // ^ first_slash 715 auto first_slash = blk_device.find('/'); 716 if (first_slash == std::string::npos) continue; 717 718 auto boot_device = blk_device.substr(first_slash + 1); 719 if (!boot_device.empty()) boot_devices.insert(std::move(boot_device)); 720 } 721 722 return boot_devices; 723 } 724 725 struct fstab *fs_mgr_read_fstab(const char *fstab_path) 726 { 727 FILE *fstab_file; 728 struct fstab *fstab; 729 730 fstab_file = fopen(fstab_path, "r"); 731 if (!fstab_file) { 732 PERROR << __FUNCTION__<< "(): cannot open file: '" << fstab_path << "'"; 733 return nullptr; 734 } 735 736 fstab = fs_mgr_read_fstab_file(fstab_file); 737 if (fstab) { 738 fstab->fstab_filename = strdup(fstab_path); 739 } else { 740 LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'"; 741 } 742 743 fclose(fstab_file); 744 return fstab; 745 } 746 747 /* Returns fstab entries parsed from the device tree if they 748 * exist 749 */ 750 struct fstab *fs_mgr_read_fstab_dt() 751 { 752 std::string fstab_buf = read_fstab_from_dt(); 753 if (fstab_buf.empty()) { 754 LINFO << __FUNCTION__ << "(): failed to read fstab from dt"; 755 return nullptr; 756 } 757 758 std::unique_ptr<FILE, decltype(&fclose)> fstab_file( 759 fmemopen(static_cast<void*>(const_cast<char*>(fstab_buf.c_str())), 760 fstab_buf.length(), "r"), fclose); 761 if (!fstab_file) { 762 PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt"; 763 return nullptr; 764 } 765 766 struct fstab *fstab = fs_mgr_read_fstab_file(fstab_file.get()); 767 if (!fstab) { 768 LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:" 769 << std::endl << fstab_buf; 770 } 771 772 return fstab; 773 } 774 775 /* 776 * Identify path to fstab file. Lookup is based on pattern 777 * fstab.<hardware>, fstab.<hardware.platform> in folders 778 /odm/etc, vendor/etc, or /. 779 */ 780 static std::string get_fstab_path() 781 { 782 for (const char* prop : {"hardware", "hardware.platform"}) { 783 std::string hw; 784 785 if (!fs_mgr_get_boot_config(prop, &hw)) continue; 786 787 for (const char* prefix : {"/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab."}) { 788 std::string fstab_path = prefix + hw; 789 if (access(fstab_path.c_str(), F_OK) == 0) { 790 return fstab_path; 791 } 792 } 793 } 794 795 return std::string(); 796 } 797 798 /* 799 * loads the fstab file and combines with fstab entries passed in from device tree. 800 */ 801 struct fstab *fs_mgr_read_fstab_default() 802 { 803 std::string default_fstab; 804 805 // Use different fstab paths for normal boot and recovery boot, respectively 806 if (access("/sbin/recovery", F_OK) == 0) { 807 default_fstab = "/etc/recovery.fstab"; 808 } else { // normal boot 809 default_fstab = get_fstab_path(); 810 } 811 812 struct fstab* fstab = nullptr; 813 if (!default_fstab.empty()) { 814 fstab = fs_mgr_read_fstab(default_fstab.c_str()); 815 } else { 816 LINFO << __FUNCTION__ << "(): failed to find device default fstab"; 817 } 818 819 struct fstab* fstab_dt = fs_mgr_read_fstab_dt(); 820 821 // combines fstab entries passed in from device tree with 822 // the ones found from default_fstab file 823 return in_place_merge(fstab_dt, fstab); 824 } 825 826 void fs_mgr_free_fstab(struct fstab *fstab) 827 { 828 int i; 829 830 if (!fstab) { 831 return; 832 } 833 834 for (i = 0; i < fstab->num_entries; i++) { 835 /* Free the pointers return by strdup(3) */ 836 free(fstab->recs[i].blk_device); 837 free(fstab->recs[i].mount_point); 838 free(fstab->recs[i].fs_type); 839 free(fstab->recs[i].fs_options); 840 free(fstab->recs[i].key_loc); 841 free(fstab->recs[i].key_dir); 842 free(fstab->recs[i].label); 843 free(fstab->recs[i].sysfs_path); 844 } 845 846 /* Free the fstab_recs array created by calloc(3) */ 847 free(fstab->recs); 848 849 /* Free the fstab filename */ 850 free(fstab->fstab_filename); 851 852 /* Free fstab */ 853 free(fstab); 854 } 855 856 /* Add an entry to the fstab, and return 0 on success or -1 on error */ 857 int fs_mgr_add_entry(struct fstab *fstab, 858 const char *mount_point, const char *fs_type, 859 const char *blk_device) 860 { 861 struct fstab_rec *new_fstab_recs; 862 int n = fstab->num_entries; 863 864 new_fstab_recs = (struct fstab_rec *) 865 realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1)); 866 867 if (!new_fstab_recs) { 868 return -1; 869 } 870 871 /* A new entry was added, so initialize it */ 872 memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec)); 873 new_fstab_recs[n].mount_point = strdup(mount_point); 874 new_fstab_recs[n].fs_type = strdup(fs_type); 875 new_fstab_recs[n].blk_device = strdup(blk_device); 876 new_fstab_recs[n].length = 0; 877 878 /* Update the fstab struct */ 879 fstab->recs = new_fstab_recs; 880 fstab->num_entries++; 881 882 return 0; 883 } 884 885 /* 886 * Returns the fstab_rec* whose mount_point is path. 887 * Returns nullptr if not found. 888 */ 889 struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path) { 890 if (!fstab) { 891 return nullptr; 892 } 893 for (int i = 0; i < fstab->num_entries; i++) { 894 if (fstab->recs[i].mount_point && path == fstab->recs[i].mount_point) { 895 return &fstab->recs[i]; 896 } 897 } 898 return nullptr; 899 } 900 901 std::set<std::string> fs_mgr_get_boot_devices() { 902 // boot_devices can be specified in device tree. 903 std::string dt_value; 904 std::string file_name = get_android_dt_dir() + "/boot_devices"; 905 if (read_dt_file(file_name, &dt_value)) { 906 auto boot_devices = android::base::Split(dt_value, ","); 907 return std::set<std::string>(boot_devices.begin(), boot_devices.end()); 908 } 909 910 // Fallback to extract boot devices from fstab. 911 std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(), 912 fs_mgr_free_fstab); 913 if (fstab) return extract_boot_devices(*fstab); 914 915 return {}; 916 } 917 918 int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab) 919 { 920 return fstab->fs_mgr_flags & MF_VOLDMANAGED; 921 } 922 923 int fs_mgr_is_nonremovable(const struct fstab_rec *fstab) 924 { 925 return fstab->fs_mgr_flags & MF_NONREMOVABLE; 926 } 927 928 int fs_mgr_is_verified(const struct fstab_rec *fstab) 929 { 930 return fstab->fs_mgr_flags & MF_VERIFY; 931 } 932 933 int fs_mgr_is_avb(const struct fstab_rec *fstab) 934 { 935 return fstab->fs_mgr_flags & MF_AVB; 936 } 937 938 int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab) 939 { 940 return fstab->fs_mgr_flags & MF_VERIFYATBOOT; 941 } 942 943 int fs_mgr_is_encryptable(const struct fstab_rec *fstab) 944 { 945 return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE); 946 } 947 948 int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab) 949 { 950 return fstab->fs_mgr_flags & MF_FILEENCRYPTION; 951 } 952 953 void fs_mgr_get_file_encryption_modes(const struct fstab_rec *fstab, 954 const char **contents_mode_ret, 955 const char **filenames_mode_ret) 956 { 957 *contents_mode_ret = flag_to_encryption_mode(file_contents_encryption_modes, 958 fstab->file_contents_mode); 959 *filenames_mode_ret = flag_to_encryption_mode(file_names_encryption_modes, 960 fstab->file_names_mode); 961 } 962 963 int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab) 964 { 965 return fstab->fs_mgr_flags & MF_FORCEFDEORFBE; 966 } 967 968 int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab) 969 { 970 return fstab->fs_mgr_flags & MF_NOEMULATEDSD; 971 } 972 973 int fs_mgr_is_notrim(const struct fstab_rec* fstab) { 974 return fstab->fs_mgr_flags & MF_NOTRIM; 975 } 976 977 int fs_mgr_is_formattable(const struct fstab_rec* fstab) { 978 return fstab->fs_mgr_flags & (MF_FORMATTABLE); 979 } 980 981 int fs_mgr_is_slotselect(const struct fstab_rec* fstab) { 982 return fstab->fs_mgr_flags & MF_SLOTSELECT; 983 } 984 985 int fs_mgr_is_nofail(const struct fstab_rec* fstab) { 986 return fstab->fs_mgr_flags & MF_NOFAIL; 987 } 988 989 int fs_mgr_is_latemount(const struct fstab_rec* fstab) { 990 return fstab->fs_mgr_flags & MF_LATEMOUNT; 991 } 992 993 int fs_mgr_is_quota(const struct fstab_rec* fstab) { 994 return fstab->fs_mgr_flags & MF_QUOTA; 995 } 996 997 int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab) 998 { 999 return fstab->fs_mgr_flags & MF_SYSFS; 1000 } 1001