Loading cmds/atrace/atrace.rc +22 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,28 @@ on post-fs chmod 0666 /sys/kernel/debug/tracing/events/lowmemorykiller/enable chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/enable # disk chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_begin/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_end/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_begin/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_end/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable chmod 0666 /sys/kernel/tracing/events/block/block_rq_issue/enable chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_issue/enable chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable # Tracing disabled by default write /sys/kernel/debug/tracing/tracing_on 0 write /sys/kernel/tracing/tracing_on 0 Loading cmds/atrace/atrace_userdebug.rc +0 −22 Original line number Diff line number Diff line Loading @@ -19,25 +19,3 @@ on post-fs chmod 0666 /sys/kernel/debug/tracing/events/irq/enable chmod 0666 /sys/kernel/tracing/events/ipi/enable chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable # disk chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_begin/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_end/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_begin/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_end/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable chmod 0666 /sys/kernel/tracing/events/block/block_rq_issue/enable chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_issue/enable chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable cmds/dumpstate/dumpstate.cpp +85 −54 Original line number Diff line number Diff line Loading @@ -32,14 +32,20 @@ #include <sys/time.h> #include <sys/wait.h> #include <unistd.h> #include <chrono> #include <functional> #include <future> #include <memory> #include <regex> #include <set> #include <string> #include <utility> #include <vector> #include <android-base/file.h> #include <android-base/properties.h> #include <android-base/scopeguard.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> Loading @@ -53,6 +59,7 @@ #include <private/android_filesystem_config.h> #include <private/android_logger.h> #include <serviceutils/PriorityDumper.h> #include <utils/StrongPointer.h> #include "DumpstateInternal.h" #include "DumpstateSectionReporter.h" #include "DumpstateService.h" Loading Loading @@ -1533,77 +1540,101 @@ void Dumpstate::DumpstateBoard() { printf("== Board\n"); printf("========================================================\n"); ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService()); if (dumpstate_device == nullptr) { MYLOGE("No IDumpstateDevice implementation\n"); return; } if (!IsZipping()) { MYLOGD("Not dumping board info because it's not a zipped bugreport\n"); return; } std::string path[NUM_OF_DUMPS]; android::base::unique_fd fd[NUM_OF_DUMPS]; int numFds = 0; std::vector<std::string> paths; std::vector<android::base::ScopeGuard<std::function<void()>>> remover; for (int i = 0; i < NUM_OF_DUMPS; i++) { path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i]; MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str()); fd[i] = android::base::unique_fd( TEMP_FAILURE_RETRY(open(path[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))); if (fd[i] < 0) { MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno)); return; } else { numFds++; paths.emplace_back(kDumpstateBoardPath + kDumpstateBoardFiles[i]); remover.emplace_back(android::base::make_scope_guard(std::bind( [](std::string path) { if (remove(path.c_str()) != 0 && errno != ENOENT) { MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno)); } }, paths[i]))); } native_handle_t *handle = native_handle_create(numFds, 0); // Given that bugreport is required to diagnose failures, it's better to // drop the result of IDumpstateDevice than to block the rest of bugreport // for an arbitrary amount of time. std::packaged_task<std::unique_ptr<ssize_t[]>()> dumpstate_task([paths]() -> std::unique_ptr<ssize_t[]> { ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService()); if (dumpstate_device == nullptr) { MYLOGE("No IDumpstateDevice implementation\n"); return nullptr; } using ScopedNativeHandle = std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>; ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0), [](native_handle_t* handle) { native_handle_close(handle); native_handle_delete(handle); }); if (handle == nullptr) { MYLOGE("Could not create native_handle\n"); return; return nullptr; } for (int i = 0; i < numFds; i++) { handle->data[i] = fd[i].release(); for (size_t i = 0; i < paths.size(); i++) { MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str()); android::base::unique_fd fd(TEMP_FAILURE_RETRY( open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))); if (fd < 0) { MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno)); return nullptr; } handle.get()->data[i] = fd.release(); } // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call. android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle); android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get()); if (!status.isOk()) { MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str()); native_handle_close(handle); native_handle_delete(handle); return nullptr; } auto file_sizes = std::make_unique<ssize_t[]>(paths.size()); for (size_t i = 0; i < paths.size(); i++) { struct stat s; if (fstat(handle.get()->data[i], &s) == -1) { MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno)); file_sizes[i] = -1; continue; } file_sizes[i] = s.st_size; } return file_sizes; }); auto result = dumpstate_task.get_future(); std::thread(std::move(dumpstate_task)).detach(); if (result.wait_for(10s) != std::future_status::ready) { MYLOGE("dumpstateBoard timed out after 10s\n"); return; } std::unique_ptr<ssize_t[]> file_sizes = result.get(); if (file_sizes == nullptr) { return; } for (int i = 0; i < numFds; i++) { struct stat s; if (fstat(handle->data[i], &s) == -1) { MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno); } else if (s.st_size > 0) { AddZipEntry(kDumpstateBoardFiles[i], path[i]); } else { for (size_t i = 0; i < paths.size(); i++) { if (file_sizes[i] == -1) { continue; } if (file_sizes[i] == 0) { MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str()); continue; } AddZipEntry(kDumpstateBoardFiles[i], paths[i]); } printf("*** See dumpstate-board.txt entry ***\n"); native_handle_close(handle); native_handle_delete(handle); for (int i = 0; i < numFds; i++) { if (remove(path[i].c_str()) != 0) { MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno)); } } } static void ShowUsageAndExit(int exitCode = 1) { Loading cmds/installd/InstalldNativeService.cpp +57 −44 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <errno.h> #include <fstream> #include <fts.h> #include <functional> #include <inttypes.h> #include <regex> #include <stdlib.h> Loading Loading @@ -2412,27 +2413,25 @@ binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath, // This kernel feature is experimental. // TODO: remove local definition once upstreamed #ifndef FS_IOC_SET_FSVERITY struct fsverity_set { __u64 offset; __u64 flags; }; #ifndef FS_IOC_ENABLE_VERITY struct fsverity_root_hash { short root_hash_algorithm; short flags; __u8 reserved[4]; __u8 root_hash[64]; }; #define FS_IOC_ENABLE_VERITY _IO('f', 133) #define FS_IOC_SET_VERITY_MEASUREMENT _IOW('f', 134, struct fsverity_measurement) #define FS_IOC_MEASURE_FSVERITY _IOW('f', 133, struct fsverity_root_hash) #define FS_IOC_SET_FSVERITY _IOW('f', 134, struct fsverity_set) #define FS_VERITY_ALG_SHA256 1 struct fsverity_measurement { __u16 digest_algorithm; __u16 digest_size; __u32 reserved1; __u64 reserved2[3]; __u8 digest[]; }; #define FSVERITY_FLAG_ENABLED 0x0001 #endif binder::Status InstalldNativeService::installApkVerity(const std::string& filePath, const ::android::base::unique_fd& verityInputAshmem) { const ::android::base::unique_fd& verityInputAshmem, int32_t contentSize) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_PATH(filePath); std::lock_guard<std::recursive_mutex> lock(mLock); Loading @@ -2440,7 +2439,7 @@ binder::Status InstalldNativeService::installApkVerity(const std::string& filePa if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) { return ok(); } #if DEBUG #ifndef NDEBUG ASSERT_PAGE_SIZE_4K(); #endif // TODO: also check fsverity support in the current file system if compiled with DEBUG. Loading @@ -2449,15 +2448,14 @@ binder::Status InstalldNativeService::installApkVerity(const std::string& filePa 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)); if (wfd.get() < 0) { return error("Failed to open " + filePath + ": " + strerror(errno)); return error("Failed to open " + filePath); } struct stat st; if (fstat(wfd.get(), &st) < 0) { return error("Failed to stat " + filePath + ": " + strerror(errno)); return error("Failed to stat " + filePath); } // fsverity starts from the block boundary. off_t padding = kVerityPageSize - st.st_size % kVerityPageSize; Loading @@ -2465,38 +2463,51 @@ binder::Status InstalldNativeService::installApkVerity(const std::string& filePa padding = 0; } if (lseek(wfd.get(), st.st_size + padding, SEEK_SET) < 0) { return error("Failed to lseek " + filePath + ": " + strerror(errno)); return error("Failed to lseek " + filePath); } // 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)); // 2. Write everything in the ashmem to the file. Note that allocated // ashmem size is multiple of page size, which is different from the // actual content size. int shmSize = ashmem_get_size_region(verityInputAshmem.get()); if (shmSize < 0) { return error("Failed to get ashmem size: " + std::to_string(shmSize)); } void* data = mmap(NULL, size, PROT_READ, MAP_SHARED, verityInputAshmem.get(), 0); if (data == MAP_FAILED) { return error("Failed to mmap the ashmem: " + std::string(strerror(errno))); if (contentSize < 0) { return error("Invalid content size: " + std::to_string(contentSize)); } char* cursor = reinterpret_cast<char*>(data); int remaining = size; if (contentSize > shmSize) { return error("Content size overflow: " + std::to_string(contentSize) + " > " + std::to_string(shmSize)); } auto data = std::unique_ptr<void, std::function<void (void *)>>( mmap(NULL, contentSize, PROT_READ, MAP_SHARED, verityInputAshmem.get(), 0), [contentSize] (void* ptr) { if (ptr != MAP_FAILED) { munmap(ptr, contentSize); } }); if (data.get() == MAP_FAILED) { return error("Failed to mmap the ashmem"); } char* cursor = reinterpret_cast<char*>(data.get()); int remaining = contentSize; while (remaining > 0) { int ret = TEMP_FAILURE_RETRY(write(wfd.get(), cursor, remaining)); if (ret < 0) { munmap(data, size); return error("Failed to write to " + filePath + " (" + std::to_string(remaining) + + "/" + std::to_string(size) + "): " + strerror(errno)); + "/" + std::to_string(contentSize) + ")"); } cursor += ret; remaining -= ret; } munmap(data, size); wfd.reset(); // 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)); // 3. Enable fsverity (needs readonly fd. Once it's done, the file becomes immutable. ::android::base::unique_fd rfd(open(filePath.c_str(), O_RDONLY)); if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, nullptr) < 0) { return error("Failed to enable fsverity on " + filePath); } return ok(); } Loading @@ -2516,17 +2527,19 @@ binder::Status InstalldNativeService::assertFsverityRootHashMatches(const std::s 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) { unsigned int buffer_size = sizeof(fsverity_measurement) + kSha256Size; std::vector<char> buffer(buffer_size, 0); fsverity_measurement* config = reinterpret_cast<fsverity_measurement*>(buffer.data()); config->digest_algorithm = FS_VERITY_ALG_SHA256; config->digest_size = kSha256Size; memcpy(config->digest, expectedHash.data(), kSha256Size); if (ioctl(fd.get(), FS_IOC_SET_VERITY_MEASUREMENT, 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)); Loading cmds/installd/InstalldNativeService.h +1 −1 Original line number Diff line number Diff line Loading @@ -123,7 +123,7 @@ public: binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet, const std::unique_ptr<std::string>& outputPath); binder::Status installApkVerity(const std::string& filePath, const ::android::base::unique_fd& verityInput); const ::android::base::unique_fd& verityInput, int32_t contentSize); binder::Status assertFsverityRootHashMatches(const std::string& filePath, const std::vector<uint8_t>& expectedHash); binder::Status reconcileSecondaryDexFile(const std::string& dexPath, Loading Loading
cmds/atrace/atrace.rc +22 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,28 @@ on post-fs chmod 0666 /sys/kernel/debug/tracing/events/lowmemorykiller/enable chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/enable # disk chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_begin/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_end/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_begin/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_end/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable chmod 0666 /sys/kernel/tracing/events/block/block_rq_issue/enable chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_issue/enable chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable # Tracing disabled by default write /sys/kernel/debug/tracing/tracing_on 0 write /sys/kernel/tracing/tracing_on 0 Loading
cmds/atrace/atrace_userdebug.rc +0 −22 Original line number Diff line number Diff line Loading @@ -19,25 +19,3 @@ on post-fs chmod 0666 /sys/kernel/debug/tracing/events/irq/enable chmod 0666 /sys/kernel/tracing/events/ipi/enable chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable # disk chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_begin/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_end/enable chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_begin/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_end/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit/enable chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable chmod 0666 /sys/kernel/tracing/events/block/block_rq_issue/enable chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_issue/enable chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
cmds/dumpstate/dumpstate.cpp +85 −54 Original line number Diff line number Diff line Loading @@ -32,14 +32,20 @@ #include <sys/time.h> #include <sys/wait.h> #include <unistd.h> #include <chrono> #include <functional> #include <future> #include <memory> #include <regex> #include <set> #include <string> #include <utility> #include <vector> #include <android-base/file.h> #include <android-base/properties.h> #include <android-base/scopeguard.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> Loading @@ -53,6 +59,7 @@ #include <private/android_filesystem_config.h> #include <private/android_logger.h> #include <serviceutils/PriorityDumper.h> #include <utils/StrongPointer.h> #include "DumpstateInternal.h" #include "DumpstateSectionReporter.h" #include "DumpstateService.h" Loading Loading @@ -1533,77 +1540,101 @@ void Dumpstate::DumpstateBoard() { printf("== Board\n"); printf("========================================================\n"); ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService()); if (dumpstate_device == nullptr) { MYLOGE("No IDumpstateDevice implementation\n"); return; } if (!IsZipping()) { MYLOGD("Not dumping board info because it's not a zipped bugreport\n"); return; } std::string path[NUM_OF_DUMPS]; android::base::unique_fd fd[NUM_OF_DUMPS]; int numFds = 0; std::vector<std::string> paths; std::vector<android::base::ScopeGuard<std::function<void()>>> remover; for (int i = 0; i < NUM_OF_DUMPS; i++) { path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i]; MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str()); fd[i] = android::base::unique_fd( TEMP_FAILURE_RETRY(open(path[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))); if (fd[i] < 0) { MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno)); return; } else { numFds++; paths.emplace_back(kDumpstateBoardPath + kDumpstateBoardFiles[i]); remover.emplace_back(android::base::make_scope_guard(std::bind( [](std::string path) { if (remove(path.c_str()) != 0 && errno != ENOENT) { MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno)); } }, paths[i]))); } native_handle_t *handle = native_handle_create(numFds, 0); // Given that bugreport is required to diagnose failures, it's better to // drop the result of IDumpstateDevice than to block the rest of bugreport // for an arbitrary amount of time. std::packaged_task<std::unique_ptr<ssize_t[]>()> dumpstate_task([paths]() -> std::unique_ptr<ssize_t[]> { ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService()); if (dumpstate_device == nullptr) { MYLOGE("No IDumpstateDevice implementation\n"); return nullptr; } using ScopedNativeHandle = std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>; ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0), [](native_handle_t* handle) { native_handle_close(handle); native_handle_delete(handle); }); if (handle == nullptr) { MYLOGE("Could not create native_handle\n"); return; return nullptr; } for (int i = 0; i < numFds; i++) { handle->data[i] = fd[i].release(); for (size_t i = 0; i < paths.size(); i++) { MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str()); android::base::unique_fd fd(TEMP_FAILURE_RETRY( open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))); if (fd < 0) { MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno)); return nullptr; } handle.get()->data[i] = fd.release(); } // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call. android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle); android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get()); if (!status.isOk()) { MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str()); native_handle_close(handle); native_handle_delete(handle); return nullptr; } auto file_sizes = std::make_unique<ssize_t[]>(paths.size()); for (size_t i = 0; i < paths.size(); i++) { struct stat s; if (fstat(handle.get()->data[i], &s) == -1) { MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno)); file_sizes[i] = -1; continue; } file_sizes[i] = s.st_size; } return file_sizes; }); auto result = dumpstate_task.get_future(); std::thread(std::move(dumpstate_task)).detach(); if (result.wait_for(10s) != std::future_status::ready) { MYLOGE("dumpstateBoard timed out after 10s\n"); return; } std::unique_ptr<ssize_t[]> file_sizes = result.get(); if (file_sizes == nullptr) { return; } for (int i = 0; i < numFds; i++) { struct stat s; if (fstat(handle->data[i], &s) == -1) { MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno); } else if (s.st_size > 0) { AddZipEntry(kDumpstateBoardFiles[i], path[i]); } else { for (size_t i = 0; i < paths.size(); i++) { if (file_sizes[i] == -1) { continue; } if (file_sizes[i] == 0) { MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str()); continue; } AddZipEntry(kDumpstateBoardFiles[i], paths[i]); } printf("*** See dumpstate-board.txt entry ***\n"); native_handle_close(handle); native_handle_delete(handle); for (int i = 0; i < numFds; i++) { if (remove(path[i].c_str()) != 0) { MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno)); } } } static void ShowUsageAndExit(int exitCode = 1) { Loading
cmds/installd/InstalldNativeService.cpp +57 −44 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <errno.h> #include <fstream> #include <fts.h> #include <functional> #include <inttypes.h> #include <regex> #include <stdlib.h> Loading Loading @@ -2412,27 +2413,25 @@ binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath, // This kernel feature is experimental. // TODO: remove local definition once upstreamed #ifndef FS_IOC_SET_FSVERITY struct fsverity_set { __u64 offset; __u64 flags; }; #ifndef FS_IOC_ENABLE_VERITY struct fsverity_root_hash { short root_hash_algorithm; short flags; __u8 reserved[4]; __u8 root_hash[64]; }; #define FS_IOC_ENABLE_VERITY _IO('f', 133) #define FS_IOC_SET_VERITY_MEASUREMENT _IOW('f', 134, struct fsverity_measurement) #define FS_IOC_MEASURE_FSVERITY _IOW('f', 133, struct fsverity_root_hash) #define FS_IOC_SET_FSVERITY _IOW('f', 134, struct fsverity_set) #define FS_VERITY_ALG_SHA256 1 struct fsverity_measurement { __u16 digest_algorithm; __u16 digest_size; __u32 reserved1; __u64 reserved2[3]; __u8 digest[]; }; #define FSVERITY_FLAG_ENABLED 0x0001 #endif binder::Status InstalldNativeService::installApkVerity(const std::string& filePath, const ::android::base::unique_fd& verityInputAshmem) { const ::android::base::unique_fd& verityInputAshmem, int32_t contentSize) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_PATH(filePath); std::lock_guard<std::recursive_mutex> lock(mLock); Loading @@ -2440,7 +2439,7 @@ binder::Status InstalldNativeService::installApkVerity(const std::string& filePa if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) { return ok(); } #if DEBUG #ifndef NDEBUG ASSERT_PAGE_SIZE_4K(); #endif // TODO: also check fsverity support in the current file system if compiled with DEBUG. Loading @@ -2449,15 +2448,14 @@ binder::Status InstalldNativeService::installApkVerity(const std::string& filePa 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)); if (wfd.get() < 0) { return error("Failed to open " + filePath + ": " + strerror(errno)); return error("Failed to open " + filePath); } struct stat st; if (fstat(wfd.get(), &st) < 0) { return error("Failed to stat " + filePath + ": " + strerror(errno)); return error("Failed to stat " + filePath); } // fsverity starts from the block boundary. off_t padding = kVerityPageSize - st.st_size % kVerityPageSize; Loading @@ -2465,38 +2463,51 @@ binder::Status InstalldNativeService::installApkVerity(const std::string& filePa padding = 0; } if (lseek(wfd.get(), st.st_size + padding, SEEK_SET) < 0) { return error("Failed to lseek " + filePath + ": " + strerror(errno)); return error("Failed to lseek " + filePath); } // 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)); // 2. Write everything in the ashmem to the file. Note that allocated // ashmem size is multiple of page size, which is different from the // actual content size. int shmSize = ashmem_get_size_region(verityInputAshmem.get()); if (shmSize < 0) { return error("Failed to get ashmem size: " + std::to_string(shmSize)); } void* data = mmap(NULL, size, PROT_READ, MAP_SHARED, verityInputAshmem.get(), 0); if (data == MAP_FAILED) { return error("Failed to mmap the ashmem: " + std::string(strerror(errno))); if (contentSize < 0) { return error("Invalid content size: " + std::to_string(contentSize)); } char* cursor = reinterpret_cast<char*>(data); int remaining = size; if (contentSize > shmSize) { return error("Content size overflow: " + std::to_string(contentSize) + " > " + std::to_string(shmSize)); } auto data = std::unique_ptr<void, std::function<void (void *)>>( mmap(NULL, contentSize, PROT_READ, MAP_SHARED, verityInputAshmem.get(), 0), [contentSize] (void* ptr) { if (ptr != MAP_FAILED) { munmap(ptr, contentSize); } }); if (data.get() == MAP_FAILED) { return error("Failed to mmap the ashmem"); } char* cursor = reinterpret_cast<char*>(data.get()); int remaining = contentSize; while (remaining > 0) { int ret = TEMP_FAILURE_RETRY(write(wfd.get(), cursor, remaining)); if (ret < 0) { munmap(data, size); return error("Failed to write to " + filePath + " (" + std::to_string(remaining) + + "/" + std::to_string(size) + "): " + strerror(errno)); + "/" + std::to_string(contentSize) + ")"); } cursor += ret; remaining -= ret; } munmap(data, size); wfd.reset(); // 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)); // 3. Enable fsverity (needs readonly fd. Once it's done, the file becomes immutable. ::android::base::unique_fd rfd(open(filePath.c_str(), O_RDONLY)); if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, nullptr) < 0) { return error("Failed to enable fsverity on " + filePath); } return ok(); } Loading @@ -2516,17 +2527,19 @@ binder::Status InstalldNativeService::assertFsverityRootHashMatches(const std::s 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) { unsigned int buffer_size = sizeof(fsverity_measurement) + kSha256Size; std::vector<char> buffer(buffer_size, 0); fsverity_measurement* config = reinterpret_cast<fsverity_measurement*>(buffer.data()); config->digest_algorithm = FS_VERITY_ALG_SHA256; config->digest_size = kSha256Size; memcpy(config->digest, expectedHash.data(), kSha256Size); if (ioctl(fd.get(), FS_IOC_SET_VERITY_MEASUREMENT, 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)); Loading
cmds/installd/InstalldNativeService.h +1 −1 Original line number Diff line number Diff line Loading @@ -123,7 +123,7 @@ public: binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet, const std::unique_ptr<std::string>& outputPath); binder::Status installApkVerity(const std::string& filePath, const ::android::base::unique_fd& verityInput); const ::android::base::unique_fd& verityInput, int32_t contentSize); binder::Status assertFsverityRootHashMatches(const std::string& filePath, const std::vector<uint8_t>& expectedHash); binder::Status reconcileSecondaryDexFile(const std::string& dexPath, Loading