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

Commit 99c4a8a6 authored by Hung-ying Tyan's avatar Hung-ying Tyan
Browse files

Mount /vendor and /odm early

Right now these two partitions are mounted in the fs stage of the init
process. As a result, many vendor/ODM files needed earlier in the boot
process (e.g., init.<hardware>.rc, fstab.<hardware>.rc,
uevent.<hardware>.rc, SELinux policy files etc) can only live on the root
partition.

To prevent vendors/ODMs from polluting the root partition, this patch makes
it possible to mount the vendor and ODM partitions in the first stage of the
init process. The fstab info of both partitions to be mounted early is
composed from new kernel cmdline arguments android.early.prefix and
android.early.fstab.

For example, with:
android.early.prefix=/sys/devices/1010000.msdc0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/
android.early.fstab=mmcblk0p10+/odm+ext4+ro+verify\nmmcblk0p09+/vendor+ext4+ro+verify

the final fstab string will be:
/sys/devices/1010000.msdc0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p10 /odm ext4 ro verify
/sys/devices/1010000.msdc0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p09 /vendor ext4 ro verify

The android.early.prefix is optional. When it is missing, the final fstab
string will be directly converted from android.early.fstab.

This patch also makes sure that the early mounted partitions are dm-verity
enabled so that they are trust worthy to store system files.

BUG=27805372

Change-Id: I3cf32482a5ec65445ba3aedab2164c7ba8f12694
parent 7a746f3a
Loading
Loading
Loading
Loading
+19 −0
Original line number Original line Diff line number Diff line
@@ -905,3 +905,22 @@ int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_dev


    return 0;
    return 0;
}
}

int fs_mgr_early_setup_verity(struct fstab_rec *fstab_rec)
{
    if ((fstab_rec->fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
        int rc = fs_mgr_setup_verity(fstab_rec);
        if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
            INFO("Verity disabled");
            return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
        } else if (rc == FS_MGR_SETUP_VERITY_SUCCESS) {
            return FS_MGR_EARLY_SETUP_VERITY_SUCCESS;
        } else {
            return FS_MGR_EARLY_SETUP_VERITY_FAIL;
        }
    } else if (device_is_secure()) {
        ERROR("Verity must be enabled for early mounted partitions on secured devices.\n");
        return FS_MGR_EARLY_SETUP_VERITY_FAIL;
    }
    return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
}
+19 −11
Original line number Original line Diff line number Diff line
@@ -210,9 +210,8 @@ static int parse_flags(char *flags, struct flag_list *fl,
    return f;
    return f;
}
}


struct fstab *fs_mgr_read_fstab(const char *fstab_path)
struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
{
{
    FILE *fstab_file;
    int cnt, entries;
    int cnt, entries;
    ssize_t len;
    ssize_t len;
    size_t alloc_len = 0;
    size_t alloc_len = 0;
@@ -224,12 +223,6 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path)
#define FS_OPTIONS_LEN 1024
#define FS_OPTIONS_LEN 1024
    char tmp_fs_options[FS_OPTIONS_LEN];
    char tmp_fs_options[FS_OPTIONS_LEN];


    fstab_file = fopen(fstab_path, "r");
    if (!fstab_file) {
        ERROR("Cannot open file %s\n", fstab_path);
        return 0;
    }

    entries = 0;
    entries = 0;
    while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
    while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
        /* if the last character is a newline, shorten the string by 1 byte */
        /* if the last character is a newline, shorten the string by 1 byte */
@@ -255,7 +248,6 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path)
    /* Allocate and init the fstab structure */
    /* Allocate and init the fstab structure */
    fstab = calloc(1, sizeof(struct fstab));
    fstab = calloc(1, sizeof(struct fstab));
    fstab->num_entries = entries;
    fstab->num_entries = entries;
    fstab->fstab_filename = strdup(fstab_path);
    fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
    fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));


    fseek(fstab_file, 0, SEEK_SET);
    fseek(fstab_file, 0, SEEK_SET);
@@ -338,18 +330,34 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path)
        ERROR("Error updating for slotselect\n");
        ERROR("Error updating for slotselect\n");
        goto err;
        goto err;
    }
    }
    fclose(fstab_file);
    free(line);
    free(line);
    return fstab;
    return fstab;


err:
err:
    fclose(fstab_file);
    free(line);
    free(line);
    if (fstab)
    if (fstab)
        fs_mgr_free_fstab(fstab);
        fs_mgr_free_fstab(fstab);
    return NULL;
    return NULL;
}
}


