diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index aeab89381..4f6a8cec9 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -35,146 +36,37 @@ #include "fs_mgr_priv.h" +using android::base::ParseByteCount; +using android::base::ParseInt; using android::base::Split; using android::base::StartsWith; const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android"); -struct fs_mgr_flag_values { - std::string key_loc; - std::string key_dir; - std::string verity_loc; - std::string sysfs_path; - std::string zram_loopback_path; - uint64_t zram_loopback_size = 512 * 1024 * 1024; // 512MB by default - std::string zram_backing_dev_path; - off64_t part_length = 0; - std::string label; - int partnum = -1; - int swap_prio = -1; - int max_comp_streams = 0; - off64_t zram_size = 0; - off64_t reserved_size = 0; - int file_contents_mode = 0; - int file_names_mode = 0; - off64_t erase_blk_size = 0; - off64_t logical_blk_size = 0; - std::string vbmeta_partition; -}; - struct flag_list { const char *name; uint64_t flag; }; -static struct flag_list mount_flags[] = { - { "noatime", MS_NOATIME }, - { "noexec", MS_NOEXEC }, - { "nosuid", MS_NOSUID }, - { "nodev", MS_NODEV }, - { "nodiratime", MS_NODIRATIME }, - { "ro", MS_RDONLY }, - { "rw", 0 }, - { "remount", MS_REMOUNT }, - { "bind", MS_BIND }, - { "rec", MS_REC }, - { "unbindable", MS_UNBINDABLE }, - { "private", MS_PRIVATE }, - { "slave", MS_SLAVE }, - { "shared", MS_SHARED }, - { "defaults", 0 }, - { 0, 0 }, -}; - -static struct flag_list fs_mgr_flags[] = { - {"wait", MF_WAIT}, - {"check", MF_CHECK}, - {"encryptable=", MF_CRYPT}, - {"forceencrypt=", MF_FORCECRYPT}, - {"fileencryption=", MF_FILEENCRYPTION}, - {"forcefdeorfbe=", MF_FORCEFDEORFBE}, - {"keydirectory=", MF_KEYDIRECTORY}, - {"nonremovable", MF_NONREMOVABLE}, - {"voldmanaged=", MF_VOLDMANAGED}, - {"length=", MF_LENGTH}, - {"recoveryonly", MF_RECOVERYONLY}, - {"swapprio=", MF_SWAPPRIO}, - {"zramsize=", MF_ZRAMSIZE}, - {"max_comp_streams=", MF_MAX_COMP_STREAMS}, - {"verifyatboot", MF_VERIFYATBOOT}, - {"verify", MF_VERIFY}, - {"avb", MF_AVB}, - {"avb=", MF_AVB}, - {"noemulatedsd", MF_NOEMULATEDSD}, - {"notrim", MF_NOTRIM}, - {"formattable", MF_FORMATTABLE}, - {"slotselect", MF_SLOTSELECT}, - {"nofail", MF_NOFAIL}, - {"first_stage_mount", MF_FIRST_STAGE_MOUNT}, - {"latemount", MF_LATEMOUNT}, - {"reservedsize=", MF_RESERVEDSIZE}, - {"quota", MF_QUOTA}, - {"eraseblk=", MF_ERASEBLKSIZE}, - {"logicalblk=", MF_LOGICALBLKSIZE}, - {"sysfs_path=", MF_SYSFS}, +static struct flag_list mount_flags_list[] = { + {"noatime", MS_NOATIME}, + {"noexec", MS_NOEXEC}, + {"nosuid", MS_NOSUID}, + {"nodev", MS_NODEV}, + {"nodiratime", MS_NODIRATIME}, + {"ro", MS_RDONLY}, + {"rw", 0}, + {"remount", MS_REMOUNT}, + {"bind", MS_BIND}, + {"rec", MS_REC}, + {"unbindable", MS_UNBINDABLE}, + {"private", MS_PRIVATE}, + {"slave", MS_SLAVE}, + {"shared", MS_SHARED}, {"defaults", 0}, - {"logical", MF_LOGICAL}, - {"checkpoint=block", MF_CHECKPOINT_BLK}, - {"checkpoint=fs", MF_CHECKPOINT_FS}, - {"slotselect_other", MF_SLOTSELECT_OTHER}, - {"zram_loopback_path=", MF_ZRAM_LOOPBACK_PATH}, - {"zram_loopback_size=", MF_ZRAM_LOOPBACK_SIZE}, - {"zram_backing_dev_path=", MF_ZRAM_BACKING_DEV_PATH}, - {"fsverity", MF_FS_VERITY}, - {0, 0}, }; -#define EM_AES_256_XTS 1 -#define EM_ICE 2 -#define EM_AES_256_CTS 3 -#define EM_AES_256_HEH 4 -#define EM_ADIANTUM 5 - -static const struct flag_list file_contents_encryption_modes[] = { - {"aes-256-xts", EM_AES_256_XTS}, - {"adiantum", EM_ADIANTUM}, - {"software", EM_AES_256_XTS}, /* alias for backwards compatibility */ - {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */ - {0, 0}, -}; - -static const struct flag_list file_names_encryption_modes[] = { - {"aes-256-cts", EM_AES_256_CTS}, - {"aes-256-heh", EM_AES_256_HEH}, - {"adiantum", EM_ADIANTUM}, - {0, 0}, -}; - -static int encryption_mode_to_flag(const struct flag_list* list, const char* mode, - const char* type) { - const struct flag_list *j; - - for (j = list; j->name; ++j) { - if (!strcmp(mode, j->name)) { - return j->flag; - } - } - LERROR << "Unknown " << type << " encryption mode: " << mode; - return 0; -} - -static const char* flag_to_encryption_mode(const struct flag_list* list, uint64_t flag) { - const struct flag_list *j; - - for (j = list; j->name; ++j) { - if (flag == j->flag) { - return j->name; - } - } - return nullptr; -} - -static off64_t calculate_zram_size(unsigned int percentage) { +static off64_t calculate_zram_size(int percentage) { off64_t total; total = sysconf(_SC_PHYS_PAGES); @@ -186,19 +78,6 @@ static off64_t calculate_zram_size(unsigned int percentage) { return total; } -static off64_t parse_size(const char* arg) { - char *endptr; - off64_t size = strtoll(arg, &endptr, 10); - if (*endptr == 'k' || *endptr == 'K') - size *= 1024LL; - else if (*endptr == 'm' || *endptr == 'M') - size *= 1024LL * 1024LL; - else if (*endptr == 'g' || *endptr == 'G') - size *= 1024LL * 1024LL * 1024LL; - - return size; -} - /* fills 'dt_value' with the underlying device tree value string without * the trailing '\0'. Returns true if 'dt_value' has a valid string, 'false' * otherwise. @@ -217,174 +96,252 @@ static bool read_dt_file(const std::string& file_name, std::string* dt_value) return false; } -static uint64_t parse_flags(char* flags, struct flag_list* fl, struct fs_mgr_flag_values* flag_vals, - std::string* fs_options) { - uint64_t f = 0; - int i; - char *p; - char *savep; +const static std::array kFileContentsEncryptionMode = { + "aes-256-xts", + "adiantum", + "ice", +}; - p = strtok_r(flags, ",", &savep); - while (p) { - /* Look for the flag "p" in the flag list "fl" - * If not found, the loop exits with fl[i].name being null. - */ - for (i = 0; fl[i].name; i++) { - auto name = fl[i].name; - auto len = strlen(name); - auto end = len; - if (name[end - 1] == '=') --end; - if (!strncmp(p, name, len) && (p[end] == name[end])) { - f |= fl[i].flag; - if (!flag_vals) break; - if (p[end] != '=') break; - char* arg = p + end + 1; - auto flag = fl[i].flag; - if (flag == MF_CRYPT) { - /* The encryptable flag is followed by an = and the - * location of the keys. Get it and return it. - */ - flag_vals->key_loc = arg; - } else if (flag == MF_VERIFY) { - /* If the verify flag is followed by an = and the - * location for the verity state, get it and return it. - */ - flag_vals->verity_loc = arg; - } else if (flag == MF_FORCECRYPT) { - /* The forceencrypt flag is followed by an = and the - * location of the keys. Get it and return it. - */ - flag_vals->key_loc = arg; - } else if (flag == MF_FORCEFDEORFBE) { - /* The forcefdeorfbe flag is followed by an = and the - * location of the keys. Get it and return it. - */ - flag_vals->key_loc = arg; - flag_vals->file_contents_mode = EM_AES_256_XTS; - flag_vals->file_names_mode = EM_AES_256_CTS; - } else if (flag == MF_FILEENCRYPTION) { - /* The fileencryption flag is followed by an = and - * the mode of contents encryption, then optionally a - * : and the mode of filenames encryption (defaults - * to aes-256-cts). Get it and return it. - */ - auto mode = arg; - auto colon = strchr(mode, ':'); - if (colon) { - *colon = '\0'; - } - flag_vals->file_contents_mode = - encryption_mode_to_flag(file_contents_encryption_modes, - mode, "file contents"); - if (colon) { - flag_vals->file_names_mode = - encryption_mode_to_flag(file_names_encryption_modes, - colon + 1, "file names"); - } else if (flag_vals->file_contents_mode == EM_ADIANTUM) { - flag_vals->file_names_mode = EM_ADIANTUM; - } else { - flag_vals->file_names_mode = EM_AES_256_CTS; - } - } else if (flag == MF_KEYDIRECTORY) { - /* The metadata flag is followed by an = and the - * directory for the keys. Get it and return it. - */ - flag_vals->key_dir = arg; - } else if (flag == MF_LENGTH) { - /* The length flag is followed by an = and the - * size of the partition. Get it and return it. - */ - flag_vals->part_length = strtoll(arg, NULL, 0); - } else if (flag == MF_VOLDMANAGED) { - /* The voldmanaged flag is followed by an = and the - * label, a colon and the partition number or the - * word "auto", e.g. - * voldmanaged=sdcard:3 - * Get and return them. - */ - auto label_start = arg; - auto label_end = strchr(label_start, ':'); +const static std::array kFileNamesEncryptionMode = { + "aes-256-cts", + "aes-256-heh", + "adiantum", +}; - if (label_end) { - flag_vals->label = std::string(label_start, (int)(label_end - label_start)); - auto part_start = label_end + 1; - if (!strcmp(part_start, "auto")) { - flag_vals->partnum = -1; - } else { - flag_vals->partnum = strtol(part_start, NULL, 0); - } - } else { - LERROR << "Warning: voldmanaged= flag malformed"; - } - } else if (flag == MF_SWAPPRIO) { - flag_vals->swap_prio = strtoll(arg, NULL, 0); - } else if (flag == MF_MAX_COMP_STREAMS) { - flag_vals->max_comp_streams = strtoll(arg, NULL, 0); - } else if (flag == MF_AVB) { - flag_vals->vbmeta_partition = arg; - } else if (flag == MF_ZRAMSIZE) { - auto is_percent = !!strrchr(arg, '%'); - auto val = strtoll(arg, NULL, 0); - if (is_percent) - flag_vals->zram_size = calculate_zram_size(val); - else - flag_vals->zram_size = val; - } else if (flag == MF_RESERVEDSIZE) { - /* The reserved flag is followed by an = and the - * reserved size of the partition. Get it and return it. - */ - flag_vals->reserved_size = parse_size(arg); - } else if (flag == MF_ERASEBLKSIZE) { - /* The erase block size flag is followed by an = and the flash - * erase block size. Get it, check that it is a power of 2 and - * at least 4096, and return it. - */ - auto val = strtoll(arg, nullptr, 0); - if (val >= 4096 && (val & (val - 1)) == 0) - flag_vals->erase_blk_size = val; - } else if (flag == MF_LOGICALBLKSIZE) { - /* The logical block size flag is followed by an = and the flash - * logical block size. Get it, check that it is a power of 2 and - * at least 4096, and return it. - */ - auto val = strtoll(arg, nullptr, 0); - if (val >= 4096 && (val & (val - 1)) == 0) - flag_vals->logical_blk_size = val; - } else if (flag == MF_SYSFS) { - /* The path to trigger device gc by idle-maint of vold. */ - flag_vals->sysfs_path = arg; - } else if (flag == MF_ZRAM_LOOPBACK_PATH) { - /* The path to use loopback for zram. */ - flag_vals->zram_loopback_path = arg; - } else if (flag == MF_ZRAM_LOOPBACK_SIZE) { - if (!android::base::ParseByteCount(arg, &flag_vals->zram_loopback_size)) { - LERROR << "Warning: zram_loopback_size = flag malformed"; - } - } else if (flag == MF_ZRAM_BACKING_DEV_PATH) { - /* The path to use loopback for zram. */ - flag_vals->zram_backing_dev_path = arg; - } - break; - } - } +static void ParseFileEncryption(const std::string& arg, FstabEntry* entry) { + // The fileencryption flag is followed by an = and the mode of contents encryption, then + // optionally a and the mode of filenames encryption (defaults to aes-256-cts). Get it and + // return it. + entry->fs_mgr_flags.file_encryption = true; - if (!fl[i].name) { - if (fs_options) { - // It's not a known flag, so it must be a filesystem specific - // option. Add it to fs_options if it was passed in. - if (!fs_options->empty()) { - fs_options->append(","); // appends a comma if not the first - } - fs_options->append(p); - } else { - // fs_options was not passed in, so if the flag is unknown it's an error. - LERROR << "Warning: unknown flag " << p; - } - } - p = strtok_r(NULL, ",", &savep); + auto parts = Split(arg, ":"); + if (parts.empty() || parts.size() > 2) { + LWARNING << "Warning: fileencryption= flag malformed: " << arg; + return; } - return f; + // Alias for backwards compatibility. + if (parts[0] == "software") { + parts[0] = "aes-256-xts"; + } + + if (std::find(kFileContentsEncryptionMode.begin(), kFileContentsEncryptionMode.end(), + parts[0]) == kFileContentsEncryptionMode.end()) { + LWARNING << "fileencryption= flag malformed, file contents encryption mode not found: " + << arg; + return; + } + + entry->file_contents_mode = parts[0]; + + if (parts.size() == 2) { + if (std::find(kFileNamesEncryptionMode.begin(), kFileNamesEncryptionMode.end(), parts[1]) == + kFileNamesEncryptionMode.end()) { + LWARNING << "fileencryption= flag malformed, file names encryption mode not found: " + << arg; + return; + } + + entry->file_names_mode = parts[1]; + } else if (entry->file_contents_mode == "adiantum") { + entry->file_names_mode = "adiantum"; + } else { + entry->file_names_mode = "aes-256-cts"; + } +} + +static bool SetMountFlag(const std::string& flag, FstabEntry* entry) { + for (const auto& [name, value] : mount_flags_list) { + if (flag == name) { + entry->flags |= value; + return true; + } + } + return false; +} + +static void ParseMountFlags(const std::string& flags, FstabEntry* entry) { + std::string fs_options; + for (const auto& flag : Split(flags, ",")) { + if (!SetMountFlag(flag, entry)) { + // Unknown flag, so it must be a filesystem specific option. + if (!fs_options.empty()) { + fs_options.append(","); // appends a comma if not the first + } + fs_options.append(flag); + } + } + entry->fs_options = std::move(fs_options); +} + +static void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) { + entry->fs_mgr_flags.val = 0U; + for (const auto& flag : Split(flags, ",")) { + std::string arg; + if (auto equal_sign = flag.find('='); equal_sign != std::string::npos) { + arg = flag.substr(equal_sign + 1); + } + + // First handle flags that simply set a boolean. +#define CheckFlag(flag_name, value) \ + if (flag == flag_name) { \ + entry->fs_mgr_flags.value = true; \ + continue; \ + } + + CheckFlag("wait", wait); + CheckFlag("check", check); + CheckFlag("nonremovable", nonremovable); + CheckFlag("recoveryonly", recovery_only); + CheckFlag("noemulatedsd", no_emulated_sd); + CheckFlag("notrim", no_trim); + CheckFlag("verify", verify); + CheckFlag("formattable", formattable); + CheckFlag("slotselect", slot_select); + CheckFlag("latemount", late_mount); + CheckFlag("nofail", no_fail); + CheckFlag("verifyatboot", verify_at_boot); + CheckFlag("quota", quota); + CheckFlag("avb", avb); + CheckFlag("logical", logical); + CheckFlag("checkpoint=block", checkpoint_blk); + CheckFlag("checkpoint=fs", checkpoint_fs); + CheckFlag("first_stage_mount", first_stage_mount); + CheckFlag("slotselect_other", slot_select_other); + CheckFlag("fsverity", fs_verity); + +#undef CheckFlag + + // Then handle flags that take an argument. + if (StartsWith(flag, "encryptable=")) { + // The encryptable flag is followed by an = and the location of the keys. + entry->fs_mgr_flags.crypt = true; + entry->key_loc = arg; + } else if (StartsWith(flag, "voldmanaged=")) { + // The voldmanaged flag is followed by an = and the label, a colon and the partition + // number or the word "auto", e.g. voldmanaged=sdcard:3 + entry->fs_mgr_flags.vold_managed = true; + auto parts = Split(arg, ":"); + if (parts.size() != 2) { + LWARNING << "Warning: voldmanaged= flag malformed: " << arg; + continue; + } + + entry->label = std::move(parts[0]); + if (parts[1] == "auto") { + entry->partnum = -1; + } else { + if (!ParseInt(parts[1], &entry->partnum)) { + entry->partnum = -1; + LWARNING << "Warning: voldmanaged= flag malformed: " << arg; + continue; + } + } + } else if (StartsWith(flag, "length=")) { + // The length flag is followed by an = and the size of the partition. + entry->fs_mgr_flags.length = true; + if (!ParseInt(arg, &entry->length)) { + LWARNING << "Warning: length= flag malformed: " << arg; + } + } else if (StartsWith(flag, "swapprio=")) { + entry->fs_mgr_flags.swap_prio = true; + if (!ParseInt(arg, &entry->swap_prio)) { + LWARNING << "Warning: length= flag malformed: " << arg; + } + } else if (StartsWith(flag, "zramsize=")) { + entry->fs_mgr_flags.zram_size = true; + + if (!arg.empty() && arg.back() == '%') { + arg.pop_back(); + int val; + if (ParseInt(arg, &val, 0, 100)) { + entry->zram_size = calculate_zram_size(val); + } else { + LWARNING << "Warning: zramsize= flag malformed: " << arg; + } + } else { + if (!ParseInt(arg, &entry->zram_size)) { + LWARNING << "Warning: zramsize= flag malformed: " << arg; + } + } + } else if (StartsWith(flag, "verify=")) { + // If the verify flag is followed by an = and the location for the verity state. + entry->fs_mgr_flags.verify = true; + entry->verity_loc = arg; + } else if (StartsWith(flag, "forceencrypt=")) { + // The forceencrypt flag is followed by an = and the location of the keys. + entry->fs_mgr_flags.force_crypt = true; + entry->key_loc = arg; + } else if (StartsWith(flag, "fileencryption=")) { + ParseFileEncryption(arg, entry); + } else if (StartsWith(flag, "forcefdeorfbe=")) { + // The forcefdeorfbe flag is followed by an = and the location of the keys. Get it and + // return it. + entry->fs_mgr_flags.force_fde_or_fbe = true; + entry->key_loc = arg; + entry->file_contents_mode = "aes-256-xts"; + entry->file_names_mode = "aes-256-cts"; + } else if (StartsWith(flag, "max_comp_streams=")) { + entry->fs_mgr_flags.max_comp_streams = true; + if (!ParseInt(arg, &entry->max_comp_streams)) { + LWARNING << "Warning: max_comp_streams= flag malformed: " << arg; + } + } else if (StartsWith(flag, "reservedsize=")) { + // The reserved flag is followed by an = and the reserved size of the partition. + entry->fs_mgr_flags.reserved_size = true; + uint64_t size; + if (!ParseByteCount(arg, &size)) { + LWARNING << "Warning: reservedsize= flag malformed: " << arg; + } else { + entry->reserved_size = static_cast(size); + } + } else if (StartsWith(flag, "eraseblk=")) { + // The erase block size flag is followed by an = and the flash erase block size. Get it, + // check that it is a power of 2 and at least 4096, and return it. + entry->fs_mgr_flags.erase_blk_size = true; + off64_t val; + if (!ParseInt(arg, &val) || val < 4096 || (val & (val - 1)) != 0) { + LWARNING << "Warning: eraseblk= flag malformed: " << arg; + } else { + entry->erase_blk_size = val; + } + } else if (StartsWith(flag, "logicalblk=")) { + // The logical block size flag is followed by an = and the flash logical block size. Get + // it, check that it is a power of 2 and at least 4096, and return it. + entry->fs_mgr_flags.logical_blk_size = true; + off64_t val; + if (!ParseInt(arg, &val) || val < 4096 || (val & (val - 1)) != 0) { + LWARNING << "Warning: logicalblk= flag malformed: " << arg; + } else { + entry->logical_blk_size = val; + } + } else if (StartsWith(flag, "avb")) { + entry->fs_mgr_flags.avb = true; + entry->vbmeta_partition = arg; + } else if (StartsWith(flag, "keydirectory=")) { + // The metadata flag is followed by an = and the directory for the keys. + entry->fs_mgr_flags.key_directory = true; + entry->key_dir = arg; + } else if (StartsWith(flag, "sysfs_path=")) { + // The path to trigger device gc by idle-maint of vold. + entry->fs_mgr_flags.sysfs = true; + entry->sysfs_path = arg; + } else if (StartsWith(flag, "zram_loopback_path=")) { + // The path to use loopback for zram. + entry->fs_mgr_flags.zram_loopback_path = true; + entry->zram_loopback_path = arg; + } else if (StartsWith(flag, "zram_loopback_size=")) { + entry->fs_mgr_flags.zram_loopback_size = true; + if (!ParseByteCount(arg, &entry->zram_loopback_size)) { + LWARNING << "Warning: zram_loopback_size= flag malformed: " << arg; + } + } else if (StartsWith(flag, "zram_backing_dev_path=")) { + entry->fs_mgr_flags.zram_backing_dev_path = true; + entry->zram_backing_dev_path = arg; + } else { + LWARNING << "Warning: unknown flag: " << flag; + } + } } static std::string init_android_dt_dir() { @@ -520,7 +477,6 @@ static bool fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts, Fstab* fs const char *delim = " \t"; char *save_ptr, *p; Fstab fstab; - struct fs_mgr_flag_values flag_vals; while ((len = getline(&line, &alloc_len, fstab_file)) != -1) { /* if the last character is a newline, shorten the string by 1 byte */ @@ -561,7 +517,8 @@ static bool fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts, Fstab* fs LERROR << "Error parsing mount_flags"; goto err; } - entry.flags = parse_flags(p, mount_flags, nullptr, &entry.fs_options); + + ParseMountFlags(p, &entry); // For /proc/mounts, ignore everything after mnt_freq and mnt_passno if (proc_mounts) { @@ -570,27 +527,9 @@ static bool fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts, Fstab* fs LERROR << "Error parsing fs_mgr_options"; goto err; } - entry.fs_mgr_flags.val = parse_flags(p, fs_mgr_flags, &flag_vals, nullptr); - entry.key_loc = std::move(flag_vals.key_loc); - entry.key_dir = std::move(flag_vals.key_dir); - entry.verity_loc = std::move(flag_vals.verity_loc); - entry.length = flag_vals.part_length; - entry.label = std::move(flag_vals.label); - entry.partnum = flag_vals.partnum; - entry.swap_prio = flag_vals.swap_prio; - entry.max_comp_streams = flag_vals.max_comp_streams; - entry.zram_size = flag_vals.zram_size; - entry.reserved_size = flag_vals.reserved_size; - entry.file_contents_mode = flag_vals.file_contents_mode; - entry.file_names_mode = flag_vals.file_names_mode; - entry.erase_blk_size = flag_vals.erase_blk_size; - entry.logical_blk_size = flag_vals.logical_blk_size; - entry.sysfs_path = std::move(flag_vals.sysfs_path); - entry.vbmeta_partition = std::move(flag_vals.vbmeta_partition); - entry.zram_loopback_path = std::move(flag_vals.zram_loopback_path); - entry.zram_loopback_size = std::move(flag_vals.zram_loopback_size); - entry.zram_backing_dev_path = std::move(flag_vals.zram_backing_dev_path); + ParseFsMgrFlags(p, &entry); + if (entry.fs_mgr_flags.logical) { entry.logical_partition_name = entry.blk_device; } @@ -834,6 +773,8 @@ void fs_mgr_free_fstab(struct fstab *fstab) free(fstab->recs[i].key_loc); free(fstab->recs[i].key_dir); free(fstab->recs[i].label); + free(fstab->recs[i].file_contents_mode); + free(fstab->recs[i].file_names_mode); free(fstab->recs[i].sysfs_path); free(fstab->recs[i].zram_loopback_path); free(fstab->recs[i].zram_backing_dev_path); @@ -975,8 +916,8 @@ fstab* FstabToLegacyFstab(const Fstab& fstab) { legacy_fstab->recs[i].max_comp_streams = fstab[i].max_comp_streams; legacy_fstab->recs[i].zram_size = fstab[i].zram_size; legacy_fstab->recs[i].reserved_size = fstab[i].reserved_size; - legacy_fstab->recs[i].file_contents_mode = fstab[i].file_contents_mode; - legacy_fstab->recs[i].file_names_mode = fstab[i].file_names_mode; + legacy_fstab->recs[i].file_contents_mode = strdup(fstab[i].file_contents_mode.c_str()); + legacy_fstab->recs[i].file_names_mode = strdup(fstab[i].file_names_mode.c_str()); legacy_fstab->recs[i].erase_blk_size = fstab[i].erase_blk_size; legacy_fstab->recs[i].logical_blk_size = fstab[i].logical_blk_size; legacy_fstab->recs[i].sysfs_path = strdup(fstab[i].sysfs_path.c_str()); @@ -1022,14 +963,10 @@ int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab) return fstab->fs_mgr_flags & MF_FILEENCRYPTION; } -void fs_mgr_get_file_encryption_modes(const struct fstab_rec *fstab, - const char **contents_mode_ret, - const char **filenames_mode_ret) -{ - *contents_mode_ret = flag_to_encryption_mode(file_contents_encryption_modes, - fstab->file_contents_mode); - *filenames_mode_ret = flag_to_encryption_mode(file_names_encryption_modes, - fstab->file_names_mode); +void fs_mgr_get_file_encryption_modes(const struct fstab_rec* fstab, const char** contents_mode_ret, + const char** filenames_mode_ret) { + *contents_mode_ret = fstab->file_contents_mode; + *filenames_mode_ret = fstab->file_names_mode; } int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab) diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h index 9c4d2da66..88ecec0d2 100644 --- a/fs_mgr/include_fstab/fstab/fstab.h +++ b/fs_mgr/include_fstab/fstab/fstab.h @@ -54,8 +54,8 @@ struct fstab_rec { int max_comp_streams; off64_t zram_size; off64_t reserved_size; - int file_contents_mode; - int file_names_mode; + char* file_contents_mode; + char* file_names_mode; off64_t erase_blk_size; off64_t logical_blk_size; char* sysfs_path; @@ -118,19 +118,19 @@ struct FstabEntry { int max_comp_streams = 0; off64_t zram_size = 0; off64_t reserved_size = 0; - int file_contents_mode = 0; - int file_names_mode = 0; + std::string file_contents_mode; + std::string file_names_mode; off64_t erase_blk_size = 0; off64_t logical_blk_size = 0; std::string sysfs_path; std::string vbmeta_partition; std::string zram_loopback_path; - uint64_t zram_loopback_size; + uint64_t zram_loopback_size = 512 * 1024 * 1024; // 512MB by default; std::string zram_backing_dev_path; // TODO: Remove this union once fstab_rec is deprecated. It only serves as a // convenient way to convert between fstab_rec::fs_mgr_flags and these bools. - union { + union FsMgrFlags { uint64_t val; struct { // bit 0 diff --git a/fs_mgr/tests/data/fstab.example b/fs_mgr/tests/data/fstab.example index 1a3dfa11b..aebce32f6 100644 --- a/fs_mgr/tests/data/fstab.example +++ b/fs_mgr/tests/data/fstab.example @@ -9,3 +9,7 @@ /dev/block/bootdevice/by-name/modem /vendor/firmware_mnt vfat ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait,slotselect /devices/platform/soc/a600000.ssusb/a600000.dwc3* auto vfat defaults voldmanaged=usb:auto /dev/block/zram0 none swap defaults zramsize=1073741824,max_comp_streams=8 +/dev/block/zram0 none2 swap nodiratime,remount,bind zramsize=1073741824,max_comp_streams=8 +/dev/block/zram0 none3 swap unbindable,private,slave zramsize=1073741824,max_comp_streams=8 +/dev/block/zram0 none4 swap noexec,shared,rec zramsize=1073741824,max_comp_streams=8 +/dev/block/zram0 none5 swap rw zramsize=1073741824,max_comp_streams=8 diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp index 458240198..e2b283ae1 100644 --- a/fs_mgr/tests/fs_mgr_test.cpp +++ b/fs_mgr/tests/fs_mgr_test.cpp @@ -201,32 +201,823 @@ TEST(fs_mgr, fs_mgr_read_fstab_file_proc_mounts) { EXPECT_EQ(i, fstab.size()); } -TEST(fs_mgr, ReadFstabFromFile_FsOptions) { +TEST(fs_mgr, ReadFstabFromFile_MountOptions) { Fstab fstab; std::string fstab_file = android::base::GetExecutableDirectory() + "/data/fstab.example"; EXPECT_TRUE(ReadFstabFromFile(fstab_file, &fstab)); EXPECT_EQ("/", fstab[0].mount_point); + EXPECT_EQ(static_cast(MS_RDONLY), fstab[0].flags); EXPECT_EQ("barrier=1", fstab[0].fs_options); EXPECT_EQ("/metadata", fstab[1].mount_point); + EXPECT_EQ(static_cast(MS_NOATIME | MS_NOSUID | MS_NODEV), fstab[1].flags); EXPECT_EQ("discard", fstab[1].fs_options); EXPECT_EQ("/data", fstab[2].mount_point); + EXPECT_EQ(static_cast(MS_NOATIME | MS_NOSUID | MS_NODEV), fstab[2].flags); EXPECT_EQ("discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier", fstab[2].fs_options); EXPECT_EQ("/misc", fstab[3].mount_point); + EXPECT_EQ(0U, fstab[3].flags); EXPECT_EQ("", fstab[3].fs_options); EXPECT_EQ("/vendor/firmware_mnt", fstab[4].mount_point); + EXPECT_EQ(static_cast(MS_RDONLY), fstab[4].flags); EXPECT_EQ( "shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337," "context=u:object_r:firmware_file:s0", fstab[4].fs_options); EXPECT_EQ("auto", fstab[5].mount_point); + EXPECT_EQ(0U, fstab[5].flags); EXPECT_EQ("", fstab[5].fs_options); EXPECT_EQ("none", fstab[6].mount_point); + EXPECT_EQ(0U, fstab[6].flags); EXPECT_EQ("", fstab[6].fs_options); + + EXPECT_EQ("none2", fstab[7].mount_point); + EXPECT_EQ(static_cast(MS_NODIRATIME | MS_REMOUNT | MS_BIND), fstab[7].flags); + EXPECT_EQ("", fstab[7].fs_options); + + EXPECT_EQ("none3", fstab[8].mount_point); + EXPECT_EQ(static_cast(MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE), fstab[8].flags); + EXPECT_EQ("", fstab[8].fs_options); + + EXPECT_EQ("none4", fstab[9].mount_point); + EXPECT_EQ(static_cast(MS_NOEXEC | MS_SHARED | MS_REC), fstab[9].flags); + EXPECT_EQ("", fstab[9].fs_options); + + EXPECT_EQ("none5", fstab[10].mount_point); + EXPECT_EQ(0U, fstab[10].flags); // rw is the same as defaults + EXPECT_EQ("", fstab[10].fs_options); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrFlags) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults wait,check,nonremovable,recoveryonly,verifyatboot,verify +source none1 swap defaults avb,noemulatedsd,notrim,formattable,slotselect,nofail +source none2 swap defaults first_stage_mount,latemount,quota,logical,slotselect_other +source none3 swap defaults checkpoint=block +source none4 swap defaults checkpoint=fs +source none5 swap defaults defaults +)fs"; + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(6U, fstab.size()); + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + { + FstabEntry::FsMgrFlags flags = {0}; + flags.wait = true; + flags.check = true; + flags.nonremovable = true; + flags.recovery_only = true; + flags.verify_at_boot = true; + flags.verify = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + } + entry++; + + EXPECT_EQ("none1", entry->mount_point); + { + FstabEntry::FsMgrFlags flags = {0}; + flags.avb = true; + flags.no_emulated_sd = true; + flags.no_trim = true; + flags.formattable = true; + flags.slot_select = true; + flags.no_fail = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + } + entry++; + + EXPECT_EQ("none2", entry->mount_point); + { + FstabEntry::FsMgrFlags flags = {0}; + flags.first_stage_mount = true; + flags.late_mount = true; + flags.quota = true; + flags.logical = true; + flags.slot_select_other = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + } + entry++; + + EXPECT_EQ("none3", entry->mount_point); + { + FstabEntry::FsMgrFlags flags = {0}; + flags.checkpoint_blk = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + } + entry++; + + EXPECT_EQ("none4", entry->mount_point); + { + FstabEntry::FsMgrFlags flags = {0}; + flags.checkpoint_fs = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + } + entry++; + + EXPECT_EQ("none5", entry->mount_point); + { + FstabEntry::FsMgrFlags flags = {0}; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + } +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_AllBad) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults encryptable,forceencrypt,fileencryption,forcefdeorfbe,keydirectory,length,swapprio,zramsize,max_comp_streams,reservedsize,eraseblk,logicalblk,sysfs_path,zram_loopback_path,zram_loopback_size,zram_backing_dev_path + +source none1 swap defaults encryptable=,forceencrypt=,fileencryption=,keydirectory=,length=,swapprio=,zramsize=,max_comp_streams=,verify=,avb=,reservedsize=,eraseblk=,logicalblk=,sysfs_path=,zram_loopback_path=,zram_loopback_size=,zram_backing_dev_path= + +source none2 swap defaults forcefdeorfbe= + +)fs"; + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(3U, fstab.size()); + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + { + FstabEntry::FsMgrFlags flags = {0}; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + } + EXPECT_EQ("", entry->key_loc); + EXPECT_EQ("", entry->key_dir); + EXPECT_EQ("", entry->verity_loc); + EXPECT_EQ(0, entry->length); + EXPECT_EQ("", entry->label); + EXPECT_EQ(-1, entry->partnum); + EXPECT_EQ(-1, entry->swap_prio); + EXPECT_EQ(0, entry->max_comp_streams); + EXPECT_EQ(0, entry->zram_size); + EXPECT_EQ(0, entry->reserved_size); + EXPECT_EQ("", entry->file_contents_mode); + EXPECT_EQ("", entry->file_names_mode); + EXPECT_EQ(0, entry->erase_blk_size); + EXPECT_EQ(0, entry->logical_blk_size); + EXPECT_EQ("", entry->sysfs_path); + EXPECT_EQ("", entry->zram_loopback_path); + EXPECT_EQ(512U * 1024U * 1024U, entry->zram_loopback_size); + EXPECT_EQ("", entry->zram_backing_dev_path); + entry++; + + EXPECT_EQ("none1", entry->mount_point); + { + FstabEntry::FsMgrFlags flags = {0}; + flags.crypt = true; + flags.force_crypt = true; + flags.file_encryption = true; + flags.key_directory = true; + flags.length = true; + flags.swap_prio = true; + flags.zram_size = true; + flags.max_comp_streams = true; + flags.verify = true; + flags.avb = true; + flags.reserved_size = true; + flags.erase_blk_size = true; + flags.logical_blk_size = true; + flags.sysfs = true; + flags.zram_loopback_path = true; + flags.zram_loopback_size = true; + flags.zram_backing_dev_path = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + } + EXPECT_EQ("", entry->key_loc); + EXPECT_EQ("", entry->key_dir); + EXPECT_EQ("", entry->verity_loc); + EXPECT_EQ(0, entry->length); + EXPECT_EQ("", entry->label); + EXPECT_EQ(-1, entry->partnum); + EXPECT_EQ(-1, entry->swap_prio); + EXPECT_EQ(0, entry->max_comp_streams); + EXPECT_EQ(0, entry->zram_size); + EXPECT_EQ(0, entry->reserved_size); + EXPECT_EQ("", entry->file_contents_mode); + EXPECT_EQ("", entry->file_names_mode); + EXPECT_EQ(0, entry->erase_blk_size); + EXPECT_EQ(0, entry->logical_blk_size); + EXPECT_EQ("", entry->sysfs_path); + EXPECT_EQ("", entry->zram_loopback_path); + EXPECT_EQ(512U * 1024U * 1024U, entry->zram_loopback_size); + EXPECT_EQ("", entry->zram_backing_dev_path); + entry++; + + // forcefdeorfbe sets file_contents_mode and file_names_mode by default, so test it separately. + EXPECT_EQ("none2", entry->mount_point); + { + FstabEntry::FsMgrFlags flags = {0}; + flags.force_fde_or_fbe = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + } + EXPECT_EQ("aes-256-xts", entry->file_contents_mode); + EXPECT_EQ("aes-256-cts", entry->file_names_mode); + EXPECT_EQ("", entry->key_loc); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Encryptable) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults encryptable=/dir/key +)fs"; + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(1U, fstab.size()); + + FstabEntry::FsMgrFlags flags = {0}; + flags.crypt = true; + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("/dir/key", entry->key_loc); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_VoldManaged) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults voldmanaged=: +source none1 swap defaults voldmanaged=sdcard +source none2 swap defaults voldmanaged=sdcard:3 +source none3 swap defaults voldmanaged=sdcard:auto +)fs"; + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(4U, fstab.size()); + + FstabEntry::FsMgrFlags flags = {0}; + flags.vold_managed = true; + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_TRUE(entry->label.empty()); + EXPECT_EQ(-1, entry->partnum); + entry++; + + EXPECT_EQ("none1", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_TRUE(entry->label.empty()); + EXPECT_EQ(-1, entry->partnum); + entry++; + + EXPECT_EQ("none2", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("sdcard", entry->label); + EXPECT_EQ(3, entry->partnum); + entry++; + + EXPECT_EQ("none3", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("sdcard", entry->label); + EXPECT_EQ(-1, entry->partnum); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Length) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults length=blah +source none1 swap defaults length=123456 +)fs"; + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(2U, fstab.size()); + + FstabEntry::FsMgrFlags flags = {0}; + flags.length = true; + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->length); + entry++; + + EXPECT_EQ("none1", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(123456, entry->length); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Swapprio) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults swapprio=blah +source none1 swap defaults swapprio=123456 +)fs"; + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(2U, fstab.size()); + + FstabEntry::FsMgrFlags flags = {0}; + flags.swap_prio = true; + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(-1, entry->swap_prio); + entry++; + + EXPECT_EQ("none1", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(123456, entry->swap_prio); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_ZramSize) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults zramsize=blah +source none1 swap defaults zramsize=123456 +source none2 swap defaults zramsize=blah% +source none3 swap defaults zramsize=5% +source none4 swap defaults zramsize=105% +source none5 swap defaults zramsize=% +)fs"; + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(6U, fstab.size()); + + FstabEntry::FsMgrFlags flags = {0}; + flags.zram_size = true; + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->zram_size); + entry++; + + EXPECT_EQ("none1", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(123456, entry->zram_size); + entry++; + + EXPECT_EQ("none2", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->zram_size); + entry++; + + EXPECT_EQ("none3", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_NE(0, entry->zram_size); + entry++; + + EXPECT_EQ("none4", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->zram_size); + entry++; + + EXPECT_EQ("none5", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->zram_size); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Verify) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults verify=/dir/key +)fs"; + + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(1U, fstab.size()); + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + + FstabEntry::FsMgrFlags flags = {0}; + flags.verify = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + + EXPECT_EQ("/dir/key", entry->verity_loc); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_ForceEncrypt) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults forceencrypt=/dir/key +)fs"; + + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(1U, fstab.size()); + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + + FstabEntry::FsMgrFlags flags = {0}; + flags.force_crypt = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + + EXPECT_EQ("/dir/key", entry->key_loc); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_ForceFdeOrFbe) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults forcefdeorfbe=/dir/key +)fs"; + + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(1U, fstab.size()); + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + + FstabEntry::FsMgrFlags flags = {0}; + flags.force_fde_or_fbe = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + + EXPECT_EQ("/dir/key", entry->key_loc); + EXPECT_EQ("aes-256-xts", entry->file_contents_mode); + EXPECT_EQ("aes-256-cts", entry->file_names_mode); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_FileEncryption) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults fileencryption=blah +source none1 swap defaults fileencryption=software +source none2 swap defaults fileencryption=aes-256-xts +source none3 swap defaults fileencryption=adiantum +source none4 swap defaults fileencryption=adiantum:aes-256-heh +source none5 swap defaults fileencryption=ice +source none6 swap defaults fileencryption=ice:blah +source none7 swap defaults fileencryption=ice:aes-256-cts +source none8 swap defaults fileencryption=ice:aes-256-heh +source none9 swap defaults fileencryption=ice:adiantum +source none10 swap defaults fileencryption=ice:adiantum: +)fs"; + + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(11U, fstab.size()); + + FstabEntry::FsMgrFlags flags = {0}; + flags.file_encryption = true; + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("", entry->file_contents_mode); + EXPECT_EQ("", entry->file_names_mode); + + entry++; + EXPECT_EQ("none1", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("aes-256-xts", entry->file_contents_mode); + EXPECT_EQ("aes-256-cts", entry->file_names_mode); + + entry++; + EXPECT_EQ("none2", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("aes-256-xts", entry->file_contents_mode); + EXPECT_EQ("aes-256-cts", entry->file_names_mode); + + entry++; + EXPECT_EQ("none3", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("adiantum", entry->file_contents_mode); + EXPECT_EQ("adiantum", entry->file_names_mode); + + entry++; + EXPECT_EQ("none4", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("adiantum", entry->file_contents_mode); + EXPECT_EQ("aes-256-heh", entry->file_names_mode); + + entry++; + EXPECT_EQ("none5", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("ice", entry->file_contents_mode); + EXPECT_EQ("aes-256-cts", entry->file_names_mode); + + entry++; + EXPECT_EQ("none6", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("ice", entry->file_contents_mode); + EXPECT_EQ("", entry->file_names_mode); + + entry++; + EXPECT_EQ("none7", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("ice", entry->file_contents_mode); + EXPECT_EQ("aes-256-cts", entry->file_names_mode); + + entry++; + EXPECT_EQ("none8", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("ice", entry->file_contents_mode); + EXPECT_EQ("aes-256-heh", entry->file_names_mode); + + entry++; + EXPECT_EQ("none9", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("ice", entry->file_contents_mode); + EXPECT_EQ("adiantum", entry->file_names_mode); + + entry++; + EXPECT_EQ("none10", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ("", entry->file_contents_mode); + EXPECT_EQ("", entry->file_names_mode); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_MaxCompStreams) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults max_comp_streams=blah +source none1 swap defaults max_comp_streams=123456 +)fs"; + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(2U, fstab.size()); + + FstabEntry::FsMgrFlags flags = {0}; + flags.max_comp_streams = true; + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->max_comp_streams); + entry++; + + EXPECT_EQ("none1", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(123456, entry->max_comp_streams); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_ReservedSize) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults reservedsize=blah +source none1 swap defaults reservedsize=2 +source none2 swap defaults reservedsize=1K +source none3 swap defaults reservedsize=2m +)fs"; + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(4U, fstab.size()); + + FstabEntry::FsMgrFlags flags = {0}; + flags.reserved_size = true; + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->reserved_size); + entry++; + + EXPECT_EQ("none1", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(2, entry->reserved_size); + entry++; + + EXPECT_EQ("none2", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(1024, entry->reserved_size); + entry++; + + EXPECT_EQ("none3", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(2 * 1024 * 1024, entry->reserved_size); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_EraseBlk) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults eraseblk=blah +source none1 swap defaults eraseblk=4000 +source none2 swap defaults eraseblk=5000 +source none3 swap defaults eraseblk=8192 +)fs"; + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(4U, fstab.size()); + + FstabEntry::FsMgrFlags flags = {0}; + flags.erase_blk_size = true; + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->erase_blk_size); + entry++; + + EXPECT_EQ("none1", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->erase_blk_size); + entry++; + + EXPECT_EQ("none2", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->erase_blk_size); + entry++; + + EXPECT_EQ("none3", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(8192, entry->erase_blk_size); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Logicalblk) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults logicalblk=blah +source none1 swap defaults logicalblk=4000 +source none2 swap defaults logicalblk=5000 +source none3 swap defaults logicalblk=8192 +)fs"; + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(4U, fstab.size()); + + FstabEntry::FsMgrFlags flags = {0}; + flags.logical_blk_size = true; + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->logical_blk_size); + entry++; + + EXPECT_EQ("none1", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->logical_blk_size); + entry++; + + EXPECT_EQ("none2", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(0, entry->logical_blk_size); + entry++; + + EXPECT_EQ("none3", entry->mount_point); + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + EXPECT_EQ(8192, entry->logical_blk_size); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Avb) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults avb=vbmeta_partition +)fs"; + + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(1U, fstab.size()); + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + + FstabEntry::FsMgrFlags flags = {0}; + flags.avb = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + + EXPECT_EQ("vbmeta_partition", entry->vbmeta_partition); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_KeyDirectory) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults keydirectory=/dir/key +)fs"; + + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(1U, fstab.size()); + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + + FstabEntry::FsMgrFlags flags = {0}; + flags.key_directory = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + + EXPECT_EQ("/dir/key", entry->key_dir); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_SysfsPath) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults sysfs_path=/sys/device +)fs"; + + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(1U, fstab.size()); + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + + FstabEntry::FsMgrFlags flags = {0}; + flags.sysfs = true; + EXPECT_EQ(flags.val, entry->fs_mgr_flags.val); + + EXPECT_EQ("/sys/device", entry->sysfs_path); +} + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Zram) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults zram_loopback_path=/dev/path + +source none1 swap defaults zram_loopback_size=blah +source none2 swap defaults zram_loopback_size=2 +source none3 swap defaults zram_loopback_size=1K +source none4 swap defaults zram_loopback_size=2m + +source none5 swap defaults zram_backing_dev_path=/dev/path2 + +)fs"; + + ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(6U, fstab.size()); + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_EQ("/dev/path", entry->zram_loopback_path); + entry++; + + EXPECT_EQ("none1", entry->mount_point); + EXPECT_EQ(512U * 1024U * 1024U, entry->zram_loopback_size); + entry++; + + EXPECT_EQ("none2", entry->mount_point); + EXPECT_EQ(2U, entry->zram_loopback_size); + entry++; + + EXPECT_EQ("none3", entry->mount_point); + EXPECT_EQ(1024U, entry->zram_loopback_size); + entry++; + + EXPECT_EQ("none4", entry->mount_point); + EXPECT_EQ(2U * 1024U * 1024U, entry->zram_loopback_size); + entry++; + + EXPECT_EQ("none5", entry->mount_point); + EXPECT_EQ("/dev/path2", entry->zram_backing_dev_path); }