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

Commit c20c0c2c authored by Sandeep Patil's avatar Sandeep Patil
Browse files

early_mount: fs_mgr: move all fstab logic into fs_mgr



With init parsing fstab fragments from kernel separately, the fs_mgr
would completely miss the device tree entries. That leads to things like
'adb remount' to go through without warning for verity even if /system
is verified. This happens because 'verity_update_state' completely
misses the partitions passed to android through the device tree.

solution is to teach fs_mgr about device tree fstab entries and add 2
new public APIs.

1. fs_mgr_read_fstab_dt() - reads device tree and returns fstab
generated from it.

2. fs_mgr_read_fstab_default() - reads both device tree fstab and
/fstab.{ro.hardware} and returns the combined table.

This also reduces the hardcoded /fstab.{ro.hardware} occurence only to
fs_mgr and for eveyone who wants to read the "default" fstab must be
changed to call fs_mgr_read_fstab_default() instead. e.g. adb.

b/27805372

Test: Angler was used since it has 2 early mounted partitions instead of
one. 1 verified and 1 unverified.
- Boot angler successfully without early mount
- Boot angler successfully with /vendor early mount and test if 'adb
remount' warns us about verity
- Boot angler successfully with both /system and /vendor early mounted
and ensure 'adb remount' warns us about verity.
- check partitions.system.verified status after /system early mount ot
ensure it is set to VERITY_MODE_DEFAULT.
- 'adb disable-verity' with early mounted /system doesn't work due to
missing changes in adb

TODO:
change adb to use the new fs_mgr_read_fstab_default() API

