Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e34f750 authored by Tom Cherry's avatar Tom Cherry
Browse files

fs_mgr: store file_contents_mode and file_names_mode directly

It doesn't really make sense to have extra logic to convert these
strings to enums then back again to strings for usage, especially
since with the C++ fstab, these strings are small enough to fall into
the small string optimization of std::string.

This will help make future changes cleaner as well.
Test: boot, fs_mgr_test

Change-Id: I5669ed10f2fc3eafdb137747446a2e93c24d55c4
parent e41489a9
Loading
Loading
Loading
Loading
+69 −83
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <unistd.h>

#include <algorithm>
#include <array>
#include <utility>
#include <vector>

@@ -55,8 +56,8 @@ struct fs_mgr_flag_values {
    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 vbmeta_partition;
@@ -129,51 +130,6 @@ static struct flag_list fs_mgr_flags[] = {
        {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) {
    off64_t total;

@@ -217,6 +173,59 @@ static bool read_dt_file(const std::string& file_name, std::string* dt_value)
    return false;
}

const static std::array<const char*, 3> kFileContentsEncryptionMode = {
        "aes-256-xts",
        "adiantum",
        "ice",
};

const static std::array<const char*, 3> kFileNamesEncryptionMode = {
        "aes-256-cts",
        "aes-256-heh",
        "adiantum",
};

static void ParseFileEncryption(const std::string& arg, struct fs_mgr_flag_values* flag_vals) {
    // 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 parts = Split(arg, ":");
    if (parts.empty() || parts.size() > 2) {
        LWARNING << "Warning: fileencryption= flag malformed: " << arg;
        return;
    }

    // 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;
    }

    flag_vals->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;
        }

        flag_vals->file_names_mode = parts[1];
    } else if (flag_vals->file_contents_mode == "adiantum") {
        flag_vals->file_names_mode = "adiantum";
    } else {
        flag_vals->file_names_mode = "aes-256-cts";
    }
}

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;
@@ -260,31 +269,10 @@ static uint64_t parse_flags(char* flags, struct flag_list* fl, struct fs_mgr_fla
                     * 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;
                    flag_vals->file_contents_mode = "aes-256-xts";
                    flag_vals->file_names_mode = "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;
                    }
                    ParseFileEncryption(arg, flag_vals);
                } else if (flag == MF_KEYDIRECTORY) {
                    /* The metadata flag is followed by an = and the
                     * directory for the keys.  Get it and return it.
@@ -582,8 +570,8 @@ static bool fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts, Fstab* fs
        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.file_contents_mode = std::move(flag_vals.file_contents_mode);
        entry.file_names_mode = std::move(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);
@@ -831,6 +819,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);
@@ -972,8 +962,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());
@@ -1019,14 +1009,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)
+5 −5
Original line number Diff line number Diff line
@@ -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,8 +118,8 @@ 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;
@@ -130,7 +130,7 @@ struct FstabEntry {

    // 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
+118 −0
Original line number Diff line number Diff line
@@ -230,3 +230,121 @@ TEST(fs_mgr, ReadFstabFromFile_FsOptions) {
    EXPECT_EQ("none", fstab[6].mount_point);
    EXPECT_EQ("", fstab[6].fs_options);
}

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);
}