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

Commit c573a137 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 4562879 from 4d2b19c3 to pi-release

Change-Id: I1fa6b4cac50a41119012e4418088f754da055f53
parents 17e03503 4d2b19c3
Loading
Loading
Loading
Loading
+122 −28
Original line number Diff line number Diff line
@@ -18,17 +18,20 @@

#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER

#include <algorithm>
#include <errno.h>
#include <inttypes.h>
#include <fstream>
#include <fts.h>
#include <inttypes.h>
#include <regex>
#include <stdlib.h>
#include <string.h>
#include <sys/capability.h>
#include <sys/file.h>
#include <sys/resource.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/quota.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/types.h>
@@ -41,6 +44,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <cutils/ashmem.h>
#include <cutils/fs.h>
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
@@ -84,6 +88,10 @@ static constexpr const char *kIdMapPath = "/system/bin/idmap";
static constexpr const char* IDMAP_PREFIX = "/data/resource-cache/";
static constexpr const char* IDMAP_SUFFIX = "@idmap";

// fsverity assumes the page size is always 4096. If not, the feature can not be
// enabled.
static constexpr int kVerityPageSize = 4096;
static constexpr size_t kSha256Size = 32;
static constexpr const char* kPropApkVerityMode = "ro.apk_verity.mode";

// NOTE: keep in sync with Installer
@@ -184,6 +192,12 @@ binder::Status checkArgumentPackageName(const std::string& packageName) {
    }                                                       \
}

#define ASSERT_PAGE_SIZE_4K() {                             \
    if (getpagesize() != kVerityPageSize) {                 \
        return error("FSVerity only supports 4K page");     \
    }                                                       \
}

}  // namespace

status_t InstalldNativeService::start() {
@@ -1940,27 +1954,6 @@ binder::Status InstalldNativeService::markBootComplete(const std::string& instru
    return ok();
}

void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
        struct stat* statbuf)
{
    while (path[basepos] != 0) {
        if (path[basepos] == '/') {
            path[basepos] = 0;
            if (lstat(path, statbuf) < 0) {
                ALOGV("Making directory: %s\n", path);
                if (mkdir(path, mode) == 0) {
                    chown(path, uid, gid);
                } else {
                    ALOGW("Unable to make directory %s: %s\n", path, strerror(errno));
                }
            }
            path[basepos] = '/';
            basepos++;
        }
        basepos++;
    }
}

binder::Status InstalldNativeService::linkNativeLibraryDirectory(
        const std::unique_ptr<std::string>& uuid, const std::string& packageName,
        const std::string& nativeLibPath32, int32_t userId) {
@@ -2358,15 +2351,116 @@ binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath,
    return res ? ok() : error();
}

binder::Status InstalldNativeService::installApkVerity(const std::string& /*filePath*/,
        const ::android::base::unique_fd& /*verityInput*/) {
// This kernel feaeture is experimental.
// TODO: remove local definition once upstreamed
#ifndef FS_IOC_SET_FSVERITY
struct fsverity_set {
    __u64 offset;
    __u64 flags;
};

struct fsverity_root_hash {
    short root_hash_algorithm;
    short flags;
    __u8 reserved[4];
    __u8 root_hash[64];
};

#define FS_IOC_MEASURE_FSVERITY        _IOW('f', 2733, struct fsverity_root_hash)
#define FS_IOC_SET_FSVERITY            _IOW('f', 2734, struct fsverity_set)

#define FSVERITY_FLAG_ENABLED          0x0001
#endif

binder::Status InstalldNativeService::installApkVerity(const std::string& filePath,
        const ::android::base::unique_fd& verityInputAshmem) {
    ENFORCE_UID(AID_SYSTEM);
    if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) {
        return ok();
    }
    // TODO: Append verity to filePath then issue ioctl to enable
    // it and hide the tree.  See b/30972906.
    return error("not implemented yet");
#if DEBUG
    ASSERT_PAGE_SIZE_4K();
#endif
    // TODO: also check fsverity support in the current file system if compiled with DEBUG.
    // TODO: change ashmem to some temporary file to support huge apk.
    if (!ashmem_valid(verityInputAshmem.get())) {
        return error("FD is not an ashmem");
    }

    // TODO(71871109): Validate filePath.
    // 1. Seek to the next page boundary beyond the end of the file.
    ::android::base::unique_fd wfd(open(filePath.c_str(), O_WRONLY | O_APPEND));
    if (wfd.get() < 0) {
        return error("Failed to open " + filePath + ": " + strerror(errno));
    }
    struct stat st;
    if (fstat(wfd.get(), &st) < 0) {
        return error("Failed to stat " + filePath + ": " + strerror(errno));
    }
    // fsverity starts from the block boundary.
    if (lseek(wfd.get(), (st.st_size + kVerityPageSize - 1) / kVerityPageSize, SEEK_SET) < 0) {
        return error("Failed to lseek " + filePath + ": " + strerror(errno));
    }

    // 2. Write everything in the ashmem to the file.
    int size = ashmem_get_size_region(verityInputAshmem.get());
    if (size < 0) {
        return error("Failed to get ashmem size: " + std::to_string(size));
    }
    void* data = mmap(NULL, size, PROT_READ, MAP_SHARED, wfd.get(), 0);
    if (data == MAP_FAILED) {
        return error("Failed to mmap the ashmem: " + std::string(strerror(errno)));
    }
    int remaining = size;
    while (remaining > 0) {
        int ret = TEMP_FAILURE_RETRY(write(wfd.get(), data, remaining));
        if (ret < 0) {
            munmap(data, size);
            return error("Failed to write to " + filePath + " (" + std::to_string(remaining) +
                         + "/" + std::to_string(size) + "): " + strerror(errno));
        }
        remaining -= ret;
    }
    munmap(data, size);

    // 3. Enable fsverity. Once it's done, the file becomes immutable.
    struct fsverity_set config;
    config.offset = st.st_size;
    config.flags = FSVERITY_FLAG_ENABLED;
    if (ioctl(wfd.get(), FS_IOC_SET_FSVERITY, &config) < 0) {
        return error("Failed to enable fsverity on " + filePath + ": " + strerror(errno));
    }
    return ok();
}