Change-Id: I82038d87c7a44488e938acce2cc1082c08f6f73a
Signed-off-by: default avatarSandeep Patil <sspatil@google.com>
parent 4bd3facb
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -49,8 +49,7 @@ bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) {
    }

    // lastly, check the device tree
    static const std::string android_dt_dir("/proc/device-tree/firmware/android");
    std::string file_name = android_dt_dir + "/compatible";
    std::string file_name = kAndroidDtDir + "/compatible";
    std::string dt_value;
    if (android::base::ReadFileToString(file_name, &dt_value)) {
        if (dt_value != "android,firmware") {
@@ -58,7 +57,7 @@ bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) {
            return false;
        }

        file_name = android_dt_dir + "/" + key;
        file_name = kAndroidDtDir + "/" + key;
        // DT entries terminate with '\0' but so do the properties
        if (android::base::ReadFileToString(file_name, out_val)) {
            return true;
+187 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */

#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -22,6 +23,10 @@
#include <sys/mount.h>
#include <unistd.h>

#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>

#include "fs_mgr_priv.h"

struct fs_mgr_flag_values {
@@ -290,6 +295,110 @@ static int parse_flags(char *flags, struct flag_list *fl,
    return f;
}

static bool is_dt_compatible() {
    std::string file_name = kAndroidDtDir + "/compatible";
    std::string dt_value;
    if (android::base::ReadFileToString(file_name, &dt_value)) {
        // trim the trailing '\0' out, otherwise the comparison
        // will produce false-negatives.
        dt_value.resize(dt_value.size() - 1);
        if (dt_value == "android,firmware") {
            return true;
        }
    }

    return false;
}

static bool is_dt_fstab_compatible() {
    std::string dt_value;
    std::string file_name = kAndroidDtDir + "/fstab/compatible";

    if (android::base::ReadFileToString(file_name, &dt_value)) {
        // trim the trailing '\0' out, otherwise the comparison
        // will produce false-negatives.
        dt_value.resize(dt_value.size() - 1);
        if (dt_value == "android,fstab") {
            return true;
        }
    }

    return false;
}

static std::string read_fstab_from_dt() {
    std::string fstab;
    if (!is_dt_compatible() || !is_dt_fstab_compatible()) {
        return fstab;
    }

    std::string fstabdir_name = kAndroidDtDir + "/fstab";
    std::unique_ptr<DIR, int (*)(DIR*)> fstabdir(opendir(fstabdir_name.c_str()), closedir);
    if (!fstabdir) return fstab;

    dirent* dp;
    while ((dp = readdir(fstabdir.get())) != NULL) {
        // skip over name and compatible
        if (dp->d_type != DT_DIR) {
            continue;
        }

        // skip if its not 'vendor', 'odm' or 'system'
        if (strcmp(dp->d_name, "odm") && strcmp(dp->d_name, "system") &&
            strcmp(dp->d_name, "vendor")) {
            continue;
        }

        // create <dev> <mnt_point>  <type>  <mnt_flags>  <fsmgr_flags>\n
        std::vector<std::string> fstab_entry;
        std::string file_name;
        std::string value;
        file_name = android::base::StringPrintf("%s/%s/dev", fstabdir_name.c_str(), dp->d_name);
        if (!android::base::ReadFileToString(file_name, &value)) {
            LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name;
            fstab.clear();
            break;
        }
        // trim the terminating '\0' out
        value.resize(value.size() - 1);
        fstab_entry.push_back(value);
        fstab_entry.push_back(android::base::StringPrintf("/%s", dp->d_name));

        file_name = android::base::StringPrintf("%s/%s/type", fstabdir_name.c_str(), dp->d_name);
        if (!android::base::ReadFileToString(file_name, &value)) {
            LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
            fstab.clear();
            break;
        }
        value.resize(value.size() - 1);
        fstab_entry.push_back(value);

        file_name = android::base::StringPrintf("%s/%s/mnt_flags", fstabdir_name.c_str(), dp->d_name);
        if (!android::base::ReadFileToString(file_name, &value)) {
            LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
            fstab.clear();
            break;
        }
        value.resize(value.size() - 1);
        fstab_entry.push_back(value);

        file_name = android::base::StringPrintf("%s/%s/fsmgr_flags", fstabdir_name.c_str(), dp->d_name);
        if (!android::base::ReadFileToString(file_name, &value)) {
            LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
            fstab.clear();
            break;
        }
        value.resize(value.size() - 1);
        fstab_entry.push_back(value);

        fstab += android::base::Join(fstab_entry, " ");
        fstab += '\n';
    }

    return fstab;
}


struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
{
    int cnt, entries;
@@ -444,6 +553,84 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path)
    return fstab;
}

/* Returns fstab entries parsed from the device tree if they
 * exist
 */
struct fstab *fs_mgr_read_fstab_dt()
{
    std::string fstab_buf = read_fstab_from_dt();
    if (fstab_buf.empty()) {
        return NULL;
    }

    std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
        fmemopen(static_cast<void*>(const_cast<char*>(fstab_buf.c_str())),
                 fstab_buf.length(), "r"), fclose);
    if (!fstab_file) {
        return NULL;
    }

    struct fstab *fstab = fs_mgr_read_fstab_file(fstab_file.get());
    if (!fstab) {
        LERROR << "failed to load fstab from kernel:" << std::endl << fstab_buf;
    }

    return fstab;
}

/* combines fstab entries passed in from device tree with
 * the ones found in /fstab.<hardware>
 */
struct fstab *fs_mgr_read_fstab_default()
{
    struct fstab *fstab = fs_mgr_read_fstab_dt();
    std::string hw;
    if (!fs_mgr_get_boot_config("hardware", &hw)) {
        // if we fail to find this, return whatever was found in device tree
        LWARNING << "failed to find device hardware name";
        return fstab;
    }

    std::string default_fstab = FSTAB_PREFIX + hw;
    struct fstab *f = fs_mgr_read_fstab(default_fstab.c_str());
    if (!f) {
        // return what we have
        LWARNING << "failed to read fstab entries from '" << default_fstab << "'";
        return fstab;
    }

    // return the fstab read from file if device tree doesn't
    // have one, other wise merge the two
    if (!fstab) {
        fstab = f;
    } else {
        int total_entries = fstab->num_entries + f->num_entries;
        fstab->recs = static_cast<struct fstab_rec *>(realloc(
                        fstab->recs, total_entries * (sizeof(struct fstab_rec))));
        if (!fstab->recs) {
            LERROR << "failed to allocate fstab recs";
            fstab->num_entries = 0;
            fs_mgr_free_fstab(fstab);
            return NULL;
        }

        for (int i = fstab->num_entries, j = 0; i < total_entries; i++, j++) {
            // copy everything and *not* strdup
            fstab->recs[i] = f->recs[j];
        }

        // free up fstab entries read from file, but don't cleanup
        // the strings within f->recs[X] to make sure they are accessible
        // through fstab->recs[X].
        free(f->fstab_filename);
        free(f);

        fstab->num_entries = total_entries;
    }

    return fstab;
}

void fs_mgr_free_fstab(struct fstab *fstab)
{
    int i;
+2 −0
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@
#define PWARNING PLOG(WARNING) << FS_MGR_TAG
#define PERROR   PLOG(ERROR) << FS_MGR_TAG

const std::string FSTAB_PREFIX("/fstab.");

__BEGIN_DECLS

#define CRYPTO_TMPFS_OPTIONS "size=256m,mode=0771,uid=1000,gid=1000"
+2 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include <sys/cdefs.h>
#include <string>

const std::string kAndroidDtDir("/proc/device-tree/firmware/android");

bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val);

#endif /* __CORE_FS_MGR_PRIV_BOOTCONFIG_H */
+4 −19
Original line number Diff line number Diff line
@@ -46,8 +46,6 @@
#include "fs_mgr_priv.h"
#include "fs_mgr_priv_dm_ioctl.h"

#define FSTAB_PREFIX "/fstab."

#define VERITY_TABLE_RSA_KEY "/verity_key"
#define VERITY_TABLE_HASH_IDX 8
#define VERITY_TABLE_SALT_IDX 9
@@ -694,8 +692,6 @@ static int load_verity_state(struct fstab_rec *fstab, int *mode)

int fs_mgr_load_verity_state(int *mode)
{
    char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
    char propbuf[PROPERTY_VALUE_MAX];
    int rc = -1;
    int i;
    int current;
@@ -705,13 +701,9 @@ int fs_mgr_load_verity_state(int *mode)
     * logging mode, in which case return that */
    *mode = VERITY_MODE_DEFAULT;

    property_get("ro.hardware", propbuf, "");
    snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);

    fstab = fs_mgr_read_fstab(fstab_filename);

    fstab = fs_mgr_read_fstab_default();
    if (!fstab) {
        LERROR << "Failed to read " << fstab_filename;
        LERROR << "Failed to read default fstab";
        goto out;
    }

@@ -745,7 +737,6 @@ int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback)
{
    alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
    bool system_root = false;
    char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
    std::string mount_point;
    char propbuf[PROPERTY_VALUE_MAX];
    const char *status;
@@ -765,22 +756,16 @@ int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback)
    }

    fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC));

    if (fd == -1) {
        PERROR << "Error opening device mapper";
        goto out;
    }

    property_get("ro.hardware", propbuf, "");
    snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);

    property_get("ro.build.system_root_image", propbuf, "");
    system_root = !strcmp(propbuf, "true");

    fstab = fs_mgr_read_fstab(fstab_filename);

    fstab = fs_mgr_read_fstab_default();
    if (!fstab) {
        LERROR << "Failed to read " << fstab_filename;
        LERROR << "Failed to read default fstab";
        goto out;
    }

Loading