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

Commit 07c1bcbc authored by bowgotsai's avatar bowgotsai Committed by android-build-merger
Browse files

Merge "fs_mgr: support using libavb to enable dm-verity"

am: 0a3c2392

Change-Id: I738a3e6596dd465e6d0b0f7d625617bce0277acf
parents 5d6e678b 0a3c2392
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -11,7 +11,8 @@ common_static_libraries := \
    libcrypto \
    libext4_utils \
    libsquashfs_utils \
    libselinux
    libselinux \
    libavb

include $(CLEAR_VARS)
LOCAL_CLANG := true
@@ -22,7 +23,9 @@ LOCAL_SRC_FILES:= \
    fs_mgr_format.c \
    fs_mgr_fstab.c \
    fs_mgr_slotselect.c \
    fs_mgr_verity.cpp
    fs_mgr_verity.cpp \
    fs_mgr_avb.cpp \
    fs_mgr_avb_ops.cpp
LOCAL_C_INCLUDES := \
    $(LOCAL_PATH)/include \
    system/vold \
+53 −2
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@
#include <private/android_logger.h>

#include "fs_mgr_priv.h"
#include "fs_mgr_priv_avb.h"
#include "fs_mgr_priv_verity.h"

#define KEY_LOC_PROP   "ro.crypto.keyfile.userdata"
@@ -670,11 +671,17 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
    int mret = -1;
    int mount_errno = 0;
    int attempted_idx = -1;
    int avb_ret = FS_MGR_SETUP_AVB_FAIL;

    if (!fstab) {
        return -1;
    }

    if (fs_mgr_is_avb_used() &&
        (avb_ret = fs_mgr_load_vbmeta_images(fstab)) == FS_MGR_SETUP_AVB_FAIL) {
        return -1;
    }

    for (i = 0; i < fstab->num_entries; i++) {
        /* Don't mount entries that are managed by vold or not for the mount mode*/
        if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) ||
@@ -713,7 +720,22 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
            wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
        }

        if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
        if (fs_mgr_is_avb_used() && (fstab->recs[i].fs_mgr_flags & MF_AVB)) {
            /* If HASHTREE_DISABLED is set (cf. 'adb disable-verity'), we
             * should set up the device without using dm-verity.
             * The actual mounting still take place in the following
             * mount_with_alternatives().
             */
            if (avb_ret == FS_MGR_SETUP_AVB_HASHTREE_DISABLED) {
                INFO("AVB HASHTREE disabled\n");
            } else if (fs_mgr_setup_avb(&fstab->recs[i]) !=
                       FS_MGR_SETUP_AVB_SUCCESS) {
                ERROR("Failed to set up AVB on partition: %s, skipping!\n",
                      fstab->recs[i].mount_point);
                /* Skips mounting the device. */
                continue;
            }
        } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
            int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
            if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
                INFO("Verity disabled");
@@ -722,6 +744,7 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
                continue;
            }
        }

        int last_idx_inspected;
        int top_idx = i;

@@ -825,6 +848,10 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
        }
    }

    if (fs_mgr_is_avb_used()) {
        fs_mgr_unload_vbmeta_images();
    }

    if (error_count) {
        return -1;
    } else {
@@ -845,11 +872,17 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
    int mount_errors = 0;
    int first_mount_errno = 0;
    char *m;
    int avb_ret = FS_MGR_SETUP_AVB_FAIL;

    if (!fstab) {
        return ret;
    }

    if (fs_mgr_is_avb_used() &&
        (avb_ret = fs_mgr_load_vbmeta_images(fstab)) == FS_MGR_SETUP_AVB_FAIL) {
        return ret;
    }

    for (i = 0; i < fstab->num_entries; i++) {
        if (!fs_match(fstab->recs[i].mount_point, n_name)) {
            continue;
@@ -882,7 +915,22 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
            do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i]);
        }

        if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
        if (fs_mgr_is_avb_used() && (fstab->recs[i].fs_mgr_flags & MF_AVB)) {
            /* If HASHTREE_DISABLED is set (cf. 'adb disable-verity'), we
             * should set up the device without using dm-verity.
             * The actual mounting still take place in the following
             * mount_with_alternatives().
             */
            if (avb_ret == FS_MGR_SETUP_AVB_HASHTREE_DISABLED) {
                INFO("AVB HASHTREE disabled\n");
            } else if (fs_mgr_setup_avb(&fstab->recs[i]) !=
                       FS_MGR_SETUP_AVB_SUCCESS) {
                ERROR("Failed to set up AVB on partition: %s, skipping!\n",
                      fstab->recs[i].mount_point);
                /* Skips mounting the device. */
                continue;
            }
        } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
            int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
            if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
                INFO("Verity disabled");
