Loading cmds/installd/InstalldNativeService.cpp +122 −28 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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> Loading Loading @@ -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 Loading Loading @@ -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() { Loading Loading @@ -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) { Loading Loading @@ -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( Loading cmds/installd/InstalldNativeService.h +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading cmds/installd/binder/android/os/IInstalld.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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, Loading headers/media_plugin/media/drm/DrmAPI.h +39 −0 Original line number Diff line number Diff line Loading @@ -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() {} Loading include/android/keycodes.h +3 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
cmds/installd/InstalldNativeService.cpp +122 −28 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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> Loading Loading @@ -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 Loading Loading @@ -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() { Loading Loading @@ -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) { Loading Loading @@ -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( Loading
cmds/installd/InstalldNativeService.h +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
cmds/installd/binder/android/os/IInstalld.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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, Loading
headers/media_plugin/media/drm/DrmAPI.h +39 −0 Original line number Diff line number Diff line Loading @@ -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() {} Loading
include/android/keycodes.h +3 −1 Original line number Diff line number Diff line Loading @@ -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