Merge "Updating ATRACE_ASYNC_FOR_TRACK_END to not require a name argument"
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 967b942..e3ea455 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -51,12 +51,9 @@
#define ATRACE_TAG ATRACE_TAG_BIONIC
#include <utils/Trace.h>
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
+#include <unwindstack/AndroidUnwinder.h>
+#include <unwindstack/Error.h>
#include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
#include "libdebuggerd/backtrace.h"
#include "libdebuggerd/tombstone.h"
@@ -623,9 +620,12 @@
}
// TODO: Use seccomp to lock ourselves down.
- unwindstack::UnwinderFromPid unwinder(256, vm_pid, unwindstack::Regs::CurrentArch());
- if (!unwinder.Init()) {
- LOG(FATAL) << "Failed to init unwinder object.";
+
+ unwindstack::AndroidRemoteUnwinder unwinder(vm_pid, unwindstack::Regs::CurrentArch());
+ unwindstack::ErrorData error_data;
+ if (!unwinder.Initialize(error_data)) {
+ LOG(FATAL) << "Failed to initialize unwinder object: "
+ << unwindstack::GetErrorCodeString(error_data.code);
}
std::string amfd_data;
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index c8b25ae..70e3022 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -31,12 +31,9 @@
#include <android-base/unique_fd.h>
#include <async_safe/log.h>
#include <bionic/reserved_signals.h>
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
+#include <unwindstack/AndroidUnwinder.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
#include "debuggerd/handler.h"
#include "handler/fallback.h"
@@ -75,11 +72,11 @@
// Do not use the thread cache here because it will call pthread_key_create
// which doesn't work in linker code. See b/189803009.
- // Use a normal cached object because the process is stopped, and there
+ // Use a normal cached object because the thread is stopped, and there
// is no chance of data changing between reads.
auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
// TODO: Create this once and store it in a global?
- unwindstack::UnwinderFromPid unwinder(kMaxFrames, getpid(), process_memory);
+ unwindstack::AndroidLocalUnwinder unwinder(process_memory);
dump_backtrace_thread(output_fd, &unwinder, thread);
}
__linker_disable_fallback_allocator();
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index fd91038..3ff9710 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -37,6 +37,7 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <log/log.h>
+#include <unwindstack/AndroidUnwinder.h>
#include <unwindstack/Unwinder.h>
#include "libdebuggerd/types.h"
@@ -57,7 +58,7 @@
_LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid);
}
-void dump_backtrace_thread(int output_fd, unwindstack::Unwinder* unwinder,
+void dump_backtrace_thread(int output_fd, unwindstack::AndroidUnwinder* unwinder,
const ThreadInfo& thread) {
log_t log;
log.tfd = output_fd;
@@ -65,21 +66,17 @@
_LOG(&log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", thread.thread_name.c_str(), thread.tid);
- unwinder->SetRegs(thread.registers.get());
- unwinder->Unwind();
- if (unwinder->NumFrames() == 0) {
- _LOG(&log, logtype::THREAD, "Unwind failed: tid = %d\n", thread.tid);
- if (unwinder->LastErrorCode() != unwindstack::ERROR_NONE) {
- _LOG(&log, logtype::THREAD, " Error code: %s\n", unwinder->LastErrorCodeString());
- _LOG(&log, logtype::THREAD, " Error address: 0x%" PRIx64 "\n", unwinder->LastErrorAddress());
- }
+ unwindstack::AndroidUnwinderData data;
+ if (!unwinder->Unwind(thread.registers.get(), data)) {
+ _LOG(&log, logtype::THREAD, "Unwind failed: tid = %d: Error %s\n", thread.tid,
+ data.GetErrorString().c_str());
return;
}
- log_backtrace(&log, unwinder, " ");
+ log_backtrace(&log, unwinder, data, " ");
}
-void dump_backtrace(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
+void dump_backtrace(android::base::unique_fd output_fd, unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread) {
log_t log;
log.tfd = output_fd.get();
diff --git a/debuggerd/libdebuggerd/gwp_asan.cpp b/debuggerd/libdebuggerd/gwp_asan.cpp
index 3d96627..d8f74e0 100644
--- a/debuggerd/libdebuggerd/gwp_asan.cpp
+++ b/debuggerd/libdebuggerd/gwp_asan.cpp
@@ -21,9 +21,8 @@
#include "gwp_asan/common.h"
#include "gwp_asan/crash_handler.h"
-#include <unwindstack/Maps.h>
+#include <unwindstack/AndroidUnwinder.h>
#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
#include <unwindstack/Unwinder.h>
#include "tombstone.pb.h"
@@ -106,7 +105,8 @@
constexpr size_t kMaxTraceLength = gwp_asan::AllocationMetadata::kMaxTraceLengthToCollect;
-void GwpAsanCrashData::AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const {
+void GwpAsanCrashData::AddCauseProtos(Tombstone* tombstone,
+ unwindstack::AndroidUnwinder* unwinder) const {
if (!CrashIsMine()) {
ALOGE("Internal Error: AddCauseProtos() on a non-GWP-ASan crash.");
return;
@@ -140,7 +140,6 @@
heap_object->set_address(__gwp_asan_get_allocation_address(responsible_allocation_));
heap_object->set_size(__gwp_asan_get_allocation_size(responsible_allocation_));
- unwinder->SetDisplayBuildID(true);
std::unique_ptr<uintptr_t[]> frames(new uintptr_t[kMaxTraceLength]);
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/backtrace.h b/debuggerd/libdebuggerd/include/libdebuggerd/backtrace.h
index c20d090..531afea 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/backtrace.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/backtrace.h
@@ -30,16 +30,16 @@
// Forward delcaration
namespace unwindstack {
-class Unwinder;
+class AndroidUnwinder;
}
// Dumps a backtrace using a format similar to what Dalvik uses so that the result
// can be intermixed in a bug report.
-void dump_backtrace(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
+void dump_backtrace(android::base::unique_fd output_fd, unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread);
void dump_backtrace_header(int output_fd);
-void dump_backtrace_thread(int output_fd, unwindstack::Unwinder* unwinder,
+void dump_backtrace_thread(int output_fd, unwindstack::AndroidUnwinder* unwinder,
const ThreadInfo& thread);
void dump_backtrace_footer(int output_fd);
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h b/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h
index a979370..0429643 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h
@@ -26,9 +26,15 @@
#include "types.h"
#include "utility.h"
+// Forward delcarations
class Cause;
class Tombstone;
+namespace unwindstack {
+class AndroidUnwinder;
+class Memory;
+} // namespace unwindstack
+
class GwpAsanCrashData {
public:
GwpAsanCrashData() = delete;
@@ -52,7 +58,7 @@
// allocator crash state.
uintptr_t GetFaultAddress() const;
- void AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const;
+ void AddCauseProtos(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder) const;
protected:
// Is GWP-ASan responsible for this crash.
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h b/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h
index 172ffe9..a506859 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h
@@ -23,9 +23,15 @@
#include "scudo/interface.h"
+// Forward delcarations
class Cause;
class Tombstone;
+namespace unwindstack {
+class AndroidUnwinder;
+class Memory;
+} // namespace unwindstack
+
class ScudoCrashData {
public:
ScudoCrashData() = delete;
@@ -34,12 +40,12 @@
bool CrashIsMine() const;
- void AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const;
+ void AddCauseProtos(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder) const;
private:
scudo_error_info error_info_ = {};
uintptr_t untagged_fault_addr_;
void FillInCause(Cause* cause, const scudo_error_report* report,
- unwindstack::Unwinder* unwinder) const;
+ unwindstack::AndroidUnwinder* unwinder) const;
};
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
index 7bf1688..be999e0 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
@@ -37,7 +37,7 @@
namespace unwindstack {
struct FrameData;
-class Unwinder;
+class AndroidUnwinder;
}
// The maximum number of frames to save when unwinding.
@@ -51,7 +51,7 @@
/* Creates a tombstone file and writes the crash dump to it. */
void engrave_tombstone(android::base::unique_fd output_fd, android::base::unique_fd proto_fd,
- unwindstack::Unwinder* unwinder,
+ unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
const ProcessInfo& process_info, OpenFilesList* open_files,
std::string* amfd_data);
@@ -59,7 +59,7 @@
void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_msg_address,
siginfo_t* siginfo, ucontext_t* ucontext);
-void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
+void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
const ProcessInfo& process_info, const OpenFilesList* open_files);
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index 63e142f..25b03af 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
@@ -73,11 +73,13 @@
void _VLOG(log_t* log, logtype ltype, const char* fmt, va_list ap);
namespace unwindstack {
-class Unwinder;
+class AndroidUnwinder;
class Memory;
+struct AndroidUnwinderData;
}
-void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* prefix);
+void log_backtrace(log_t* log, unwindstack::AndroidUnwinder* unwinder,
+ unwindstack::AndroidUnwinderData& data, const char* prefix);
ssize_t dump_memory(void* out, size_t len, uint8_t* tags, size_t tags_len, uint64_t* addr,
unwindstack::Memory* memory);
diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp
index a4836d7..27fae25 100644
--- a/debuggerd/libdebuggerd/scudo.cpp
+++ b/debuggerd/libdebuggerd/scudo.cpp
@@ -17,8 +17,8 @@
#include "libdebuggerd/scudo.h"
#include "libdebuggerd/tombstone.h"
+#include "unwindstack/AndroidUnwinder.h"
#include "unwindstack/Memory.h"
-#include "unwindstack/Unwinder.h"
#include <android-base/macros.h>
#include <bionic/macros.h>
@@ -80,7 +80,7 @@
}
void ScudoCrashData::FillInCause(Cause* cause, const scudo_error_report* report,
- unwindstack::Unwinder* unwinder) const {
+ unwindstack::AndroidUnwinder* unwinder) const {
MemoryError* memory_error = cause->mutable_memory_error();
HeapObject* heap_object = memory_error->mutable_heap();
@@ -102,7 +102,6 @@
heap_object->set_address(report->allocation_address);
heap_object->set_size(report->allocation_size);
- unwinder->SetDisplayBuildID(true);
heap_object->set_allocation_tid(report->allocation_tid);
for (size_t i = 0; i < arraysize(report->allocation_trace) && report->allocation_trace[i]; ++i) {
@@ -123,7 +122,8 @@
set_human_readable_cause(cause, untagged_fault_addr_);
}
-void ScudoCrashData::AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const {
+void ScudoCrashData::AddCauseProtos(Tombstone* tombstone,
+ unwindstack::AndroidUnwinder* unwinder) const {
size_t report_num = 0;
while (report_num < sizeof(error_info_.reports) / sizeof(error_info_.reports[0]) &&
error_info_.reports[report_num].error_type != UNKNOWN) {
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index eda7182..5ca2c00 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -36,9 +36,9 @@
#include <async_safe/log.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
-#include <unwindstack/Memory.h>
+#include <unwindstack/AndroidUnwinder.h>
+#include <unwindstack/Error.h>
#include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
#include "libdebuggerd/backtrace.h"
#include "libdebuggerd/open_files_list.h"
@@ -101,12 +101,16 @@
}
}
- auto process_memory =
- unwindstack::Memory::CreateProcessMemoryCached(getpid());
- unwindstack::UnwinderFromPid unwinder(kMaxFrames, pid, unwindstack::Regs::CurrentArch(), nullptr,
- process_memory);
- if (!unwinder.Init()) {
- async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to init unwinder object");
+ // Do not use the thread cache here because it will call pthread_key_create
+ // which doesn't work in linker code. See b/189803009.
+ // Use a normal cached object because the thread is stopped, and there
+ // is no chance of data changing between reads.
+ auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
+ unwindstack::AndroidLocalUnwinder unwinder(process_memory);
+ unwindstack::ErrorData error;
+ if (!unwinder.Initialize(error)) {
+ async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to init unwinder object: %s",
+ unwindstack::GetErrorCodeString(error.code));
return;
}
@@ -116,7 +120,8 @@
process_info, nullptr, nullptr);
}
-void engrave_tombstone(unique_fd output_fd, unique_fd proto_fd, unwindstack::Unwinder* unwinder,
+void engrave_tombstone(unique_fd output_fd, unique_fd proto_fd,
+ unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
const ProcessInfo& process_info, OpenFilesList* open_files,
std::string* amfd_data) {
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index bee4a67..159ebc8 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -56,10 +56,11 @@
#include <private/android_filesystem_config.h>
#include <procinfo/process.h>
+#include <unwindstack/AndroidUnwinder.h>
+#include <unwindstack/Error.h>
+#include <unwindstack/MapInfo.h>
#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
#include "libdebuggerd/open_files_list.h"
#include "libdebuggerd/utility.h"
@@ -189,7 +190,7 @@
error_type_str, diff, byte_suffix, location_str, heap_object.size(), heap_object.address()));
}
-static void dump_probable_cause(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
+static void dump_probable_cause(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
const ProcessInfo& process_info, const ThreadInfo& main_thread) {
#if defined(USE_SCUDO)
ScudoCrashData scudo_crash_data(unwinder->GetProcessMemory().get(), process_info);
@@ -245,9 +246,9 @@
}
}
-static void dump_abort_message(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
+static void dump_abort_message(Tombstone* tombstone,
+ std::shared_ptr<unwindstack::Memory>& process_memory,
const ProcessInfo& process_info) {
- std::shared_ptr<unwindstack::Memory> process_memory = unwinder->GetProcessMemory();
uintptr_t address = process_info.abort_msg_address;
if (address == 0) {
return;
@@ -348,7 +349,7 @@
f->set_build_id(frame.map_info->GetPrintableBuildID());
}
-static void dump_registers(unwindstack::Unwinder* unwinder,
+static void dump_registers(unwindstack::AndroidUnwinder* unwinder,
const std::unique_ptr<unwindstack::Regs>& regs, Thread& thread,
bool memory_dump) {
if (regs == nullptr) {
@@ -402,27 +403,9 @@
});
}
-static void log_unwinder_error(unwindstack::Unwinder* unwinder) {
- if (unwinder->LastErrorCode() == unwindstack::ERROR_NONE) {
- return;
- }
-
- async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, " error code: %s",
- unwinder->LastErrorCodeString());
- async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, " error address: 0x%" PRIx64,
- unwinder->LastErrorAddress());
-}
-
-static void dump_thread_backtrace(unwindstack::Unwinder* unwinder, Thread& thread) {
- if (unwinder->NumFrames() == 0) {
- async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to unwind");
- log_unwinder_error(unwinder);
- return;
- }
-
- unwinder->SetDisplayBuildID(true);
+static void dump_thread_backtrace(std::vector<unwindstack::FrameData>& frames, Thread& thread) {
std::set<std::string> unreadable_elf_files;
- for (const auto& frame : unwinder->frames()) {
+ for (const auto& frame : frames) {
BacktraceFrame* f = thread.add_current_backtrace();
fill_in_backtrace_frame(f, frame);
if (frame.map_info != nullptr && frame.map_info->ElfFileNotReadable()) {
@@ -446,7 +429,7 @@
}
}
-static void dump_thread(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
+static void dump_thread(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
const ThreadInfo& thread_info, bool memory_dump = false) {
Thread thread;
@@ -455,36 +438,29 @@
thread.set_tagged_addr_ctrl(thread_info.tagged_addr_ctrl);
thread.set_pac_enabled_keys(thread_info.pac_enabled_keys);
- if (thread_info.pid == getpid() && thread_info.pid != thread_info.tid) {
- // Fallback path for non-main thread, doing unwind from running process.
- unwindstack::ThreadUnwinder thread_unwinder(kMaxFrames, unwinder->GetMaps());
- if (!thread_unwinder.Init()) {
- async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
- "Unable to initialize ThreadUnwinder object.");
- log_unwinder_error(&thread_unwinder);
- return;
- }
-
- std::unique_ptr<unwindstack::Regs> initial_regs;
- thread_unwinder.UnwindWithSignal(BIONIC_SIGNAL_BACKTRACE, thread_info.tid, &initial_regs);
- dump_registers(&thread_unwinder, initial_regs, thread, memory_dump);
- dump_thread_backtrace(&thread_unwinder, thread);
+ unwindstack::AndroidUnwinderData data;
+ // Indicate we want a copy of the initial registers.
+ data.saved_initial_regs = std::make_optional<std::unique_ptr<unwindstack::Regs>>();
+ bool unwind_ret;
+ if (thread_info.registers != nullptr) {
+ unwind_ret = unwinder->Unwind(thread_info.registers.get(), data);
} else {
- dump_registers(unwinder, thread_info.registers, thread, memory_dump);
- std::unique_ptr<unwindstack::Regs> regs_copy(thread_info.registers->Clone());
- unwinder->SetRegs(regs_copy.get());
- unwinder->Unwind();
- dump_thread_backtrace(unwinder, thread);
+ unwind_ret = unwinder->Unwind(thread_info.tid, data);
}
+ if (!unwind_ret) {
+ async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "Unwind failed for tid %d: Error %s",
+ thread_info.tid, data.GetErrorString().c_str());
+ } else {
+ dump_thread_backtrace(data.frames, thread);
+ }
+ dump_registers(unwinder, *data.saved_initial_regs, thread, memory_dump);
auto& threads = *tombstone->mutable_threads();
threads[thread_info.tid] = thread;
}
-static void dump_mappings(Tombstone* tombstone, unwindstack::Unwinder* unwinder) {
- unwindstack::Maps* maps = unwinder->GetMaps();
- std::shared_ptr<unwindstack::Memory> process_memory = unwinder->GetProcessMemory();
-
+static void dump_mappings(Tombstone* tombstone, unwindstack::Maps* maps,
+ std::shared_ptr<unwindstack::Memory>& process_memory) {
for (const auto& map_info : *maps) {
auto* map = tombstone->add_memory_mappings();
map->set_begin_address(map_info->start());
@@ -593,7 +569,8 @@
}
static void dump_tags_around_fault_addr(Signal* signal, const Tombstone& tombstone,
- unwindstack::Unwinder* unwinder, uintptr_t fault_addr) {
+ std::shared_ptr<unwindstack::Memory>& process_memory,
+ uintptr_t fault_addr) {
if (tombstone.arch() != Architecture::ARM64) return;
fault_addr = untag_address(fault_addr);
@@ -604,8 +581,6 @@
// a valid address for us to dump tags from.
if (fault_addr < kBytesToRead / 2) return;
- unwindstack::Memory* memory = unwinder->GetProcessMemory().get();
-
constexpr uintptr_t kRowStartMask = ~(kNumTagColumns * kTagGranuleSize - 1);
size_t start_address = (fault_addr & kRowStartMask) - kBytesToRead / 2;
MemoryDump tag_dump;
@@ -614,7 +589,7 @@
// Attempt to read the first tag. If reading fails, this likely indicates the
// lowest touched page is inaccessible or not marked with PROT_MTE.
// Fast-forward over pages until one has tags, or we exhaust the search range.
- while (memory->ReadTag(start_address) < 0) {
+ while (process_memory->ReadTag(start_address) < 0) {
size_t page_size = sysconf(_SC_PAGE_SIZE);
size_t bytes_to_next_page = page_size - (start_address % page_size);
if (bytes_to_next_page >= granules_to_read * kTagGranuleSize) return;
@@ -626,7 +601,7 @@
std::string* mte_tags = tag_dump.mutable_arm_mte_metadata()->mutable_memory_tags();
for (size_t i = 0; i < granules_to_read; ++i) {
- long tag = memory->ReadTag(start_address + i * kTagGranuleSize);
+ long tag = process_memory->ReadTag(start_address + i * kTagGranuleSize);
if (tag < 0) break;
mte_tags->push_back(static_cast<uint8_t>(tag));
}
@@ -636,7 +611,7 @@
}
}
-void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
+void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
const ProcessInfo& process_info, const OpenFilesList* open_files) {
Tombstone result;
@@ -691,12 +666,12 @@
sig.set_has_fault_address(true);
uintptr_t fault_addr = process_info.maybe_tagged_fault_address;
sig.set_fault_address(fault_addr);
- dump_tags_around_fault_addr(&sig, result, unwinder, fault_addr);
+ dump_tags_around_fault_addr(&sig, result, unwinder->GetProcessMemory(), fault_addr);
}
*result.mutable_signal_info() = sig;
- dump_abort_message(&result, unwinder, process_info);
+ dump_abort_message(&result, unwinder->GetProcessMemory(), process_info);
// Dump the main thread, but save the memory around the registers.
dump_thread(&result, unwinder, main_thread, /* memory_dump */ true);
@@ -709,7 +684,7 @@
dump_probable_cause(&result, unwinder, process_info, main_thread);
- dump_mappings(&result, unwinder);
+ dump_mappings(&result, unwinder->GetMaps(), unwinder->GetProcessMemory());
// Only dump logs on debuggable devices.
if (android::base::GetBoolProperty("ro.debuggable", false)) {
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index ecd98a4..74a1423 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -39,6 +39,7 @@
#include <bionic/reserved_signals.h>
#include <debuggerd/handler.h>
#include <log/log.h>
+#include <unwindstack/AndroidUnwinder.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Unwinder.h>
@@ -483,10 +484,10 @@
return describe_end(value, desc);
}
-void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* prefix) {
+void log_backtrace(log_t* log, unwindstack::AndroidUnwinder* unwinder,
+ unwindstack::AndroidUnwinderData& data, const char* prefix) {
std::set<std::string> unreadable_elf_files;
- unwinder->SetDisplayBuildID(true);
- for (const auto& frame : unwinder->frames()) {
+ for (const auto& frame : data.frames) {
if (frame.map_info != nullptr && frame.map_info->ElfFileNotReadable()) {
unreadable_elf_files.emplace(frame.map_info->name());
}
@@ -509,7 +510,7 @@
}
}
- for (const auto& frame : unwinder->frames()) {
+ for (const auto& frame : data.frames) {
_LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, unwinder->FormatFrame(frame).c_str());
}
}
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index 9ae2c37..5c07eb0 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -130,12 +130,10 @@
"-Werror",
"-Wvla",
"-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
+ "-Wthread-safety",
],
rtti: true,
- clang_cflags: [
- "-Wthread-safety",
- ],
}
cc_binary {
@@ -215,7 +213,7 @@
"-Werror",
"-Wunreachable-code",
"-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
- "-D_FILE_OFFSET_BITS=64"
+ "-D_FILE_OFFSET_BITS=64",
],
target: {
@@ -411,7 +409,7 @@
":fastboot_test_vendor_ramdisk_replace",
":fastboot_test_vendor_boot_v3",
":fastboot_test_vendor_boot_v4_without_frag",
- ":fastboot_test_vendor_boot_v4_with_frag"
+ ":fastboot_test_vendor_boot_v4_with_frag",
],
}
diff --git a/fastboot/fuzzy_fastboot/Android.bp b/fastboot/fuzzy_fastboot/Android.bp
index 159c314..2031170 100644
--- a/fastboot/fuzzy_fastboot/Android.bp
+++ b/fastboot/fuzzy_fastboot/Android.bp
@@ -9,6 +9,7 @@
cc_test_host {
name: "fuzzy_fastboot",
+ isolated: false,
compile_multilib: "first",
srcs: [
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 6863894..396bcb8 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -124,8 +124,8 @@
FS_STAT_RO_MOUNT_FAILED = 0x0040,
FS_STAT_RO_UNMOUNT_FAILED = 0x0080,
FS_STAT_FULL_MOUNT_FAILED = 0x0100,
- FS_STAT_E2FSCK_FAILED = 0x0200,
- FS_STAT_E2FSCK_FS_FIXED = 0x0400,
+ FS_STAT_FSCK_FAILED = 0x0200,
+ FS_STAT_FSCK_FS_FIXED = 0x0400,
FS_STAT_INVALID_MAGIC = 0x0800,
FS_STAT_TOGGLE_QUOTAS_FAILED = 0x10000,
FS_STAT_SET_RESERVED_BLOCKS_FAILED = 0x20000,
@@ -136,7 +136,6 @@
};
static void log_fs_stat(const std::string& blk_device, int fs_stat) {
- if ((fs_stat & FS_STAT_IS_EXT4) == 0) return; // only log ext4
std::string msg =
android::base::StringPrintf("\nfs_stat,%s,0x%x\n", blk_device.c_str(), fs_stat);
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(FSCK_LOG_FILE, O_WRONLY | O_CLOEXEC |
@@ -166,7 +165,7 @@
return fs_stat &
(FS_STAT_E2FSCK_F_ALWAYS | FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED |
FS_STAT_RO_MOUNT_FAILED | FS_STAT_RO_UNMOUNT_FAILED | FS_STAT_FULL_MOUNT_FAILED |
- FS_STAT_E2FSCK_FAILED | FS_STAT_TOGGLE_QUOTAS_FAILED |
+ FS_STAT_FSCK_FAILED | FS_STAT_TOGGLE_QUOTAS_FAILED |
FS_STAT_SET_RESERVED_BLOCKS_FAILED | FS_STAT_ENABLE_ENCRYPTION_FAILED);
}
@@ -255,10 +254,10 @@
if (ret < 0) {
/* No need to check for error in fork, we can't really handle it now */
LERROR << "Failed trying to run " << E2FSCK_BIN;
- *fs_stat |= FS_STAT_E2FSCK_FAILED;
+ *fs_stat |= FS_STAT_FSCK_FAILED;
} else if (status != 0) {
LINFO << "e2fsck returned status 0x" << std::hex << status;
- *fs_stat |= FS_STAT_E2FSCK_FS_FIXED;
+ *fs_stat |= FS_STAT_FSCK_FS_FIXED;
}
}
} else if (is_f2fs(fs_type)) {
@@ -267,20 +266,30 @@
const char* f2fs_fsck_forced_argv[] = {
F2FS_FSCK_BIN, "-f", "-c", "10000", "--debug-cache", blk_device.c_str()};
- if (should_force_check(*fs_stat)) {
- LINFO << "Running " << F2FS_FSCK_BIN << " -f -c 10000 --debug-cache "
- << realpath(blk_device);
- ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_forced_argv), f2fs_fsck_forced_argv,
- &status, false, LOG_KLOG | LOG_FILE, false, nullptr);
+ if (access(F2FS_FSCK_BIN, X_OK)) {
+ LINFO << "Not running " << F2FS_FSCK_BIN << " on " << realpath(blk_device)
+ << " (executable not in system image)";
} else {
- LINFO << "Running " << F2FS_FSCK_BIN << " -a -c 10000 --debug-cache "
- << realpath(blk_device);
- ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status, false,
- LOG_KLOG | LOG_FILE, false, nullptr);
- }
- if (ret < 0) {
- /* No need to check for error in fork, we can't really handle it now */
- LERROR << "Failed trying to run " << F2FS_FSCK_BIN;
+ if (should_force_check(*fs_stat)) {
+ LINFO << "Running " << F2FS_FSCK_BIN << " -f -c 10000 --debug-cache "
+ << realpath(blk_device);
+ ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_forced_argv), f2fs_fsck_forced_argv,
+ &status, false, LOG_KLOG | LOG_FILE, false,
+ FSCK_LOG_FILE);
+ } else {
+ LINFO << "Running " << F2FS_FSCK_BIN << " -a -c 10000 --debug-cache "
+ << realpath(blk_device);
+ ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status,
+ false, LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE);
+ }
+ if (ret < 0) {
+ /* No need to check for error in fork, we can't really handle it now */
+ LERROR << "Failed trying to run " << F2FS_FSCK_BIN;
+ *fs_stat |= FS_STAT_FSCK_FAILED;
+ } else if (status != 0) {
+ LINFO << F2FS_FSCK_BIN << " returned status 0x" << std::hex << status;
+ *fs_stat |= FS_STAT_FSCK_FS_FIXED;
+ }
}
}
android::base::SetProperty("ro.boottime.init.fsck." + Basename(target),
@@ -1911,6 +1920,7 @@
while (retry_count-- > 0) {
if (!__mount(n_blk_device, mount_point, fstab_entry)) {
fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
+ log_fs_stat(fstab_entry.blk_device, fs_stat);
return FS_MGR_DOMNT_SUCCESS;
} else {
if (retry_count <= 0) break; // run check_fs only once
diff --git a/fs_mgr/liblp/TEST_MAPPING b/fs_mgr/liblp/TEST_MAPPING
index 875ccb0..cf0d22b 100644
--- a/fs_mgr/liblp/TEST_MAPPING
+++ b/fs_mgr/liblp/TEST_MAPPING
@@ -4,7 +4,7 @@
"name": "liblp_test"
}
],
- "hwasan-postsubmit": [
+ "hwasan-presubmit": [
{
"name": "liblp_test"
}
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index 8e6bbd9..f4d5c72 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -171,11 +171,11 @@
std::optional<uint64_t> last_label_;
std::shared_ptr<std::vector<CowOperation>> ops_;
std::shared_ptr<std::vector<uint32_t>> merge_op_blocks_;
- uint64_t merge_op_start_;
+ uint64_t merge_op_start_{};
std::shared_ptr<std::unordered_map<uint32_t, int>> block_map_;
- uint64_t num_total_data_ops_;
- uint64_t num_ordered_ops_to_merge_;
- bool has_seq_ops_;
+ uint64_t num_total_data_ops_{};
+ uint64_t num_ordered_ops_to_merge_{};
+ bool has_seq_ops_{};
std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc_;
ReaderFlags reader_flag_;
};
diff --git a/init/Android.bp b/init/Android.bp
index dd67d04..f91265e 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -178,7 +178,6 @@
"update_metadata-protos",
],
shared_libs: [
- "libbacktrace",
"libbase",
"libbootloader_message",
"libcrypto",
@@ -195,6 +194,7 @@
"libprocessgroup",
"libprocessgroup_setup",
"libselinux",
+ "libunwindstack",
"libutils",
"libziparchive",
],
@@ -352,7 +352,6 @@
"libgsi",
"liblzma",
"libunwindstack_no_dex",
- "libbacktrace_no_dex",
"libmodprobe",
"libext2_uuid",
"libprotobuf-cpp-lite",
diff --git a/init/action.h b/init/action.h
index 1534bf9..eddc384 100644
--- a/init/action.h
+++ b/init/action.h
@@ -22,6 +22,8 @@
#include <variant>
#include <vector>
+#include <android-base/strings.h>
+
#include "builtins.h"
#include "keyword_map.h"
#include "result.h"
@@ -79,6 +81,7 @@
static void set_function_map(const BuiltinFunctionMap* function_map) {
function_map_ = function_map;
}
+ bool IsFromApex() const { return base::StartsWith(filename_, "/apex/"); }
private:
void ExecuteCommand(const Command& command) const;
diff --git a/init/action_manager.h b/init/action_manager.h
index b6f93d9..2746a7c 100644
--- a/init/action_manager.h
+++ b/init/action_manager.h
@@ -37,6 +37,10 @@
size_t CheckAllCommands();
void AddAction(std::unique_ptr<Action> action);
+ template <class UnaryPredicate>
+ void RemoveActionIf(UnaryPredicate predicate) {
+ actions_.erase(std::remove_if(actions_.begin(), actions_.end(), predicate), actions_.end());
+ }
void QueueEventTrigger(const std::string& trigger);
void QueuePropertyChange(const std::string& name, const std::string& value);
void QueueAllPropertyActions();
diff --git a/init/action_parser.cpp b/init/action_parser.cpp
index 52f6a1f..49fe24a 100644
--- a/init/action_parser.cpp
+++ b/init/action_parser.cpp
@@ -142,6 +142,14 @@
action_subcontext = subcontext_;
}
+ // We support 'on' for only Vendor APEXes from /{vendor, odm}.
+ // It is to prevent mainline modules from using 'on' triggers because events/properties are
+ // not stable for mainline modules.
+ // Note that this relies on Subcontext::PathMatchesSubcontext() to identify Vendor APEXes.
+ if (StartsWith(filename, "/apex/") && !action_subcontext) {
+ return Error() << "ParseSection() failed: 'on' is supported for only Vendor APEXes.";
+ }
+
std::string event_trigger;
std::map<std::string, std::string> property_triggers;
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 01db4f5..9e1d93c 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1288,7 +1288,8 @@
return Error() << "glob pattern '" << glob_pattern << "' failed";
}
std::vector<std::string> configs;
- Parser parser = CreateServiceOnlyParser(ServiceList::GetInstance(), true);
+ Parser parser =
+ CreateApexConfigParser(ActionManager::GetInstance(), ServiceList::GetInstance());
for (size_t i = 0; i < glob_result.gl_pathc; i++) {
std::string path = glob_result.gl_pathv[i];
// Filter-out /apex/<name>@<ver> paths. The paths are bind-mounted to
diff --git a/init/init.cpp b/init/init.cpp
index 038f172..4955bc5 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -48,7 +48,6 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <backtrace/Backtrace.h>
#include <fs_avb/fs_avb.h>
#include <fs_mgr_vendor_overlay.h>
#include <keyutils.h>
@@ -58,6 +57,7 @@
#include <processgroup/processgroup.h>
#include <processgroup/setup.h>
#include <selinux/android.h>
+#include <unwindstack/AndroidUnwinder.h>
#include "action_parser.h"
#include "builtins.h"
@@ -85,6 +85,10 @@
#include "system/core/init/property_service.pb.h"
#include "util.h"
+#ifndef RECOVERY
+#include "com_android_apex.h"
+#endif // RECOVERY
+
using namespace std::chrono_literals;
using namespace std::string_literals;
@@ -253,12 +257,14 @@
} shutdown_state;
static void UnwindMainThreadStack() {
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, 1));
- if (!backtrace->Unwind(0)) {
- LOG(ERROR) << __FUNCTION__ << "sys.powerctl: Failed to unwind callstack.";
+ unwindstack::AndroidLocalUnwinder unwinder;
+ unwindstack::AndroidUnwinderData data;
+ if (!unwinder.Unwind(data)) {
+ LOG(ERROR) << __FUNCTION__
+ << "sys.powerctl: Failed to unwind callstack: " << data.GetErrorString();
}
- for (size_t i = 0; i < backtrace->NumFrames(); i++) {
- LOG(ERROR) << "sys.powerctl: " << backtrace->FormatFrameData(i);
+ for (const auto& frame : data.frames) {
+ LOG(ERROR) << "sys.powerctl: " << unwinder.FormatFrame(frame);
}
}
@@ -291,13 +297,59 @@
return parser;
}
-// parser that only accepts new services
-Parser CreateServiceOnlyParser(ServiceList& service_list, bool from_apex) {
- Parser parser;
+#ifndef RECOVERY
+template <typename T>
+struct LibXmlErrorHandler {
+ T handler_;
+ template <typename Handler>
+ LibXmlErrorHandler(Handler&& handler) : handler_(std::move(handler)) {
+ xmlSetGenericErrorFunc(nullptr, &ErrorHandler);
+ }
+ ~LibXmlErrorHandler() { xmlSetGenericErrorFunc(nullptr, nullptr); }
+ static void ErrorHandler(void*, const char* msg, ...) {
+ va_list args;
+ va_start(args, msg);
+ char* formatted;
+ if (vasprintf(&formatted, msg, args) >= 0) {
+ LOG(ERROR) << formatted;
+ }
+ free(formatted);
+ va_end(args);
+ }
+};
- parser.AddSectionParser(
- "service", std::make_unique<ServiceParser>(&service_list, GetSubcontext(), std::nullopt,
- from_apex));
+template <typename Handler>
+LibXmlErrorHandler(Handler&&) -> LibXmlErrorHandler<Handler>;
+#endif // RECOVERY
+
+// Returns a Parser that accepts scripts from APEX modules. It supports `service` and `on`.
+Parser CreateApexConfigParser(ActionManager& action_manager, ServiceList& service_list) {
+ Parser parser;
+ auto subcontext = GetSubcontext();
+#ifndef RECOVERY
+ if (subcontext) {
+ const auto apex_info_list_file = "/apex/apex-info-list.xml";
+ auto error_handler = LibXmlErrorHandler([&](const auto& error_message) {
+ LOG(ERROR) << "Failed to read " << apex_info_list_file << ":" << error_message;
+ });
+ const auto apex_info_list = com::android::apex::readApexInfoList(apex_info_list_file);
+ if (apex_info_list.has_value()) {
+ std::vector<std::string> subcontext_apexes;
+ for (const auto& info : apex_info_list->getApexInfo()) {
+ if (info.hasPreinstalledModulePath() &&
+ subcontext->PathMatchesSubcontext(info.getPreinstalledModulePath())) {
+ subcontext_apexes.push_back(info.getModuleName());
+ }
+ }
+ subcontext->SetApexList(std::move(subcontext_apexes));
+ }
+ }
+#endif // RECOVERY
+ parser.AddSectionParser("service",
+ std::make_unique<ServiceParser>(&service_list, subcontext, std::nullopt,
+ /*from_apex=*/true));
+ parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, subcontext));
+
return parser;
}
diff --git a/init/init.h b/init/init.h
index 4f686cb..5220535 100644
--- a/init/init.h
+++ b/init/init.h
@@ -29,7 +29,7 @@
namespace init {
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
-Parser CreateServiceOnlyParser(ServiceList& service_list, bool from_apex);
+Parser CreateApexConfigParser(ActionManager& action_manager, ServiceList& service_list);
bool start_waiting_for_property(const char *name, const char *value);
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 8550ec8..0dc6ff6 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -42,34 +42,34 @@
using ActionManagerCommand = std::function<void(ActionManager&)>;
void TestInit(const std::string& init_script_file, const BuiltinFunctionMap& test_function_map,
- const std::vector<ActionManagerCommand>& commands, ServiceList* service_list) {
- ActionManager am;
-
+ const std::vector<ActionManagerCommand>& commands, ActionManager* action_manager,
+ ServiceList* service_list) {
Action::set_function_map(&test_function_map);
Parser parser;
parser.AddSectionParser("service",
std::make_unique<ServiceParser>(service_list, nullptr, std::nullopt));
- parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
+ parser.AddSectionParser("on", std::make_unique<ActionParser>(action_manager, nullptr));
parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
ASSERT_TRUE(parser.ParseConfig(init_script_file));
for (const auto& command : commands) {
- command(am);
+ command(*action_manager);
}
- while (am.HasMoreCommands()) {
- am.ExecuteOneCommand();
+ while (action_manager->HasMoreCommands()) {
+ action_manager->ExecuteOneCommand();
}
}
void TestInitText(const std::string& init_script, const BuiltinFunctionMap& test_function_map,
- const std::vector<ActionManagerCommand>& commands, ServiceList* service_list) {
+ const std::vector<ActionManagerCommand>& commands, ActionManager* action_manager,
+ ServiceList* service_list) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
ASSERT_TRUE(android::base::WriteStringToFd(init_script, tf.fd));
- TestInit(tf.path, test_function_map, commands, service_list);
+ TestInit(tf.path, test_function_map, commands, action_manager, service_list);
}
TEST(init, SimpleEventTrigger) {
@@ -91,8 +91,9 @@
ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
std::vector<ActionManagerCommand> commands{trigger_boot};
+ ActionManager action_manager;
ServiceList service_list;
- TestInitText(init_script, test_function_map, commands, &service_list);
+ TestInitText(init_script, test_function_map, commands, &action_manager, &service_list);
EXPECT_TRUE(expect_true);
}
@@ -154,8 +155,10 @@
ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
std::vector<ActionManagerCommand> commands{trigger_boot};
+ ActionManager action_manager;
ServiceList service_list;
- TestInitText(init_script, test_function_map, commands, &service_list);
+ TestInitText(init_script, test_function_map, commands, &action_manager, &service_list);
+ EXPECT_EQ(3, num_executed);
}
TEST(init, OverrideService) {
@@ -169,8 +172,9 @@
)init";
+ ActionManager action_manager;
ServiceList service_list;
- TestInitText(init_script, BuiltinFunctionMap(), {}, &service_list);
+ TestInitText(init_script, BuiltinFunctionMap(), {}, &action_manager, &service_list);
ASSERT_EQ(1, std::distance(service_list.begin(), service_list.end()));
auto service = service_list.begin()->get();
@@ -236,13 +240,100 @@
ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
std::vector<ActionManagerCommand> commands{trigger_boot};
+ ActionManager action_manager;
ServiceList service_list;
-
- TestInit(start.path, test_function_map, commands, &service_list);
+ TestInit(start.path, test_function_map, commands, &action_manager, &service_list);
EXPECT_EQ(6, num_executed);
}
+BuiltinFunctionMap GetTestFunctionMapForLazyLoad(int& num_executed, ActionManager& action_manager) {
+ auto execute_command = [&num_executed](const BuiltinArguments& args) {
+ EXPECT_EQ(2U, args.size());
+ EXPECT_EQ(++num_executed, std::stoi(args[1]));
+ return Result<void>{};
+ };
+ auto load_command = [&action_manager](const BuiltinArguments& args) -> Result<void> {
+ EXPECT_EQ(2U, args.size());
+ Parser parser;
+ parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, nullptr));
+ if (!parser.ParseConfig(args[1])) {
+ return Error() << "Failed to load";
+ }
+ return Result<void>{};
+ };
+ auto trigger_command = [&action_manager](const BuiltinArguments& args) {
+ EXPECT_EQ(2U, args.size());
+ LOG(INFO) << "Queue event trigger: " << args[1];
+ action_manager.QueueEventTrigger(args[1]);
+ return Result<void>{};
+ };
+ BuiltinFunctionMap test_function_map = {
+ {"execute", {1, 1, {false, execute_command}}},
+ {"load", {1, 1, {false, load_command}}},
+ {"trigger", {1, 1, {false, trigger_command}}},
+ };
+ return test_function_map;
+}
+
+TEST(init, LazilyLoadedActionsCantBeTriggeredByTheSameTrigger) {
+ // "start" script loads "lazy" script. Even though "lazy" scripts
+ // defines "on boot" action, it's not executed by the current "boot"
+ // event because it's already processed.
+ TemporaryFile lazy;
+ ASSERT_TRUE(lazy.fd != -1);
+ ASSERT_TRUE(android::base::WriteStringToFd("on boot\nexecute 2", lazy.fd));
+
+ TemporaryFile start;
+ // clang-format off
+ std::string start_script = "on boot\n"
+ "load " + std::string(lazy.path) + "\n"
+ "execute 1";
+ // clang-format on
+ ASSERT_TRUE(android::base::WriteStringToFd(start_script, start.fd));
+
+ int num_executed = 0;
+ ActionManager action_manager;
+ ServiceList service_list;
+ BuiltinFunctionMap test_function_map =
+ GetTestFunctionMapForLazyLoad(num_executed, action_manager);
+
+ ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
+ std::vector<ActionManagerCommand> commands{trigger_boot};
+ TestInit(start.path, test_function_map, commands, &action_manager, &service_list);
+
+ EXPECT_EQ(1, num_executed);
+}
+
+TEST(init, LazilyLoadedActionsCanBeTriggeredByTheNextTrigger) {
+ // "start" script loads "lazy" script and then triggers "next" event
+ // which executes "on next" action loaded by the previous command.
+ TemporaryFile lazy;
+ ASSERT_TRUE(lazy.fd != -1);
+ ASSERT_TRUE(android::base::WriteStringToFd("on next\nexecute 2", lazy.fd));
+
+ TemporaryFile start;
+ // clang-format off
+ std::string start_script = "on boot\n"
+ "load " + std::string(lazy.path) + "\n"
+ "execute 1\n"
+ "trigger next";
+ // clang-format on
+ ASSERT_TRUE(android::base::WriteStringToFd(start_script, start.fd));
+
+ int num_executed = 0;
+ ActionManager action_manager;
+ ServiceList service_list;
+ BuiltinFunctionMap test_function_map =
+ GetTestFunctionMapForLazyLoad(num_executed, action_manager);
+
+ ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
+ std::vector<ActionManagerCommand> commands{trigger_boot};
+ TestInit(start.path, test_function_map, commands, &action_manager, &service_list);
+
+ EXPECT_EQ(2, num_executed);
+}
+
TEST(init, RejectsCriticalAndOneshotService) {
if (GetIntProperty("ro.product.first_api_level", 10000) < 30) {
GTEST_SKIP() << "Test only valid for devices launching with R or later";
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 41cf748..4e4bfd8 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -892,7 +892,16 @@
sub_reason = "ns_switch";
return Error() << "Failed to switch to bootstrap namespace";
}
- // Remove services that were defined in an APEX.
+ ActionManager::GetInstance().RemoveActionIf([](const auto& action) -> bool {
+ if (action->IsFromApex()) {
+ std::string trigger_name = action->BuildTriggersString();
+ LOG(INFO) << "Removing action (" << trigger_name << ") from (" << action->filename()
+ << ":" << action->line() << ")";
+ return true;
+ }
+ return false;
+ });
+ // Remove services that were defined in an APEX
ServiceList::GetInstance().RemoveServiceIf([](const std::unique_ptr<Service>& s) -> bool {
if (s->is_from_apex()) {
LOG(INFO) << "Removing service '" << s->name() << "' because it's defined in an APEX";
diff --git a/init/reboot_utils.cpp b/init/reboot_utils.cpp
index b3fa9fd..f8e1de0 100644
--- a/init/reboot_utils.cpp
+++ b/init/reboot_utils.cpp
@@ -26,8 +26,8 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
-#include <backtrace/Backtrace.h>
#include <cutils/android_reboot.h>
+#include <unwindstack/AndroidUnwinder.h>
#include "capabilities.h"
#include "reboot_utils.h"
@@ -157,13 +157,13 @@
// In the parent, let's try to get a backtrace then shutdown.
LOG(ERROR) << __FUNCTION__ << ": signal " << signal_number;
- std::unique_ptr<Backtrace> backtrace(
- Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- if (!backtrace->Unwind(0)) {
- LOG(ERROR) << __FUNCTION__ << ": Failed to unwind callstack.";
+ unwindstack::AndroidLocalUnwinder unwinder;
+ unwindstack::AndroidUnwinderData data;
+ if (!unwinder.Unwind(data)) {
+ LOG(ERROR) << __FUNCTION__ << ": Failed to unwind callstack: " << data.GetErrorString();
}
- for (size_t i = 0; i < backtrace->NumFrames(); i++) {
- LOG(ERROR) << backtrace->FormatFrameData(i);
+ for (const auto& frame : data.frames) {
+ LOG(ERROR) << unwinder.FormatFrame(frame);
}
if (init_fatal_panic) {
LOG(ERROR) << __FUNCTION__ << ": Trigger crash";
diff --git a/init/service.cpp b/init/service.cpp
index 077477a..01dd685 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -288,6 +288,10 @@
if (flags_ & SVC_EXEC) UnSetExec();
+ if (name_ == "zygote" || name_ == "zygote64") {
+ removeAllEmptyProcessGroups();
+ }
+
if (flags_ & SVC_TEMPORARY) return;
pid_ = 0;
@@ -541,6 +545,10 @@
if ((flags_ & SVC_ONESHOT) && disabled) {
flags_ |= SVC_RESTART;
}
+
+ LOG(INFO) << "service '" << name_
+ << "' requested start, but it is already running (flags: " << flags_ << ")";
+
// It is not an error to try to start a service that is already running.
reboot_on_failure.Disable();
return {};
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index 7aa4a9d..bb3967e 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -250,7 +250,14 @@
Fork();
}
-bool Subcontext::PathMatchesSubcontext(const std::string& path) {
+bool Subcontext::PathMatchesSubcontext(const std::string& path) const {
+ static const std::string kApexDir = "/apex/";
+ if (StartsWith(path, kApexDir)) {
+ auto begin = kApexDir.size();
+ auto end = path.find('/', begin);
+ auto apex_name = path.substr(begin, end - begin);
+ return std::find(apex_list_.begin(), apex_list_.end(), apex_name) != apex_list_.end();
+ }
for (const auto& prefix : path_prefixes_) {
if (StartsWith(path, prefix)) {
return true;
@@ -259,6 +266,10 @@
return false;
}
+void Subcontext::SetApexList(std::vector<std::string>&& apex_list) {
+ apex_list_ = std::move(apex_list);
+}
+
Result<SubcontextReply> Subcontext::TransmitMessage(const SubcontextCommand& subcontext_command) {
if (auto result = SendMessage(socket_, subcontext_command); !result.ok()) {
Restart();
diff --git a/init/subcontext.h b/init/subcontext.h
index cb4138e..8acc032 100644
--- a/init/subcontext.h
+++ b/init/subcontext.h
@@ -46,7 +46,8 @@
Result<void> Execute(const std::vector<std::string>& args);
Result<std::vector<std::string>> ExpandArgs(const std::vector<std::string>& args);
void Restart();
- bool PathMatchesSubcontext(const std::string& path);
+ bool PathMatchesSubcontext(const std::string& path) const;
+ void SetApexList(std::vector<std::string>&& apex_list);
const std::string& context() const { return context_; }
pid_t pid() const { return pid_; }
@@ -56,6 +57,7 @@
Result<SubcontextReply> TransmitMessage(const SubcontextCommand& subcontext_command);
std::vector<std::string> path_prefixes_;
+ std::vector<std::string> apex_list_;
std::string context_;
pid_t pid_;
android::base::unique_fd socket_;
diff --git a/init/util.cpp b/init/util.cpp
index d1e518b..1801d17 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -61,6 +61,8 @@
const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android/");
+const std::string kDataDirPrefix("/data/");
+
void (*trigger_shutdown)(const std::string& command) = nullptr;
// DecodeUid() - decodes and returns the given string, which can be either the
@@ -458,58 +460,34 @@
return {};
}
-static FscryptAction FscryptInferAction(const std::string& dir) {
- const std::string prefix = "/data/";
-
- if (!android::base::StartsWith(dir, prefix)) {
- return FscryptAction::kNone;
- }
-
- // Special-case /data/media/obb per b/64566063
- if (dir == "/data/media/obb") {
- // Try to set policy on this directory, but if it is non-empty this may fail.
- return FscryptAction::kAttempt;
- }
-
- // Only set policy on first level /data directories
- // To make this less restrictive, consider using a policy file.
- // However this is overkill for as long as the policy is simply
- // to apply a global policy to all /data folders created via makedir
- if (dir.find_first_of('/', prefix.size()) != std::string::npos) {
- return FscryptAction::kNone;
- }
-
- // Special case various directories that must not be encrypted,
- // often because their subdirectories must be encrypted.
- // This isn't a nice way to do this, see b/26641735
- std::vector<std::string> directories_to_exclude = {
- "lost+found", "system_ce", "system_de", "misc_ce", "misc_de",
- "vendor_ce", "vendor_de", "media", "data", "user",
- "user_de", "apex", "preloads", "app-staging", "gsi",
- };
- for (const auto& d : directories_to_exclude) {
- if ((prefix + d) == dir) {
- return FscryptAction::kNone;
+// Remove unnecessary slashes so that any later checks (e.g., the check for
+// whether the path is a top-level directory in /data) don't get confused.
+std::string CleanDirPath(const std::string& path) {
+ std::string result;
+ result.reserve(path.length());
+ // Collapse duplicate slashes, e.g. //data//foo// => /data/foo/
+ for (char c : path) {
+ if (c != '/' || result.empty() || result.back() != '/') {
+ result += c;
}
}
- // Empty these directories if policy setting fails.
- std::vector<std::string> wipe_on_failure = {
- "rollback", "rollback-observer", // b/139193659
- };
- for (const auto& d : wipe_on_failure) {
- if ((prefix + d) == dir) {
- return FscryptAction::kDeleteIfNecessary;
- }
+ // Remove trailing slash, e.g. /data/foo/ => /data/foo
+ if (result.length() > 1 && result.back() == '/') {
+ result.pop_back();
}
- return FscryptAction::kRequire;
+ return result;
}
Result<MkdirOptions> ParseMkdir(const std::vector<std::string>& args) {
+ std::string path = CleanDirPath(args[1]);
+ const bool is_toplevel_data_dir =
+ StartsWith(path, kDataDirPrefix) &&
+ path.find_first_of('/', kDataDirPrefix.size()) == std::string::npos;
+ FscryptAction fscrypt_action =
+ is_toplevel_data_dir ? FscryptAction::kRequire : FscryptAction::kNone;
mode_t mode = 0755;
Result<uid_t> uid = -1;
Result<gid_t> gid = -1;
- FscryptAction fscrypt_inferred_action = FscryptInferAction(args[1]);
- FscryptAction fscrypt_action = fscrypt_inferred_action;
std::string ref_option = "ref";
bool set_option_encryption = false;
bool set_option_key = false;
@@ -574,24 +552,17 @@
if (set_option_key && fscrypt_action == FscryptAction::kNone) {
return Error() << "Key option set but encryption action is none";
}
- const std::string prefix = "/data/";
- if (StartsWith(args[1], prefix) &&
- args[1].find_first_of('/', prefix.size()) == std::string::npos) {
+ if (is_toplevel_data_dir) {
if (!set_option_encryption) {
- LOG(WARNING) << "Top-level directory needs encryption action, eg mkdir " << args[1]
+ LOG(WARNING) << "Top-level directory needs encryption action, eg mkdir " << path
<< " <mode> <uid> <gid> encryption=Require";
}
if (fscrypt_action == FscryptAction::kNone) {
- LOG(INFO) << "Not setting encryption policy on: " << args[1];
+ LOG(INFO) << "Not setting encryption policy on: " << path;
}
}
- if (fscrypt_action != fscrypt_inferred_action) {
- LOG(WARNING) << "Inferred action different from explicit one, expected "
- << static_cast<int>(fscrypt_inferred_action) << " but got "
- << static_cast<int>(fscrypt_action);
- }
- return MkdirOptions{args[1], mode, *uid, *gid, fscrypt_action, ref_option};
+ return MkdirOptions{path, mode, *uid, *gid, fscrypt_action, ref_option};
}
Result<MountAllOptions> ParseMountAll(const std::vector<std::string>& args) {
diff --git a/init/util.h b/init/util.h
index bf53675..47d4ff5 100644
--- a/init/util.h
+++ b/init/util.h
@@ -69,6 +69,7 @@
bool IsLegalPropertyName(const std::string& name);
Result<void> IsLegalPropertyValue(const std::string& name, const std::string& value);
+std::string CleanDirPath(const std::string& path);
struct MkdirOptions {
std::string target;
diff --git a/init/util_test.cpp b/init/util_test.cpp
index 565e7d4..e8144c3 100644
--- a/init/util_test.cpp
+++ b/init/util_test.cpp
@@ -170,5 +170,18 @@
EXPECT_TRUE(is_dir(path1.c_str()));
}
+TEST(util, CleanDirPath) {
+ EXPECT_EQ("", CleanDirPath(""));
+ EXPECT_EQ("/", CleanDirPath("/"));
+ EXPECT_EQ("/", CleanDirPath("//"));
+ EXPECT_EQ("/foo", CleanDirPath("/foo"));
+ EXPECT_EQ("/foo", CleanDirPath("//foo"));
+ EXPECT_EQ("/foo", CleanDirPath("/foo/"));
+ EXPECT_EQ("/foo/bar", CleanDirPath("/foo/bar"));
+ EXPECT_EQ("/foo/bar", CleanDirPath("/foo/bar/"));
+ EXPECT_EQ("/foo/bar", CleanDirPath("/foo/bar////"));
+ EXPECT_EQ("/foo/bar", CleanDirPath("//foo//bar"));
+}
+
} // namespace init
} // namespace android
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index c5badc9..39b9f3f 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -67,6 +67,7 @@
bool setProcessGroupLimit(uid_t uid, int initialPid, int64_t limitInBytes);
void removeAllProcessGroups(void);
+void removeAllEmptyProcessGroups(void);
// Provides the path for an attribute in a specific process group
// Returns false in case of error, true in case of success
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index e3a80e9..267e62c 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -200,7 +200,7 @@
return ret;
}
-static bool RemoveUidProcessGroups(const std::string& uid_path) {
+static bool RemoveUidProcessGroups(const std::string& uid_path, bool empty_only) {
std::unique_ptr<DIR, decltype(&closedir)> uid(opendir(uid_path.c_str()), closedir);
bool empty = true;
if (uid != NULL) {
@@ -215,6 +215,21 @@
}
auto path = StringPrintf("%s/%s", uid_path.c_str(), dir->d_name);
+ if (empty_only) {
+ struct stat st;
+ auto procs_file = StringPrintf("%s/%s", path.c_str(),
+ PROCESSGROUP_CGROUP_PROCS_FILE);
+ if (stat(procs_file.c_str(), &st) == -1) {
+ PLOG(ERROR) << "Failed to get stats for " << procs_file;
+ continue;
+ }
+ if (st.st_size > 0) {
+ // skip non-empty groups
+ LOG(VERBOSE) << "Skipping non-empty group " << path;
+ empty = false;
+ continue;
+ }
+ }
LOG(VERBOSE) << "Removing " << path;
if (rmdir(path.c_str()) == -1) {
if (errno != EBUSY) {
@@ -227,9 +242,7 @@
return empty;
}
-void removeAllProcessGroups() {
- LOG(VERBOSE) << "removeAllProcessGroups()";
-
+void removeAllProcessGroupsInternal(bool empty_only) {
std::vector<std::string> cgroups;
std::string path, memcg_apps_path;
@@ -256,7 +269,7 @@
}
auto path = StringPrintf("%s/%s", cgroup_root_path.c_str(), dir->d_name);
- if (!RemoveUidProcessGroups(path)) {
+ if (!RemoveUidProcessGroups(path, empty_only)) {
LOG(VERBOSE) << "Skip removing " << path;
continue;
}
@@ -269,6 +282,16 @@
}
}
+void removeAllProcessGroups() {
+ LOG(VERBOSE) << "removeAllProcessGroups()";
+ removeAllProcessGroupsInternal(false);
+}
+
+void removeAllEmptyProcessGroups() {
+ LOG(VERBOSE) << "removeAllEmptyProcessGroups()";
+ removeAllProcessGroupsInternal(true);
+}
+
/**
* Process groups are primarily created by the Zygote, meaning that uid/pid groups are created by
* the user root. Ownership for the newly created cgroup and all of its files must thus be
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index f5533c2..8589a8d 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -224,19 +224,6 @@
]
},
{
- "Name": "VMCompilationPerformance",
- "Actions": [
- {
- "Name": "JoinCgroup",
- "Params":
- {
- "Controller": "cpu",
- "Path": "system"
- }
- }
- ]
- },
- {
"Name": "CpuPolicySpread",
"Actions": [
{
@@ -660,6 +647,10 @@
"Profiles": [ "ServicePerformance", "LowIoPriority", "TimerSlackNormal" ]
},
{
+ "Name": "SCHED_SP_COMPUTE",
+ "Profiles": [ "HighPerformance", "ProcessCapacityHigh", "LowIoPriority", "TimerSlackNormal" ]
+ },
+ {
"Name": "SCHED_SP_RT_APP",
"Profiles": [ "RealtimePerformance", "MaxIoPriority", "TimerSlackNormal" ]
},
diff --git a/libsparse/img2simg.cpp b/libsparse/img2simg.cpp
index 3e24cc0..51580f7 100644
--- a/libsparse/img2simg.cpp
+++ b/libsparse/img2simg.cpp
@@ -38,24 +38,41 @@
#endif
void usage() {
- fprintf(stderr, "Usage: img2simg <raw_image_file> <sparse_image_file> [<block_size>]\n");
+ fprintf(stderr, "Usage: img2simg [-s] <raw_image_file> <sparse_image_file> [<block_size>]\n");
}
int main(int argc, char* argv[]) {
+ char *arg_in;
+ char *arg_out;
+ enum sparse_read_mode mode = SPARSE_READ_MODE_NORMAL;
+ int extra;
int in;
+ int opt;
int out;
int ret;
struct sparse_file* s;
unsigned int block_size = 4096;
off64_t len;
- if (argc < 3 || argc > 4) {
+ while ((opt = getopt(argc, argv, "s")) != -1) {
+ switch (opt) {
+ case 's':
+ mode = SPARSE_READ_MODE_HOLE;
+ break;
+ default:
+ usage();
+ exit(-1);
+ }
+ }
+
+ extra = argc - optind;
+ if (extra < 2 || extra > 3) {
usage();
exit(-1);
}
- if (argc == 4) {
- block_size = atoi(argv[3]);
+ if (extra == 3) {
+ block_size = atoi(argv[optind + 2]);
}
if (block_size < 1024 || block_size % 4 != 0) {
@@ -63,22 +80,24 @@
exit(-1);
}
- if (strcmp(argv[1], "-") == 0) {
+ arg_in = argv[optind];
+ if (strcmp(arg_in, "-") == 0) {
in = STDIN_FILENO;
} else {
- in = open(argv[1], O_RDONLY | O_BINARY);
+ in = open(arg_in, O_RDONLY | O_BINARY);
if (in < 0) {
- fprintf(stderr, "Cannot open input file %s\n", argv[1]);
+ fprintf(stderr, "Cannot open input file %s\n", arg_in);
exit(-1);
}
}
- if (strcmp(argv[2], "-") == 0) {
+ arg_out = argv[optind + 1];
+ if (strcmp(arg_out, "-") == 0) {
out = STDOUT_FILENO;
} else {
- out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
+ out = open(arg_out, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
if (out < 0) {
- fprintf(stderr, "Cannot open output file %s\n", argv[2]);
+ fprintf(stderr, "Cannot open output file %s\n", arg_out);
exit(-1);
}
}
@@ -93,7 +112,7 @@
}
sparse_file_verbose(s);
- ret = sparse_file_read(s, in, SPARSE_READ_MODE_NORMAL, false);
+ ret = sparse_file_read(s, in, mode, false);
if (ret) {
fprintf(stderr, "Failed to read file\n");
exit(-1);
diff --git a/libsparse/sparse_fuzzer.cpp b/libsparse/sparse_fuzzer.cpp
index 235d15d..663c812 100644
--- a/libsparse/sparse_fuzzer.cpp
+++ b/libsparse/sparse_fuzzer.cpp
@@ -23,5 +23,7 @@
if (!file) {
return 0;
}
- return sparse_file_callback(file, false, false, WriteCallback, nullptr);
+ int32_t result = sparse_file_callback(file, false, false, WriteCallback, nullptr);
+ sparse_file_destroy(file);
+ return result;
}
diff --git a/libstats/socket_lazy/TEST_MAPPING b/libstats/socket_lazy/TEST_MAPPING
index b182660..03506cd 100644
--- a/libstats/socket_lazy/TEST_MAPPING
+++ b/libstats/socket_lazy/TEST_MAPPING
@@ -4,7 +4,7 @@
"name" : "libstatssocket_lazy_test"
}
],
- "hwasan-postsubmit" : [
+ "hwasan-presubmit" : [
{
"name" : "libstatssocket_lazy_test"
}
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 1b29285..f663671 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -44,14 +44,6 @@
export_include_dirs: ["include"],
target: {
- android: {
- header_libs: ["libbacktrace_headers"],
- export_header_lib_headers: ["libbacktrace_headers"],
- },
- host_linux: {
- header_libs: ["libbacktrace_headers"],
- export_header_lib_headers: ["libbacktrace_headers"],
- },
linux_bionic: {
enabled: true,
},
@@ -196,7 +188,7 @@
shared_libs: [
"libutils",
- "libbacktrace",
+ "libunwindstack",
],
target: {
diff --git a/libutils/CallStack.cpp b/libutils/CallStack.cpp
index fe6f33d..f19ba6a 100644
--- a/libutils/CallStack.cpp
+++ b/libutils/CallStack.cpp
@@ -20,7 +20,7 @@
#include <utils/Errors.h>
#include <utils/Log.h>
-#include <backtrace/Backtrace.h>
+#include <unwindstack/AndroidUnwinder.h>
#define CALLSTACK_WEAK // Don't generate weak definitions.
#include <utils/CallStack.h>
@@ -39,14 +39,25 @@
}
void CallStack::update(int32_t ignoreDepth, pid_t tid) {
+ if (ignoreDepth < 0) {
+ ignoreDepth = 0;
+ }
+
mFrameLines.clear();
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, tid));
- if (!backtrace->Unwind(ignoreDepth)) {
- ALOGW("%s: Failed to unwind callstack.", __FUNCTION__);
+ unwindstack::AndroidLocalUnwinder unwinder;
+ unwindstack::AndroidUnwinderData data;
+ std::optional<pid_t> tid_val;
+ if (tid != -1) {
+ *tid_val = tid;
}
- for (size_t i = 0; i < backtrace->NumFrames(); i++) {
- mFrameLines.push_back(String8(backtrace->FormatFrameData(i).c_str()));
+ if (!unwinder.Unwind(tid_val, data)) {
+ ALOGW("%s: Failed to unwind callstack: %s", __FUNCTION__, data.GetErrorString().c_str());
+ }
+ for (size_t i = ignoreDepth; i < data.frames.size(); i++) {
+ auto& frame = data.frames[i];
+ frame.num -= ignoreDepth;
+ mFrameLines.push_back(String8(unwinder.FormatFrame(frame).c_str()));
}
}
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
index c97a19b..d951b8b 100644
--- a/libutils/VectorImpl.cpp
+++ b/libutils/VectorImpl.cpp
@@ -279,14 +279,12 @@
ssize_t VectorImpl::removeItemsAt(size_t index, size_t count)
{
- ALOG_ASSERT((index+count)<=size(),
- "[%p] remove: index=%d, count=%d, size=%d",
- this, (int)index, (int)count, (int)size());
-
- if ((index+count) > size())
- return BAD_VALUE;
- _shrink(index, count);
- return index;
+ size_t end;
+ LOG_ALWAYS_FATAL_IF(__builtin_add_overflow(index, count, &end), "overflow: index=%zu count=%zu",
+ index, count);
+ if (end > size()) return BAD_VALUE;
+ _shrink(index, count);
+ return index;
}
void VectorImpl::finish_vector()
diff --git a/libutils/Vector_test.cpp b/libutils/Vector_test.cpp
index 5336c40..6d90eaa 100644
--- a/libutils/Vector_test.cpp
+++ b/libutils/Vector_test.cpp
@@ -136,4 +136,13 @@
}
}
+TEST_F(VectorTest, removeItemsAt_overflow) {
+ android::Vector<int> v;
+ for (int i = 0; i < 666; i++) v.add(i);
+
+ ASSERT_DEATH(v.removeItemsAt(SIZE_MAX, 666), "overflow");
+ ASSERT_DEATH(v.removeItemsAt(666, SIZE_MAX), "overflow");
+ ASSERT_DEATH(v.removeItemsAt(SIZE_MAX, SIZE_MAX), "overflow");
+}
+
} // namespace android
diff --git a/libutils/include/utils/CallStack.h b/libutils/include/utils/CallStack.h
index 7a4a345..fe4d4f5 100644
--- a/libutils/include/utils/CallStack.h
+++ b/libutils/include/utils/CallStack.h
@@ -20,7 +20,6 @@
#include <memory>
#include <android/log.h>
-#include <backtrace/backtrace_constants.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -59,7 +58,7 @@
// Immediately collect the stack traces for the specified thread.
// The default is to dump the stack of the current call.
- void update(int32_t ignoreDepth = 1, pid_t tid = BACKTRACE_CURRENT_THREAD);
+ void update(int32_t ignoreDepth = 1, pid_t tid = -1);
// Dump a stack trace to the log using the supplied logtag.
void log(const char* logtag,
diff --git a/libutils/include/utils/Thread.h b/libutils/include/utils/Thread.h
index fc67656..5cf6b47 100644
--- a/libutils/include/utils/Thread.h
+++ b/libutils/include/utils/Thread.h
@@ -42,7 +42,9 @@
{
public:
// Create a Thread object, but doesn't create or start the associated
- // thread. See the run() method.
+ // thread. See the run() method. This object must be used with RefBase/sp,
+ // like any other RefBase object, because they are conventionally promoted
+ // from bare pointers (Thread::run is particularly problematic here).
explicit Thread(bool canCallJava = true);
virtual ~Thread();
diff --git a/property_service/TEST_MAPPING b/property_service/TEST_MAPPING
index 20f6c84..7b02b51 100644
--- a/property_service/TEST_MAPPING
+++ b/property_service/TEST_MAPPING
@@ -4,7 +4,7 @@
"name": "propertyinfoserializer_tests"
}
],
- "hwasan-postsubmit": [
+ "hwasan-presubmit": [
{
"name": "propertyinfoserializer_tests"
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index aae28dc..70a3736 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -86,6 +86,10 @@
mkdir /dev/sys/fs 0755 system system
mkdir /dev/sys/block 0755 system system
+ # Create location for fs_mgr to store abbreviated output from filesystem
+ # checker programs.
+ mkdir /dev/fscklogs 0770 root system
+
# Run boringssl self test for each ABI so that later processes can skip it. http://b/139348610
on early-init && property:ro.product.cpu.abilist32=*
exec_start boringssl_self_test32
@@ -97,22 +101,18 @@
exec_start boringssl_self_test_apex64
service boringssl_self_test32 /system/bin/boringssl_self_test32
- setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
service boringssl_self_test64 /system/bin/boringssl_self_test64
- setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
service boringssl_self_test_apex32 /apex/com.android.conscrypt/bin/boringssl_self_test32
- setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
service boringssl_self_test_apex64 /apex/com.android.conscrypt/bin/boringssl_self_test64
- setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
@@ -447,10 +447,6 @@
mount bpf bpf /sys/fs/bpf nodev noexec nosuid
- # Create location for fs_mgr to store abbreviated output from filesystem
- # checker programs.
- mkdir /dev/fscklogs 0770 root system
-
# pstore/ramoops previous console log
mount pstore pstore /sys/fs/pstore nodev noexec nosuid
chown system log /sys/fs/pstore
@@ -538,6 +534,10 @@
# /data, which in turn can only be loaded when system properties are present.
trigger post-fs-data
+ # APEXes are ready to use. apex-ready is a public trigger similar to apexd.status=ready which
+ # is a system-private property.
+ trigger apex-ready
+
# Should be before netd, but after apex, properties and logging is available.
trigger load_bpf_programs
@@ -688,8 +688,6 @@
copy /data/system/entropy.dat /dev/urandom
mkdir /data/vendor 0771 root root encryption=Require
- mkdir /data/vendor_ce 0771 root root encryption=None
- mkdir /data/vendor_de 0771 root root encryption=None
mkdir /data/vendor/hardware 0771 root root
# Start tombstoned early to be able to store tombstones.
@@ -738,6 +736,13 @@
# To handle userspace reboots as well as devices that use FDE, make sure
# that apexd is started cleanly here (set apexd.status="") and that it is
# restarted if it's already running.
+ #
+ # /data/apex uses encryption=None because direct I/O support is needed on
+ # APEX files, but some devices don't support direct I/O on encrypted files.
+ # Also, APEXes are public information, similar to the system image.
+ # /data/apex/decompressed and /data/apex/ota_reserved override this setting;
+ # they are encrypted so that files in them can be hard-linked into
+ # /data/rollback which is encrypted.
mkdir /data/apex 0755 root system encryption=None
mkdir /data/apex/active 0755 root system
mkdir /data/apex/backup 0700 root system
@@ -828,19 +833,20 @@
# directory used for odsign metrics
mkdir /data/misc/odsign/metrics 0770 root system
- # Directory for VirtualizationService temporary image files. Always create
- # a fresh new empty directory to remove any stale files from the previous
- # boot.
- rmdir /data/misc/virtualizationservice
- mkdir /data/misc/virtualizationservice 0700 system system
+ # Directory for VirtualizationService temporary image files.
+ # Delete any stale files owned by the old virtualizationservice uid (b/230056726).
+ chmod 0770 /data/misc/virtualizationservice
+ exec - virtualizationservice system -- /bin/rm -rf /data/misc/virtualizationservice
+ mkdir /data/misc/virtualizationservice 0770 system system
+ # /data/preloads uses encryption=None because it only contains preloaded
+ # files that are public information, similar to the system image.
mkdir /data/preloads 0775 system system encryption=None
# For security reasons, /data/local/tmp should always be empty.
# Do not place files or directories in /data/local/tmp
mkdir /data/local/tmp 0771 shell shell
mkdir /data/local/traces 0777 shell shell
- mkdir /data/data 0771 system system encryption=None
mkdir /data/app-private 0771 system system encryption=Require
mkdir /data/app-ephemeral 0771 system system encryption=Require
mkdir /data/app-asec 0700 root root encryption=Require
@@ -878,7 +884,10 @@
chown system system /data/resource-cache
chmod 0771 /data/resource-cache
- # create the lost+found directories, so as to enforce our permissions
+ # Ensure that lost+found exists and has the correct permissions. Linux
+ # filesystems expect this directory to exist; it's where the fsck tool puts
+ # any recovered files that weren't present in any directory. It must be
+ # unencrypted, as fsck must be able to write to it.
mkdir /data/lost+found 0770 root root encryption=None
# create directory for DRM plug-ins - give drm the read/write access to
@@ -906,21 +915,26 @@
mkdir /data/system/heapdump 0700 system system
mkdir /data/system/users 0775 system system
- mkdir /data/system_de 0770 system system encryption=None
- mkdir /data/system_ce 0770 system system encryption=None
-
- mkdir /data/misc_de 01771 system misc encryption=None
+ # Create the parent directories of the user CE and DE storage directories.
+ # These parent directories must use encryption=None, since each of their
+ # subdirectories uses a different encryption policy (a per-user one), and
+ # encryption policies apply recursively. These directories should never
+ # contain any subdirectories other than the per-user ones. /data/media/obb
+ # is an exception that exists for legacy reasons.
+ mkdir /data/media 0770 media_rw media_rw encryption=None
mkdir /data/misc_ce 01771 system misc encryption=None
-
+ mkdir /data/misc_de 01771 system misc encryption=None
+ mkdir /data/system_ce 0770 system system encryption=None
+ mkdir /data/system_de 0770 system system encryption=None
mkdir /data/user 0711 system system encryption=None
mkdir /data/user_de 0711 system system encryption=None
+ mkdir /data/vendor_ce 0771 root root encryption=None
+ mkdir /data/vendor_de 0771 root root encryption=None
- # Unlink /data/user/0 if we previously symlink it to /data/data
- rm /data/user/0
-
- # Bind mount /data/user/0 to /data/data
- mkdir /data/user/0 0700 system system encryption=None
- mount none /data/data /data/user/0 bind rec
+ # Set the casefold flag on /data/media. For upgrades, a restorecon can be
+ # needed first to relabel the directory from media_rw_data_file.
+ restorecon /data/media
+ exec - media_rw media_rw -- /system/bin/chattr +F /data/media
# A tmpfs directory, which will contain all apps CE DE data directory that
# bind mount from the original source.
@@ -933,8 +947,10 @@
mkdir /data_mirror/data_ce/null 0700 root root
mkdir /data_mirror/data_de/null 0700 root root
- # Bind mount CE and DE data directory to mirror's default volume directory
- mount none /data/user /data_mirror/data_ce/null bind rec
+ # Bind mount CE and DE data directory to mirror's default volume directory.
+ # The 'slave' option (MS_SLAVE) is needed to cause the later bind mount of
+ # /data/data onto /data/user/0 to propagate to /data_mirror/data_ce/null/0.
+ mount none /data/user /data_mirror/data_ce/null bind rec slave
mount none /data/user_de /data_mirror/data_de/null bind rec
# Create mirror directory for jit profiles
@@ -967,13 +983,8 @@
wait_for_prop apexd.status activated
perform_apex_config
- # Special-case /data/media/obb per b/64566063
- mkdir /data/media 0770 media_rw media_rw encryption=None
- exec - media_rw media_rw -- /system/bin/chattr +F /data/media
- mkdir /data/media/obb 0770 media_rw media_rw encryption=Attempt
-
# Create directories for boot animation.
- mkdir /data/bootanim 0755 system system encryption=None
+ mkdir /data/bootanim 0755 system system encryption=DeleteIfNecessary
exec_start derive_sdk
@@ -1099,6 +1110,9 @@
write /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time 50
write /dev/sys/fs/by-name/userdata/iostat_enable 1
+ # set readahead multiplier for POSIX_FADV_SEQUENTIAL files
+ write /dev/sys/fs/by-name/userdata/seq_file_ra_mul 16
+
# limit discard size to 128MB in order to avoid long IO latency
# for filesystem tuning first (dm or sda)
# this requires enabling selinux entry for sda/mmcblk0 in vendor side
@@ -1132,10 +1146,6 @@
chown system system /sys/devices/system/cpu/cpufreq/interactive/io_is_busy
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/io_is_busy
- # Assume SMP uses shared cpufreq policy for all CPUs
- chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
- chmod 0660 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
-
chown system system /sys/class/leds/vibrator/trigger
chown system system /sys/class/leds/vibrator/activate
chown system system /sys/class/leds/vibrator/brightness
@@ -1303,6 +1313,7 @@
on userspace-reboot-resume
trigger userspace-reboot-fs-remount
trigger post-fs-data
+ trigger apex-ready
trigger zygote-start
trigger early-boot
trigger boot
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 8cc8b59..cefef6e 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -333,7 +333,7 @@
first_write = false;
}
- if (benchmark_size) {
+ if (benchmark_size && benchmark_time_ns) {
int perf = benchmark_size * 1000000LLU / benchmark_time_ns;
storage_info->update_perf_history(perf, system_clock::now());
}
diff --git a/trusty/keymaster/keymint/TEST_MAPPING b/trusty/keymaster/keymint/TEST_MAPPING
index ae24fb4..6671355 100644
--- a/trusty/keymaster/keymint/TEST_MAPPING
+++ b/trusty/keymaster/keymint/TEST_MAPPING
@@ -4,7 +4,7 @@
"name" : "vts_treble_vintf_framework_test"
}
],
- "hwasan-postsubmit" : [
+ "hwasan-presubmit" : [
{
"name" : "vts_treble_vintf_framework_test"
}
diff --git a/trusty/keymaster/keymint/TrustyKeyMintOperation.cpp b/trusty/keymaster/keymint/TrustyKeyMintOperation.cpp
index 9440724..78e765e 100644
--- a/trusty/keymaster/keymint/TrustyKeyMintOperation.cpp
+++ b/trusty/keymaster/keymint/TrustyKeyMintOperation.cpp
@@ -52,11 +52,15 @@
}
ScopedAStatus TrustyKeyMintOperation::updateAad(
- const vector<uint8_t>& input, const optional<HardwareAuthToken>& /* authToken */,
+ const vector<uint8_t>& input, const optional<HardwareAuthToken>& authToken,
const optional<TimeStampToken>& /* timestampToken */) {
UpdateOperationRequest request(impl_->message_version());
request.op_handle = opHandle_;
request.additional_params.push_back(TAG_ASSOCIATED_DATA, input.data(), input.size());
+ if (authToken) {
+ auto tokenAsVec(authToken2AidlVec(*authToken));
+ request.additional_params.push_back(TAG_AUTH_TOKEN, tokenAsVec.data(), tokenAsVec.size());
+ }
UpdateOperationResponse response(impl_->message_version());
impl_->UpdateOperation(request, &response);