@@ -921,6 +969,9 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
    }

out:
    if (fs_mgr_is_avb_used()) {
        fs_mgr_unload_vbmeta_images();
    }
    return ret;
}

fs_mgr/fs_mgr_avb.cpp

0 → 100644
+642 −0

File added.

Preview size limit exceeded, changes collapsed.

+206 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <string>

#include <android-base/macros.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <libavb/libavb.h>
#include <utils/Compat.h>

#include "fs_mgr.h"
#include "fs_mgr_avb_ops.h"
#include "fs_mgr_priv.h"

static struct fstab *fs_mgr_fstab = nullptr;

static AvbIOResult read_from_partition(AvbOps *ops ATTRIBUTE_UNUSED,
                                       const char *partition,
                                       int64_t offset,
                                       size_t num_bytes,
                                       void *buffer,
                                       size_t *out_num_read)
{
    // The input |partition| name is with ab_suffix, e.g. system_a.
    // Slot suffix (e.g. _a) will be appended to the device file path
    // for partitions having 'slotselect' optin in fstab file, but it
    // won't be appended to the mount point.
    //
    // In AVB, we can assume that there's an entry for the /misc mount
    // point and use that to get the device file for the misc partition.
    // From there we'll assume that a by-name scheme is used
    // so we can just replace the trailing "misc" by the given
    // |partition|, e.g.
    //
    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a

    struct fstab_rec *fstab_entry =
        fs_mgr_get_entry_for_mount_point(fs_mgr_fstab, "/misc");

    if (fstab_entry == nullptr) {
        ERROR("Partition (%s) not found in fstab\n", partition);
        return AVB_IO_RESULT_ERROR_IO;
    }

    std::string partition_name(partition);
    std::string path(fstab_entry->blk_device);
    // Replaces the last field of device file if it's not misc.
    if (!android::base::StartsWith(partition_name, "misc")) {
        size_t end_slash = path.find_last_of("/");
        std::string by_name_prefix(path.substr(0, end_slash + 1));
        path = by_name_prefix + partition_name;
    }

    android::base::unique_fd fd(
        TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));

    if (fd < 0) {
        ERROR("Failed to open %s (%s)\n", path.c_str(), strerror(errno));
        return AVB_IO_RESULT_ERROR_IO;
    }

    // If offset is negative, interprets its absolute value as the
    //  number of bytes from the end of the partition.
    if (offset < 0) {
        off64_t total_size = lseek64(fd, 0, SEEK_END);
        if (total_size == -1) {
            ERROR("Failed to lseek64 to end of the partition\n");
            return AVB_IO_RESULT_ERROR_IO;
        }
        offset = total_size + offset;
        // Repositions the offset to the beginning.
        if (lseek64(fd, 0, SEEK_SET) == -1) {
            ERROR("Failed to lseek64 to the beginning of the partition\n");
            return AVB_IO_RESULT_ERROR_IO;
        }
    }

    // On Linux, we never get partial reads from block devices (except
    // for EOF).
    ssize_t num_read =
        TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset));

    if (num_read < 0 || (size_t)num_read != num_bytes) {
        ERROR("Failed to read %zu bytes from %s offset %" PRId64 " (%s)\n",
              num_bytes, path.c_str(), offset, strerror(errno));
        return AVB_IO_RESULT_ERROR_IO;
    }

    if (out_num_read != nullptr) {
        *out_num_read = num_read;
    }

    return AVB_IO_RESULT_OK;
}

static AvbIOResult dummy_read_rollback_index(AvbOps *ops ATTRIBUTE_UNUSED,
                                             size_t rollback_index_location
                                                 ATTRIBUTE_UNUSED,
                                             uint64_t *out_rollback_index)
{
    // rollback_index has been checked in bootloader phase.
    // In user-space, returns the smallest value 0 to pass the check.
    *out_rollback_index = 0;
    return AVB_IO_RESULT_OK;
}