binder::Status InstalldNativeService::assertFsverityRootHashMatches(const std::string& filePath,
        const std::vector<uint8_t>& expectedHash) {
    ENFORCE_UID(AID_SYSTEM);
    if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) {
        return ok();
    }
    // TODO: also check fsverity support in the current file system if compiled with DEBUG.
    if (expectedHash.size() != kSha256Size) {
        return error("verity hash size should be " + std::to_string(kSha256Size) + " but is " +
                     std::to_string(expectedHash.size()));
    }

    // TODO(71871109): Validate filePath.
    ::android::base::unique_fd fd(open(filePath.c_str(), O_RDONLY));
    if (fd.get() < 0) {
        return error("Failed to open " + filePath + ": " + strerror(errno));
    }

    struct fsverity_root_hash config;
    memset(&config, 0, sizeof(config));
    config.root_hash_algorithm = 0;  // SHA256
    memcpy(config.root_hash, expectedHash.data(), std::min(sizeof(config.root_hash), kSha256Size));
    if (ioctl(fd.get(), FS_IOC_MEASURE_FSVERITY, &config) < 0) {
        // This includes an expected failure case with no FSVerity setup. It normally happens when
        // the apk does not contains the Merkle tree root hash.
        return error("Failed to measure fsverity on " + filePath + ": " + strerror(errno));
    }
    return ok();  // hashes match
}

binder::Status InstalldNativeService::reconcileSecondaryDexFile(
+2 −0
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ public:
            const std::unique_ptr<std::string>& outputPath);
    binder::Status installApkVerity(const std::string& filePath,
            const ::android::base::unique_fd& verityInput);
    binder::Status assertFsverityRootHashMatches(const std::string& filePath,
            const std::vector<uint8_t>& expectedHash);
    binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
        const std::string& packageName, int32_t uid, const std::vector<std::string>& isa,
        const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ interface IInstalld {
    void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
            @nullable @utf8InCpp String outputPath);
    void installApkVerity(@utf8InCpp String filePath, in FileDescriptor verityInput);
    void assertFsverityRootHashMatches(@utf8InCpp String filePath, in byte[] expectedHash);

    boolean reconcileSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
        int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid,
+39 −0
Original line number Diff line number Diff line
@@ -123,6 +123,45 @@ namespace android {
            KeyStatusType mType;
        };

        // Enumerate HDCP output protection levels
        enum HdcpLevel {
            // Failure to access HDCP level, an error occurred
            kHdcpLevelUnknown,
            // HDCP is not supported on this device, content is unprotected
            kHdcpNone,
            // HDCP version 1.0
            kHdcpV1,
            // HDCP version 2.0 Type 1.
            kHdcpV2,
            // HDCP version 2.1 Type 1.
            kHdcpV2_1,
            // HDCP version 2.2 Type 1.
            kHdcpV2_2,
            // No digital output, implicitly secure
            kHdcpNoOutput = 0x7fff
        };

        // SecurityLevel indicates the level of robustness of the DRM
        // implementation on the device
        enum SecurityLevel {
            // Failure to access security level, an error occurred
            kSecurityLevelUnknown,
            // Software-based whitebox crypto
            kSecurityLevelSwSecureCrypto,
            // Software-based whitebox crypto and an obfuscated decoder
            kSecurityLevelSwSecureDecode,
            // DRM key management and crypto operations are performed within a
            // hardware backed trusted execution environment
            kSecurityLevelHwSecureCrypto,
            // DRM key management, crypto operations and decoding of content
            // are performed within a hardware backed trusted execution environment
            kSecurityLevelHwSecureDecode,
            // DRM key management, crypto operations, decoding of content  and all
            // handling of the media (compressed and uncompressed) is handled within
            // a hardware backed trusted execution environment.
            kSecurityLevelHwSecureAll
        };

        DrmPlugin() {}
        virtual ~DrmPlugin() {}

+3 −1
Original line number Diff line number Diff line
@@ -767,7 +767,9 @@ enum {
    /** fingerprint navigation key, right. */
    AKEYCODE_SYSTEM_NAVIGATION_RIGHT = 283,
    /** all apps */
    AKEYCODE_ALL_APPS = 284
    AKEYCODE_ALL_APPS = 284,
    /** refresh key */
    AKEYCODE_REFRESH = 285

    // NOTE: If you add a new keycode here you must also add it to several other files.
    //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
Loading