struct fstab *fs_mgr_read_fstab(const char *fstab_path)
{
    FILE *fstab_file;
    struct fstab *fstab;

    fstab_file = fopen(fstab_path, "r");
    if (!fstab_file) {
        ERROR("Cannot open file %s\n", fstab_path);
        return NULL;
    }
    fstab = fs_mgr_read_fstab_file(fstab_file);
    if (fstab) {
        fstab->fstab_filename = strdup(fstab_path);
    }
    fclose(fstab_file);
    return fstab;
}

void fs_mgr_free_fstab(struct fstab *fstab)
void fs_mgr_free_fstab(struct fstab *fstab)
{
{
    int i;
    int i;
+0 −16
Original line number Original line Diff line number Diff line
@@ -341,17 +341,6 @@ static int resume_verity_table(struct dm_ioctl *io, char *name, int fd)
    return 0;
    return 0;
}
}


static int test_access(char *device) {
    int tries = 25;
    while (tries--) {
        if (!access(device, F_OK) || errno != ENOENT) {
            return 0;
        }
        usleep(40 * 1000);
    }
    return -1;
}

static int check_verity_restart(const char *fname)
static int check_verity_restart(const char *fname)
{
{
    char buffer[VERITY_KMSG_BUFSIZE + 1];
    char buffer[VERITY_KMSG_BUFSIZE + 1];
@@ -1031,11 +1020,6 @@ loaded:
    fstab->blk_device = verity_blk_name;
    fstab->blk_device = verity_blk_name;
    verity_blk_name = 0;
    verity_blk_name = 0;


    // make sure we've set everything up properly
    if (test_access(fstab->blk_device) < 0) {
        goto out;
    }

    retval = FS_MGR_SETUP_VERITY_SUCCESS;
    retval = FS_MGR_SETUP_VERITY_SUCCESS;


out:
out:
+7 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
#ifndef __CORE_FS_MGR_H
#ifndef __CORE_FS_MGR_H
#define __CORE_FS_MGR_H
#define __CORE_FS_MGR_H


#include <stdio.h>
#include <stdint.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdbool.h>
#include <linux/dm-ioctl.h>
#include <linux/dm-ioctl.h>
@@ -72,6 +73,7 @@ struct fstab_rec {
typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab,
typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab,
        const char *mount_point, int mode, int status);
        const char *mount_point, int mode, int status);


struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file);
struct fstab *fs_mgr_read_fstab(const char *fstab_path);
struct fstab *fs_mgr_read_fstab(const char *fstab_path);
void fs_mgr_free_fstab(struct fstab *fstab);
void fs_mgr_free_fstab(struct fstab *fstab);


@@ -111,6 +113,11 @@ int fs_mgr_swapon_all(struct fstab *fstab);


int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer);
int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer);


#define FS_MGR_EARLY_SETUP_VERITY_NO_VERITY -2
#define FS_MGR_EARLY_SETUP_VERITY_FAIL -1
#define FS_MGR_EARLY_SETUP_VERITY_SUCCESS 0
int fs_mgr_early_setup_verity(struct fstab_rec *fstab);

#ifdef __cplusplus
#ifdef __cplusplus
}
}
#endif
#endif
+85 −16
Original line number Original line Diff line number Diff line
@@ -44,6 +44,7 @@


#include <android-base/file.h>
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <cutils/list.h>
#include <cutils/list.h>
#include <cutils/uevent.h>
#include <cutils/uevent.h>


@@ -601,14 +602,17 @@ static const char *parse_device_name(struct uevent *uevent, unsigned int len)
    return name;
    return name;
}
}


#define DEVPATH_LEN 96
#define MAX_DEV_NAME 64

static void handle_block_device_event(struct uevent *uevent)
static void handle_block_device_event(struct uevent *uevent)
{
{
    const char *base = "/dev/block/";
    const char *base = "/dev/block/";
    const char *name;
    const char *name;
    char devpath[96];
    char devpath[DEVPATH_LEN];
    char **links = NULL;
    char **links = NULL;


    name = parse_device_name(uevent, 64);
    name = parse_device_name(uevent, MAX_DEV_NAME);
    if (!name)
    if (!name)
        return;
        return;


@@ -622,8 +626,6 @@ static void handle_block_device_event(struct uevent *uevent)
            uevent->major, uevent->minor, links);
            uevent->major, uevent->minor, links);
}
}