static AvbIOResult dummy_validate_vbmeta_public_key(
    AvbOps *ops ATTRIBUTE_UNUSED,
    const uint8_t *public_key_data ATTRIBUTE_UNUSED,
    size_t public_key_length ATTRIBUTE_UNUSED,
    const uint8_t *public_key_metadata ATTRIBUTE_UNUSED,
    size_t public_key_metadata_length ATTRIBUTE_UNUSED,
    bool *out_is_trusted)
{
    // vbmeta public key has been checked in bootloader phase.
    // In user-space, returns true to pass the check.
    //
    // Addtionally, user-space should check
    // androidboot.vbmeta.{hash_alg, size, digest} against the digest
    // of all vbmeta images after invoking avb_slot_verify().

    *out_is_trusted = true;
    return AVB_IO_RESULT_OK;
}

static AvbIOResult dummy_read_is_device_unlocked(AvbOps *ops ATTRIBUTE_UNUSED,
                                                 bool *out_is_unlocked)
{
    // The function is for bootloader to update the value into
    // androidboot.vbmeta.device_state in kernel cmdline.
    // In user-space, returns true as we don't need to update it anymore.
    *out_is_unlocked = true;
    return AVB_IO_RESULT_OK;
}

static AvbIOResult dummy_get_unique_guid_for_partition(
    AvbOps *ops ATTRIBUTE_UNUSED,
    const char *partition ATTRIBUTE_UNUSED,
    char *guid_buf,
    size_t guid_buf_size)
{
    // The function is for bootloader to set the correct UUID
    // for a given partition in kernel cmdline.
    // In user-space, returns a faking one as we don't need to update
    // it anymore.
    snprintf(guid_buf, guid_buf_size, "1234-fake-guid-for:%s", partition);
    return AVB_IO_RESULT_OK;
}

AvbOps *fs_mgr_dummy_avb_ops_new(struct fstab *fstab)
{
    AvbOps *ops;

    // Assigns the fstab to the static variable for later use.
    fs_mgr_fstab = fstab;

    ops = (AvbOps *)calloc(1, sizeof(AvbOps));
    if (ops == nullptr) {
        ERROR("Error allocating memory for AvbOps.\n");
        return nullptr;
    }

    // We only need these operations since that's all what is being used
    // by the avb_slot_verify(); Most of them are dummy operations because
    // they're only required in bootloader but not required in user-space.
    ops->read_from_partition = read_from_partition;
    ops->read_rollback_index = dummy_read_rollback_index;
    ops->validate_vbmeta_public_key = dummy_validate_vbmeta_public_key;
    ops->read_is_device_unlocked = dummy_read_is_device_unlocked;
    ops->get_unique_guid_for_partition = dummy_get_unique_guid_for_partition;

    return ops;
}

void fs_mgr_dummy_avb_ops_free(AvbOps *ops)
{
    free(ops);
}
+59 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef __CORE_FS_MGR_AVB_OPS_H
#define __CORE_FS_MGR_AVB_OPS_H

#include <libavb/libavb.h>

#include "fs_mgr.h"

__BEGIN_DECLS

/* Allocates a "dummy" AvbOps instance solely for use in user-space.
 * Returns nullptr on OOM.
 *
 * It mainly provides read_from_partitions() for user-space to get
 * AvbSlotVerifyData.vbmeta_images[] and the caller MUST check their
 * integrity against the androidboot.vbmeta.{hash_alg, size, digest}
 * values from /proc/cmdline, e.g. verify_vbmeta_images()
 * in fs_mgr_avb.cpp.
 *
 * Other I/O operations are only required in boot loader so we set
 * them as dummy operations here.
 *  - Will allow any public key for signing.
 *  - returns 0 for any rollback index location.
 *  - returns device is unlocked regardless of the actual state.
 *  - returns a dummy guid for any partition.
 *
 * Frees with fs_mgr_dummy_avb_ops_free().
 */
AvbOps *fs_mgr_dummy_avb_ops_new(struct fstab *fstab);

/* Frees an AvbOps instance previously allocated with fs_mgr_avb_ops_new(). */
void fs_mgr_dummy_avb_ops_free(AvbOps *ops);

__END_DECLS

#endif /* __CORE_FS_MGR_AVB_OPS_H */
Loading