#define DEVPATH_LEN 96

static bool assemble_devpath(char *devpath, const char *dirname,
static bool assemble_devpath(char *devpath, const char *dirname,
        const char *devname)
        const char *devname)
{
{
@@ -657,7 +659,7 @@ static void handle_generic_device_event(struct uevent *uevent)
    char devpath[DEVPATH_LEN] = {0};
    char devpath[DEVPATH_LEN] = {0};
    char **links = NULL;
    char **links = NULL;


    name = parse_device_name(uevent, 64);
    name = parse_device_name(uevent, MAX_DEV_NAME);
    if (!name)
    if (!name)
        return;
        return;


@@ -900,7 +902,8 @@ static void handle_firmware_event(struct uevent *uevent)
}
}


#define UEVENT_MSG_LEN  2048
#define UEVENT_MSG_LEN  2048
void handle_device_fd()

static inline void handle_device_fd_with(void (handle_uevent)(struct uevent*))
{
{
    char msg[UEVENT_MSG_LEN+2];
    char msg[UEVENT_MSG_LEN+2];
    int n;
    int n;
@@ -913,7 +916,14 @@ void handle_device_fd()


        struct uevent uevent;
        struct uevent uevent;
        parse_event(msg, &uevent);
        parse_event(msg, &uevent);
        handle_uevent(&uevent);
    }
}


void handle_device_fd()
{
    handle_device_fd_with(
        [](struct uevent *uevent) {
            if (selinux_status_updated() > 0) {
            if (selinux_status_updated() > 0) {
                struct selabel_handle *sehandle2;
                struct selabel_handle *sehandle2;
                sehandle2 = selinux_android_file_context_handle();
                sehandle2 = selinux_android_file_context_handle();
@@ -923,9 +933,9 @@ void handle_device_fd()
                }
                }
            }
            }


        handle_device_event(&uevent);
            handle_device_event(uevent);
        handle_firmware_event(&uevent);
            handle_firmware_event(uevent);
    }
        });
}
}


/* Coldboot walks parts of the /sys tree and pokes the uevent files
/* Coldboot walks parts of the /sys tree and pokes the uevent files
@@ -979,6 +989,65 @@ static void coldboot(const char *path)
    }
    }
}
}


static void early_uevent_handler(struct uevent *uevent, const char *base, bool is_block)
{
    const char *name;
    char devpath[DEVPATH_LEN];

    if (is_block && strncmp(uevent->subsystem, "block", 5))
        return;

    name = parse_device_name(uevent, MAX_DEV_NAME);
    if (!name) {
        LOG(ERROR) << "Failed to parse dev name from uevent: " << uevent->action
                   << " " << uevent->partition_name << " " << uevent->partition_num
                   << " " << uevent->major << ":" << uevent->minor;
        return;
    }

    snprintf(devpath, sizeof(devpath), "%s%s", base, name);
    make_dir(base, 0755);

    dev_t dev = makedev(uevent->major, uevent->minor);
    mode_t mode = 0600 | (is_block ? S_IFBLK : S_IFCHR);
    mknod(devpath, mode, dev);
}

void early_create_dev(const std::string& syspath, early_device_type dev_type)
{
    android::base::unique_fd dfd(open(syspath.c_str(), O_RDONLY));
    if (dfd < 0) {
        LOG(ERROR) << "Failed to open " << syspath;
        return;
    }

    android::base::unique_fd fd(openat(dfd, "uevent", O_WRONLY));
    if (fd < 0) {
        LOG(ERROR) << "Failed to open " << syspath << "/uevent";
        return;
    }

    fcntl(device_fd, F_SETFL, O_NONBLOCK);

    write(fd, "add\n", 4);
    handle_device_fd_with(dev_type == EARLY_BLOCK_DEV ?
        [](struct uevent *uevent) {
            early_uevent_handler(uevent, "/dev/block/", true);
        } :
        [](struct uevent *uevent) {
            early_uevent_handler(uevent, "/dev/", false);
        });
}

int early_device_socket_open() {
    device_fd = uevent_open_socket(256*1024, true);
    return device_fd < 0;
}

void early_device_socket_close() {
    close(device_fd);
}

void device_init() {
void device_init() {
    sehandle = selinux_android_file_context_handle();
    sehandle = selinux_android_file_context_handle();
    selinux_status_open(true);
    selinux_status_open(true);
Loading