Merge "storageproxyd: Retry RPMB request on UNIT ATTENTION"
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 9ca0eba..0ff047f 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -180,7 +180,6 @@
"libdebuggerd/backtrace.cpp",
"libdebuggerd/gwp_asan.cpp",
"libdebuggerd/open_files_list.cpp",
- "libdebuggerd/scudo.cpp",
"libdebuggerd/tombstone.cpp",
"libdebuggerd/tombstone_proto.cpp",
"libdebuggerd/tombstone_proto_to_text.cpp",
@@ -193,9 +192,6 @@
include_dirs: [
// Needed for private/bionic_fdsan.h
"bionic/libc",
-
- // Needed for scudo/interface.h
- "external/scudo/standalone/include",
],
header_libs: [
"bionic_libc_platform_headers",
@@ -217,7 +213,6 @@
whole_static_libs: [
"libasync_safe",
"gwp_asan_crash_handler",
- "libscudo",
"libtombstone_proto",
"libprocinfo",
"libprotobuf-cpp-lite",
@@ -246,6 +241,13 @@
debuggable: {
cflags: ["-DROOT_POSSIBLE"],
},
+
+ malloc_not_svelte: {
+ cflags: ["-DUSE_SCUDO"],
+ whole_static_libs: ["libscudo"],
+ srcs: ["libdebuggerd/scudo.cpp"],
+ header_libs: ["scudo_headers"],
+ },
},
}
@@ -316,10 +318,6 @@
"gwp_asan_headers",
],
- include_dirs: [
- "external/scudo/standalone/include",
- ],
-
local_include_dirs: [
"libdebuggerd",
],
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index ff03bcd..534d7be 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -36,6 +36,7 @@
#include <string>
#include <android-base/file.h>
+#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -57,10 +58,13 @@
#include "libdebuggerd/backtrace.h"
#include "libdebuggerd/gwp_asan.h"
#include "libdebuggerd/open_files_list.h"
-#include "libdebuggerd/scudo.h"
#include "libdebuggerd/utility.h"
#include "util.h"
+#if defined(USE_SCUDO)
+#include "libdebuggerd/scudo.h"
+#endif
+
#include "gwp_asan/common.h"
#include "gwp_asan/crash_handler.h"
@@ -115,8 +119,26 @@
return "";
}
-static void dump_probable_cause(log_t* log, const siginfo_t* si, unwindstack::Maps* maps,
- unwindstack::Regs* regs) {
+static void dump_probable_cause(log_t* log, unwindstack::Unwinder* unwinder,
+ const ProcessInfo& process_info, const ThreadInfo& main_thread) {
+#if defined(USE_SCUDO)
+ ScudoCrashData scudo_crash_data(unwinder->GetProcessMemory().get(), process_info);
+ if (scudo_crash_data.CrashIsMine()) {
+ scudo_crash_data.DumpCause(log, unwinder);
+ return;
+ }
+#endif
+
+ GwpAsanCrashData gwp_asan_crash_data(unwinder->GetProcessMemory().get(), process_info,
+ main_thread);
+ if (gwp_asan_crash_data.CrashIsMine()) {
+ gwp_asan_crash_data.DumpCause(log);
+ return;
+ }
+
+ unwindstack::Maps* maps = unwinder->GetMaps();
+ unwindstack::Regs* regs = main_thread.registers.get();
+ const siginfo_t* si = main_thread.siginfo;
std::string cause;
if (si->si_signo == SIGSEGV && si->si_code == SEGV_MAPERR) {
if (si->si_addr < reinterpret_cast<void*>(4096)) {
@@ -395,22 +417,11 @@
dump_signal_info(log, thread_info, process_info, unwinder->GetProcessMemory().get());
}
- std::unique_ptr<GwpAsanCrashData> gwp_asan_crash_data;
- std::unique_ptr<ScudoCrashData> scudo_crash_data;
if (primary_thread) {
- gwp_asan_crash_data = std::make_unique<GwpAsanCrashData>(unwinder->GetProcessMemory().get(),
- process_info, thread_info);
- scudo_crash_data =
- std::make_unique<ScudoCrashData>(unwinder->GetProcessMemory().get(), process_info);
- }
+ // The main thread must have a valid siginfo.
+ CHECK(thread_info.siginfo != nullptr);
+ dump_probable_cause(log, unwinder, process_info, thread_info);
- if (primary_thread && gwp_asan_crash_data->CrashIsMine()) {
- gwp_asan_crash_data->DumpCause(log);
- } else if (thread_info.siginfo && !(primary_thread && scudo_crash_data->CrashIsMine())) {
- dump_probable_cause(log, thread_info.siginfo, unwinder->GetMaps(), thread_info.registers.get());
- }
-
- if (primary_thread) {
dump_abort_message(log, unwinder->GetProcessMemory().get(), process_info.abort_msg_address);
}
@@ -432,16 +443,17 @@
}
if (primary_thread) {
- if (gwp_asan_crash_data->HasDeallocationTrace()) {
- gwp_asan_crash_data->DumpDeallocationTrace(log, unwinder);
+ GwpAsanCrashData gwp_asan_crash_data(unwinder->GetProcessMemory().get(), process_info,
+ thread_info);
+
+ if (gwp_asan_crash_data.HasDeallocationTrace()) {
+ gwp_asan_crash_data.DumpDeallocationTrace(log, unwinder);
}
- if (gwp_asan_crash_data->HasAllocationTrace()) {
- gwp_asan_crash_data->DumpAllocationTrace(log, unwinder);
+ if (gwp_asan_crash_data.HasAllocationTrace()) {
+ gwp_asan_crash_data.DumpAllocationTrace(log, unwinder);
}
- scudo_crash_data->DumpCause(log, unwinder);
-
unwindstack::Maps* maps = unwinder->GetMaps();
dump_memory_and_code(log, maps, unwinder->GetProcessMemory().get(),
thread_info.registers.get());
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index 99f636e..6c380a1 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -18,7 +18,9 @@
#include "libdebuggerd/tombstone.h"
#include "libdebuggerd/gwp_asan.h"
+#if defined(USE_SCUDO)
#include "libdebuggerd/scudo.h"
+#endif
#include <errno.h>
#include <fcntl.h>
@@ -38,6 +40,7 @@
#include <async_safe/log.h>
#include <android-base/file.h>
+#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -186,11 +189,13 @@
static void dump_probable_cause(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
const ProcessInfo& process_info, const ThreadInfo& main_thread) {
+#if defined(USE_SCUDO)
ScudoCrashData scudo_crash_data(unwinder->GetProcessMemory().get(), process_info);
if (scudo_crash_data.CrashIsMine()) {
scudo_crash_data.AddCauseProtos(tombstone, unwinder);
return;
}
+#endif
GwpAsanCrashData gwp_asan_crash_data(unwinder->GetProcessMemory().get(), process_info,
main_thread);
@@ -612,6 +617,8 @@
result.set_tid(main_thread.tid);
result.set_uid(main_thread.uid);
result.set_selinux_label(main_thread.selinux_label);
+ // The main thread must have a valid siginfo.
+ CHECK(main_thread.siginfo != nullptr);
struct sysinfo si;
sysinfo(&si);
diff --git a/fs_mgr/OWNERS b/fs_mgr/OWNERS
index cf353a1..c6f9054 100644
--- a/fs_mgr/OWNERS
+++ b/fs_mgr/OWNERS
@@ -1,2 +1,4 @@
+# Bug component: 30545
bowgotsai@google.com
dvander@google.com
+elsk@google.com
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 428a7f4..2bb9035 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -86,7 +86,9 @@
name: "vts_libdm_test",
defaults: ["libdm_test_defaults"],
test_suites: ["vts"],
- test_min_api_level: 29,
+ test_options: {
+ min_shipping_api_level: 29,
+ },
}
cc_fuzz {
diff --git a/fs_mgr/libfiemap/Android.bp b/fs_mgr/libfiemap/Android.bp
index d16b8d6..5deba65 100644
--- a/fs_mgr/libfiemap/Android.bp
+++ b/fs_mgr/libfiemap/Android.bp
@@ -90,7 +90,9 @@
test_suites: ["vts", "device-tests"],
auto_gen_config: true,
- test_min_api_level: 29,
+ test_options: {
+ min_shipping_api_level: 29,
+ },
require_root: true,
}
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index fc2d8a1..4b81c2c 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -105,7 +105,9 @@
defaults: ["liblp_test_defaults"],
test_suites: ["vts"],
auto_gen_config: true,
- test_min_api_level: 29,
+ test_options: {
+ min_shipping_api_level: 29,
+ },
require_root: true,
}
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index df00f45..5ab2ce2 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -251,7 +251,9 @@
"vts",
"device-tests"
],
- test_min_api_level: 29,
+ test_options: {
+ min_shipping_api_level: 29,
+ },
auto_gen_config: true,
require_root: true,
}
@@ -407,7 +409,9 @@
test_suites: [
"device-tests"
],
- test_min_api_level: 30,
+ test_options: {
+ min_shipping_api_level: 30,
+ },
auto_gen_config: true,
require_root: false,
host_supported: true,
diff --git a/fs_mgr/libsnapshot/cow_api_test.cpp b/fs_mgr/libsnapshot/cow_api_test.cpp
index 6066309..ba4044f 100644
--- a/fs_mgr/libsnapshot/cow_api_test.cpp
+++ b/fs_mgr/libsnapshot/cow_api_test.cpp
@@ -1171,18 +1171,18 @@
ASSERT_TRUE(writer.Initialize(cow_->fd));
ASSERT_TRUE(writer.AddSequenceData(6, sequence));
- ASSERT_TRUE(writer.AddCopy(6, 3));
+ ASSERT_TRUE(writer.AddCopy(6, 13));
ASSERT_TRUE(writer.AddZeroBlocks(12, 1));
ASSERT_TRUE(writer.AddZeroBlocks(8, 1));
ASSERT_TRUE(writer.AddZeroBlocks(11, 1));
- ASSERT_TRUE(writer.AddCopy(3, 5));
- ASSERT_TRUE(writer.AddCopy(2, 1));
+ ASSERT_TRUE(writer.AddCopy(3, 15));
+ ASSERT_TRUE(writer.AddCopy(2, 11));
ASSERT_TRUE(writer.AddZeroBlocks(4, 1));
ASSERT_TRUE(writer.AddZeroBlocks(9, 1));
- ASSERT_TRUE(writer.AddCopy(5, 6));
+ ASSERT_TRUE(writer.AddCopy(5, 16));
ASSERT_TRUE(writer.AddZeroBlocks(1, 1));
- ASSERT_TRUE(writer.AddCopy(10, 2));
- ASSERT_TRUE(writer.AddCopy(7, 4));
+ ASSERT_TRUE(writer.AddCopy(10, 12));
+ ASSERT_TRUE(writer.AddCopy(7, 14));
ASSERT_TRUE(writer.Finalize());
// New block in cow order is 6, 12, 8, 11, 3, 2, 4, 9, 5, 1, 10, 7
@@ -1219,12 +1219,12 @@
ASSERT_TRUE(writer.Initialize(cow_->fd));
- ASSERT_TRUE(writer.AddCopy(2, 1));
- ASSERT_TRUE(writer.AddCopy(10, 2));
- ASSERT_TRUE(writer.AddCopy(6, 3));
- ASSERT_TRUE(writer.AddCopy(7, 4));
- ASSERT_TRUE(writer.AddCopy(3, 5));
- ASSERT_TRUE(writer.AddCopy(5, 6));
+ ASSERT_TRUE(writer.AddCopy(2, 11));
+ ASSERT_TRUE(writer.AddCopy(10, 12));
+ ASSERT_TRUE(writer.AddCopy(6, 13));
+ ASSERT_TRUE(writer.AddCopy(7, 14));
+ ASSERT_TRUE(writer.AddCopy(3, 15));
+ ASSERT_TRUE(writer.AddCopy(5, 16));
ASSERT_TRUE(writer.AddZeroBlocks(12, 1));
ASSERT_TRUE(writer.AddZeroBlocks(8, 1));
ASSERT_TRUE(writer.AddZeroBlocks(11, 1));
@@ -1260,6 +1260,39 @@
ASSERT_TRUE(iter->Done());
}
+TEST_F(CowTest, InvalidMergeOrderTest) {
+ CowOptions options;
+ options.cluster_ops = 5;
+ options.num_merge_ops = 1;
+ std::string data = "This is some data, believe it";
+ data.resize(options.block_size, '\0');
+ auto writer = std::make_unique<CowWriter>(options);
+ CowReader reader;
+
+ ASSERT_TRUE(writer->Initialize(cow_->fd));
+
+ ASSERT_TRUE(writer->AddCopy(3, 2));
+ ASSERT_TRUE(writer->AddCopy(2, 1));
+ ASSERT_TRUE(writer->AddLabel(1));
+ ASSERT_TRUE(writer->Finalize());
+ ASSERT_TRUE(reader.Parse(cow_->fd));
+ ASSERT_TRUE(reader.VerifyMergeOps());
+
+ ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 1));
+ ASSERT_TRUE(writer->AddCopy(4, 2));
+ ASSERT_TRUE(writer->Finalize());
+ ASSERT_TRUE(reader.Parse(cow_->fd));
+ ASSERT_FALSE(reader.VerifyMergeOps());
+
+ writer = std::make_unique<CowWriter>(options);
+ ASSERT_TRUE(writer->Initialize(cow_->fd));
+ ASSERT_TRUE(writer->AddCopy(2, 1));
+ ASSERT_TRUE(writer->AddXorBlocks(3, &data, data.size(), 1, 1));
+ ASSERT_TRUE(writer->Finalize());
+ ASSERT_TRUE(reader.Parse(cow_->fd));
+ ASSERT_FALSE(reader.VerifyMergeOps());
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/cow_format.cpp b/fs_mgr/libsnapshot/cow_format.cpp
index 8e6bec7..94c4109 100644
--- a/fs_mgr/libsnapshot/cow_format.cpp
+++ b/fs_mgr/libsnapshot/cow_format.cpp
@@ -56,7 +56,10 @@
os << (int)op.compression << "?, ";
os << "data_length:" << op.data_length << ",\t";
os << "new_block:" << op.new_block << ",\t";
- os << "source:" << op.source << ")";
+ os << "source:" << op.source;
+ if (op.type == kCowXorOp)
+ os << " (block:" << op.source / BLOCK_SZ << " offset:" << op.source % BLOCK_SZ << ")";
+ os << ")";
return os;
}
diff --git a/fs_mgr/libsnapshot/cow_reader.cpp b/fs_mgr/libsnapshot/cow_reader.cpp
index 773d978..5306b28 100644
--- a/fs_mgr/libsnapshot/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/cow_reader.cpp
@@ -58,6 +58,7 @@
cow->last_label_ = last_label_;
cow->ops_ = ops_;
cow->merge_op_blocks_ = merge_op_blocks_;
+ cow->merge_op_start_ = merge_op_start_;
cow->block_map_ = block_map_;
cow->num_total_data_ops_ = num_total_data_ops_;
cow->num_ordered_ops_to_merge_ = num_ordered_ops_to_merge_;
@@ -230,7 +231,7 @@
memcpy(&footer_->op, ¤t_op, sizeof(footer->op));
off_t offs = lseek(fd_.get(), pos, SEEK_SET);
if (offs < 0 || pos != static_cast<uint64_t>(offs)) {
- PLOG(ERROR) << "lseek next op failed";
+ PLOG(ERROR) << "lseek next op failed " << offs;
return false;
}
if (!android::base::ReadFully(fd_, &footer->data, sizeof(footer->data))) {
@@ -250,7 +251,7 @@
// Position for next cluster read
off_t offs = lseek(fd_.get(), pos, SEEK_SET);
if (offs < 0 || pos != static_cast<uint64_t>(offs)) {
- PLOG(ERROR) << "lseek next op failed";
+ PLOG(ERROR) << "lseek next op failed " << offs;
return false;
}
ops_buffer->resize(current_op_num);
@@ -468,8 +469,7 @@
num_total_data_ops_ = merge_op_blocks->size();
if (header_.num_merge_ops > 0) {
- merge_op_blocks->erase(merge_op_blocks->begin(),
- merge_op_blocks->begin() + header_.num_merge_ops);
+ merge_op_start_ = header_.num_merge_ops;
}
block_map_ = block_map;
@@ -477,6 +477,44 @@
return true;
}
+bool CowReader::VerifyMergeOps() {
+ auto itr = GetMergeOpIter(true);
+ std::unordered_map<uint64_t, CowOperation> overwritten_blocks;
+ while (!itr->Done()) {
+ CowOperation op = itr->Get();
+ uint64_t block;
+ bool offset;
+ if (op.type == kCowCopyOp) {
+ block = op.source;
+ offset = false;
+ } else if (op.type == kCowXorOp) {
+ block = op.source / BLOCK_SZ;
+ offset = (op.source % BLOCK_SZ) != 0;
+ } else {
+ itr->Next();
+ continue;
+ }
+
+ CowOperation* overwrite = nullptr;
+ if (overwritten_blocks.count(block)) {
+ overwrite = &overwritten_blocks[block];
+ LOG(ERROR) << "Invalid Sequence! Block needed for op:\n"
+ << op << "\noverwritten by previously merged op:\n"
+ << *overwrite;
+ }
+ if (offset && overwritten_blocks.count(block + 1)) {
+ overwrite = &overwritten_blocks[block + 1];
+ LOG(ERROR) << "Invalid Sequence! Block needed for op:\n"
+ << op << "\noverwritten by previously merged op:\n"
+ << *overwrite;
+ }
+ if (overwrite != nullptr) return false;
+ overwritten_blocks[op.new_block] = op;
+ itr->Next();
+ }
+ return true;
+}
+
bool CowReader::GetHeader(CowHeader* header) {
*header = header_;
return true;
@@ -530,7 +568,8 @@
public:
explicit CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
std::shared_ptr<std::vector<uint32_t>> merge_op_blocks,
- std::shared_ptr<std::unordered_map<uint32_t, int>> map);
+ std::shared_ptr<std::unordered_map<uint32_t, int>> map,
+ uint64_t start);
bool Done() override;
const CowOperation& Get() override;
@@ -541,20 +580,67 @@
std::shared_ptr<std::vector<uint32_t>> merge_op_blocks_;
std::shared_ptr<std::unordered_map<uint32_t, int>> map_;
std::vector<uint32_t>::reverse_iterator block_riter_;
+ uint64_t start_;
};
-CowRevMergeOpIter::CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
- std::shared_ptr<std::vector<uint32_t>> merge_op_blocks,
- std::shared_ptr<std::unordered_map<uint32_t, int>> map) {
+class CowMergeOpIter final : public ICowOpIter {
+ public:
+ explicit CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
+ std::shared_ptr<std::vector<uint32_t>> merge_op_blocks,
+ std::shared_ptr<std::unordered_map<uint32_t, int>> map, uint64_t start);
+
+ bool Done() override;
+ const CowOperation& Get() override;
+ void Next() override;
+
+ private:
+ std::shared_ptr<std::vector<CowOperation>> ops_;
+ std::shared_ptr<std::vector<uint32_t>> merge_op_blocks_;
+ std::shared_ptr<std::unordered_map<uint32_t, int>> map_;
+ std::vector<uint32_t>::iterator block_iter_;
+ uint64_t start_;
+};
+
+CowMergeOpIter::CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
+ std::shared_ptr<std::vector<uint32_t>> merge_op_blocks,
+ std::shared_ptr<std::unordered_map<uint32_t, int>> map,
+ uint64_t start) {
ops_ = ops;
merge_op_blocks_ = merge_op_blocks;
map_ = map;
+ start_ = start;
+
+ block_iter_ = merge_op_blocks->begin() + start;
+}
+
+bool CowMergeOpIter::Done() {
+ return block_iter_ == merge_op_blocks_->end();
+}
+
+void CowMergeOpIter::Next() {
+ CHECK(!Done());
+ block_iter_++;
+}
+
+const CowOperation& CowMergeOpIter::Get() {
+ CHECK(!Done());
+ return ops_->data()[map_->at(*block_iter_)];
+}
+
+CowRevMergeOpIter::CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
+ std::shared_ptr<std::vector<uint32_t>> merge_op_blocks,
+ std::shared_ptr<std::unordered_map<uint32_t, int>> map,
+ uint64_t start) {
+ ops_ = ops;
+ merge_op_blocks_ = merge_op_blocks;
+ map_ = map;
+ start_ = start;
block_riter_ = merge_op_blocks->rbegin();
}
bool CowRevMergeOpIter::Done() {
- return block_riter_ == merge_op_blocks_->rend();
+ return block_riter_ == merge_op_blocks_->rend() - start_;
}
void CowRevMergeOpIter::Next() {
@@ -571,8 +657,14 @@
return std::make_unique<CowOpIter>(ops_);
}
-std::unique_ptr<ICowOpIter> CowReader::GetRevMergeOpIter() {
- return std::make_unique<CowRevMergeOpIter>(ops_, merge_op_blocks_, block_map_);
+std::unique_ptr<ICowOpIter> CowReader::GetRevMergeOpIter(bool ignore_progress) {
+ return std::make_unique<CowRevMergeOpIter>(ops_, merge_op_blocks_, block_map_,
+ ignore_progress ? 0 : merge_op_start_);
+}
+
+std::unique_ptr<ICowOpIter> CowReader::GetMergeOpIter(bool ignore_progress) {
+ return std::make_unique<CowMergeOpIter>(ops_, merge_op_blocks_, block_map_,
+ ignore_progress ? 0 : merge_op_start_);
}
bool CowReader::GetRawBytes(uint64_t offset, void* buffer, size_t len, size_t* read) {
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index 0786e82..143f73c 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -68,6 +68,7 @@
// Return the file footer.
virtual bool GetFooter(CowFooter* footer) = 0;
+ virtual bool VerifyMergeOps() = 0;
// Return the last valid label
virtual bool GetLastLabel(uint64_t* label) = 0;
@@ -75,8 +76,11 @@
// Return an iterator for retrieving CowOperation entries.
virtual std::unique_ptr<ICowOpIter> GetOpIter() = 0;
+ // Return an iterator for retrieving CowOperation entries in reverse merge order
+ virtual std::unique_ptr<ICowOpIter> GetRevMergeOpIter(bool ignore_progress) = 0;
+
// Return an iterator for retrieving CowOperation entries in merge order
- virtual std::unique_ptr<ICowOpIter> GetRevMergeOpIter() = 0;
+ virtual std::unique_ptr<ICowOpIter> GetMergeOpIter(bool ignore_progress) = 0;
// Get decoded bytes from the data section, handling any decompression.
// All retrieved data is passed to the sink.
@@ -98,7 +102,7 @@
virtual void Next() = 0;
};
-class CowReader : public ICowReader {
+class CowReader final : public ICowReader {
public:
CowReader();
~CowReader() { owned_fd_ = {}; }
@@ -109,6 +113,7 @@
bool Parse(android::base::borrowed_fd fd, std::optional<uint64_t> label = {});
bool InitForMerge(android::base::unique_fd&& fd);
+ bool VerifyMergeOps() override;
bool GetHeader(CowHeader* header) override;
bool GetFooter(CowFooter* footer) override;
@@ -120,7 +125,8 @@
// whose lifetime depends on the CowOpIter object; the return
// value of these will never be null.
std::unique_ptr<ICowOpIter> GetOpIter() override;
- std::unique_ptr<ICowOpIter> GetRevMergeOpIter() override;
+ std::unique_ptr<ICowOpIter> GetRevMergeOpIter(bool ignore_progress = false) override;
+ std::unique_ptr<ICowOpIter> GetMergeOpIter(bool ignore_progress = false) override;
bool ReadData(const CowOperation& op, IByteSink* sink) override;
@@ -152,6 +158,7 @@
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_;
std::shared_ptr<std::unordered_map<uint32_t, int>> block_map_;
uint64_t num_total_data_ops_;
uint64_t num_ordered_ops_to_merge_;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
index 3655c01..b0be5a5 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
@@ -44,6 +44,7 @@
// Open the writer in write mode (no append).
MOCK_METHOD(bool, Initialize, (), (override));
+ MOCK_METHOD(bool, VerifyMergeOps, (), (override, const, noexcept));
// Open the writer in append mode, with the last label to resume
// from. See CowWriter::InitializeAppend.
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
index b09e1ae..545f117 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
@@ -47,6 +47,7 @@
virtual bool InitializeAppend(uint64_t label) = 0;
virtual std::unique_ptr<FileDescriptor> OpenReader() = 0;
+ virtual bool VerifyMergeOps() const noexcept = 0;
protected:
android::base::borrowed_fd GetSourceFd();
@@ -58,7 +59,7 @@
};
// Send writes to a COW or a raw device directly, based on a threshold.
-class CompressedSnapshotWriter : public ISnapshotWriter {
+class CompressedSnapshotWriter final : public ISnapshotWriter {
public:
CompressedSnapshotWriter(const CowOptions& options);
@@ -70,6 +71,7 @@
bool Finalize() override;
uint64_t GetCowSize() override;
std::unique_ptr<FileDescriptor> OpenReader() override;
+ bool VerifyMergeOps() const noexcept;
protected:
bool EmitCopy(uint64_t new_block, uint64_t old_block) override;
@@ -81,13 +83,14 @@
bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
private:
+ std::unique_ptr<CowReader> OpenCowReader() const;
android::base::unique_fd cow_device_;
std::unique_ptr<CowWriter> cow_;
};
// Write directly to a dm-snapshot device.
-class OnlineKernelSnapshotWriter : public ISnapshotWriter {
+class OnlineKernelSnapshotWriter final : public ISnapshotWriter {
public:
OnlineKernelSnapshotWriter(const CowOptions& options);
@@ -101,6 +104,10 @@
uint64_t GetCowSize() override { return cow_size_; }
std::unique_ptr<FileDescriptor> OpenReader() override;
+ // Online kernel snapshot writer doesn't care about merge sequences.
+ // So ignore.
+ bool VerifyMergeOps() const noexcept override { return true; }
+
protected:
bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
diff --git a/fs_mgr/libsnapshot/inspect_cow.cpp b/fs_mgr/libsnapshot/inspect_cow.cpp
index 3c0ba16..548ba00 100644
--- a/fs_mgr/libsnapshot/inspect_cow.cpp
+++ b/fs_mgr/libsnapshot/inspect_cow.cpp
@@ -44,10 +44,13 @@
LOG(ERROR) << "\t -b Show data for failed decompress";
LOG(ERROR) << "\t -l Show ops";
LOG(ERROR) << "\t -m Show ops in reverse merge order";
- LOG(ERROR) << "\t -o Shows sequence op block order\n";
+ LOG(ERROR) << "\t -n Show ops in merge order";
+ LOG(ERROR) << "\t -a Include merged ops in any merge order listing";
+ LOG(ERROR) << "\t -o Shows sequence op block order";
+ LOG(ERROR) << "\t -v Verifies merge order has no conflicts\n";
}
-enum OpIter { Normal, RevMerge };
+enum OpIter { Normal, RevMerge, Merge };
struct Options {
bool silent;
@@ -55,7 +58,9 @@
bool show_ops;
bool show_bad;
bool show_seq;
+ bool verify_sequence;
OpIter iter_type;
+ bool include_merged;
};
// Sink that always appends to the end of a string.
@@ -132,11 +137,21 @@
}
}
+ if (opt.verify_sequence) {
+ if (reader.VerifyMergeOps()) {
+ std::cout << "\nMerge sequence is consistent.\n";
+ } else {
+ std::cout << "\nMerge sequence is inconsistent!\n";
+ }
+ }
+
std::unique_ptr<ICowOpIter> iter;
if (opt.iter_type == Normal) {
iter = reader.GetOpIter();
} else if (opt.iter_type == RevMerge) {
- iter = reader.GetRevMergeOpIter();
+ iter = reader.GetRevMergeOpIter(opt.include_merged);
+ } else if (opt.iter_type == Merge) {
+ iter = reader.GetMergeOpIter(opt.include_merged);
}
StringSink sink;
bool success = true;
@@ -188,7 +203,9 @@
opt.decompress = false;
opt.show_bad = false;
opt.iter_type = android::snapshot::Normal;
- while ((ch = getopt(argc, argv, "sdbmol")) != -1) {
+ opt.verify_sequence = false;
+ opt.include_merged = false;
+ while ((ch = getopt(argc, argv, "sdbmnolva")) != -1) {
switch (ch) {
case 's':
opt.silent = true;
@@ -202,12 +219,21 @@
case 'm':
opt.iter_type = android::snapshot::RevMerge;
break;
+ case 'n':
+ opt.iter_type = android::snapshot::Merge;
+ break;
case 'o':
opt.show_seq = true;
break;
case 'l':
opt.show_ops = true;
break;
+ case 'v':
+ opt.verify_sequence = true;
+ break;
+ case 'a':
+ opt.include_merged = true;
+ break;
default:
android::snapshot::usage();
}
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp b/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp
index 0096f85..acee2f4 100644
--- a/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp
+++ b/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp
@@ -139,7 +139,7 @@
auto& dm = DeviceMapper::Instance();
std::vector<DeviceMapper::TargetInfo> table;
if (!dm.GetTableInfo(dev_name, &table)) {
- PCHECK(errno == ENODEV);
+ PCHECK(errno == ENODEV || errno == ENXIO);
return {};
}
return table;
diff --git a/fs_mgr/libsnapshot/snapshot_writer.cpp b/fs_mgr/libsnapshot/snapshot_writer.cpp
index 3eda08e..48b7d80 100644
--- a/fs_mgr/libsnapshot/snapshot_writer.cpp
+++ b/fs_mgr/libsnapshot/snapshot_writer.cpp
@@ -67,7 +67,7 @@
return cow_->GetCowSize();
}
-std::unique_ptr<FileDescriptor> CompressedSnapshotWriter::OpenReader() {
+std::unique_ptr<CowReader> CompressedSnapshotWriter::OpenCowReader() const {
unique_fd cow_fd(dup(cow_device_.get()));
if (cow_fd < 0) {
PLOG(ERROR) << "dup COW device";
@@ -79,6 +79,20 @@
LOG(ERROR) << "Unable to read COW";
return nullptr;
}
+ return cow;
+}
+
+bool CompressedSnapshotWriter::VerifyMergeOps() const noexcept {
+ auto cow_reader = OpenCowReader();
+ if (cow_reader == nullptr) {
+ LOG(ERROR) << "Couldn't open CowReader";
+ return false;
+ }
+ return cow_reader->VerifyMergeOps();
+}
+
+std::unique_ptr<FileDescriptor> CompressedSnapshotWriter::OpenReader() {
+ auto cow = OpenCowReader();
auto reader = std::make_unique<CompressedSnapshotReader>();
if (!reader->SetCow(std::move(cow))) {
diff --git a/fs_mgr/libsnapshot/snapuserd/Android.bp b/fs_mgr/libsnapshot/snapuserd/Android.bp
index 47268d4..6bd5323 100644
--- a/fs_mgr/libsnapshot/snapuserd/Android.bp
+++ b/fs_mgr/libsnapshot/snapuserd/Android.bp
@@ -128,7 +128,9 @@
"libstorage_literals_headers",
"libfiemap_headers",
],
- test_min_api_level: 30,
+ test_options: {
+ min_shipping_api_level: 30,
+ },
auto_gen_config: true,
require_root: false,
}
diff --git a/init/Android.bp b/init/Android.bp
index a0fe017..9b02c38 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -321,7 +321,6 @@
"first_stage_mount.cpp",
"reboot_utils.cpp",
"selabel.cpp",
- "selinux.cpp",
"service_utils.cpp",
"snapuserd_transition.cpp",
"switch_root.cpp",
@@ -336,23 +335,16 @@
"libfec",
"libfec_rs",
"libsquashfs_utils",
- "liblogwrap",
- "libext4_utils",
"libcrypto_utils",
- "libsparse",
"libavb",
- "libkeyutils",
"liblp",
"libcutils",
"libbase",
"liblog",
"libcrypto_static",
- "libdl",
- "libz",
"libselinux",
"libcap",
"libgsi",
- "libcom.android.sysprop.apex",
"liblzma",
"libunwindstack_no_dex",
"libbacktrace_no_dex",
@@ -463,6 +455,7 @@
"persistent_properties_test.cpp",
"property_service_test.cpp",
"property_type_test.cpp",
+ "reboot_test.cpp",
"rlimit_parser_test.cpp",
"service_test.cpp",
"subcontext_test.cpp",
diff --git a/init/init.cpp b/init/init.cpp
index bde8e04..e3596cb 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -27,6 +27,7 @@
#include <sys/mount.h>
#include <sys/signalfd.h>
#include <sys/types.h>
+#include <sys/utsname.h>
#include <unistd.h>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
@@ -554,6 +555,19 @@
}
}
+/// Set ro.kernel.version property to contain the major.minor pair as returned
+/// by uname(2).
+static void SetKernelVersion() {
+ struct utsname uts;
+ unsigned int major, minor;
+
+ if ((uname(&uts) != 0) || (sscanf(uts.release, "%u.%u", &major, &minor) != 2)) {
+ LOG(ERROR) << "Could not parse the kernel version from uname";
+ return;
+ }
+ SetProperty("ro.kernel.version", android::base::StringPrintf("%u.%u", major, minor));
+}
+
static void HandleSigtermSignal(const signalfd_siginfo& siginfo) {
if (siginfo.ssi_pid != 0) {
// Drop any userspace SIGTERM requests.
@@ -858,6 +872,7 @@
export_oem_lock_status();
MountHandler mount_handler(&epoll);
SetUsbController();
+ SetKernelVersion();
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
Action::set_function_map(&function_map);
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index 593e5ae..bce1cc3 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -82,11 +82,6 @@
return updatable;
}
-static bool IsMicrodroid() {
- static bool is_microdroid = android::base::GetProperty("ro.hardware", "") == "microdroid";
- return is_microdroid;
-}
-
// In case we have two sets of APEXes (non-updatable, updatable), we need two separate mount
// namespaces.
static bool NeedsTwoMountNamespaces() {
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 2d67bf5..84ed58e 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -1017,6 +1017,31 @@
}
}
+static void property_initialize_ro_vendor_api_level() {
+ // ro.vendor.api_level shows the api_level that the vendor images (vendor, odm, ...) are
+ // required to support.
+ constexpr auto VENDOR_API_LEVEL_PROP = "ro.vendor.api_level";
+ // Candidate api levels. The order of the properties must be kept.
+ const char* VENDOR_API_LEVEL_PROPS[] = {
+ "ro.board.api_level", "ro.board.first_api_level", "ro.product.first_api_level",
+ "ro.vndk.version", "ro.vendor.build.version.sdk", "ro.build.version.sdk"};
+
+ for (const auto& api_level_prop : VENDOR_API_LEVEL_PROPS) {
+ int api_level = android::base::GetIntProperty(api_level_prop, 0);
+ if (api_level != 0) {
+ std::string error;
+ uint32_t res = PropertySet(VENDOR_API_LEVEL_PROP, std::to_string(api_level), &error);
+ if (res != PROP_SUCCESS) {
+ LOG(ERROR) << "Failed to set " << VENDOR_API_LEVEL_PROP << " with " << api_level
+ << ": " << error;
+ }
+ return;
+ }
+ }
+ // If no api integers are found from the vendor api level properties, ro.vendor.api_level
+ // will not be set.
+}
+
void PropertyLoadBootDefaults() {
// We read the properties and their values into a map, in order to always allow properties
// loaded in the later property files to override the properties in loaded in the earlier
@@ -1102,6 +1127,7 @@
property_derive_build_fingerprint();
property_derive_legacy_build_fingerprint();
property_initialize_ro_cpu_abilist();
+ property_initialize_ro_vendor_api_level();
update_sys_usb_config();
}
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 1681627..6aa9912 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -550,8 +550,8 @@
// Like StopServices, but also logs all the services that failed to stop after the provided timeout.
// Returns number of violators.
-static int StopServicesAndLogViolations(const std::set<std::string>& services,
- std::chrono::milliseconds timeout, bool terminate) {
+int StopServicesAndLogViolations(const std::set<std::string>& services,
+ std::chrono::milliseconds timeout, bool terminate) {
StopServices(services, timeout, terminate);
int still_running = 0;
for (const auto& s : ServiceList::GetInstance()) {
diff --git a/init/reboot.h b/init/reboot.h
index 81c3edc..551a114 100644
--- a/init/reboot.h
+++ b/init/reboot.h
@@ -17,11 +17,17 @@
#ifndef _INIT_REBOOT_H
#define _INIT_REBOOT_H
+#include <chrono>
+#include <set>
#include <string>
namespace android {
namespace init {
+// Like StopServices, but also logs all the services that failed to stop after the provided timeout.
+// Returns number of violators.
+int StopServicesAndLogViolations(const std::set<std::string>& services,
+ std::chrono::milliseconds timeout, bool terminate);
// Parses and handles a setprop sys.powerctl message.
void HandlePowerctlMessage(const std::string& command);
diff --git a/init/reboot_test.cpp b/init/reboot_test.cpp
new file mode 100644
index 0000000..b3d038d
--- /dev/null
+++ b/init/reboot_test.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "reboot.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <memory>
+#include <string_view>
+
+#include <android-base/file.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <gtest/gtest.h>
+#include <selinux/selinux.h>
+
+#include "builtin_arguments.h"
+#include "builtins.h"
+#include "parser.h"
+#include "service_list.h"
+#include "service_parser.h"
+#include "subcontext.h"
+#include "util.h"
+
+using namespace std::literals;
+
+using android::base::GetProperty;
+using android::base::Join;
+using android::base::SetProperty;
+using android::base::Split;
+using android::base::StringReplace;
+using android::base::WaitForProperty;
+using android::base::WriteStringToFd;
+
+namespace android {
+namespace init {
+
+class RebootTest : public ::testing::Test {
+ public:
+ RebootTest() {
+ std::vector<std::string> names = GetServiceNames();
+ if (!names.empty()) {
+ ADD_FAILURE() << "Expected empty ServiceList but found: [" << Join(names, ',') << "]";
+ }
+ }
+
+ ~RebootTest() {
+ std::vector<std::string> names = GetServiceNames();
+ for (const auto& name : names) {
+ auto s = ServiceList::GetInstance().FindService(name);
+ auto pid = s->pid();
+ ServiceList::GetInstance().RemoveService(*s);
+ if (pid > 0) {
+ kill(pid, SIGTERM);
+ kill(pid, SIGKILL);
+ }
+ }
+ }
+
+ private:
+ std::vector<std::string> GetServiceNames() const {
+ std::vector<std::string> names;
+ for (const auto& s : ServiceList::GetInstance()) {
+ names.push_back(s->name());
+ }
+ return names;
+ }
+};
+
+std::string GetSecurityContext() {
+ char* ctx;
+ if (getcon(&ctx) == -1) {
+ ADD_FAILURE() << "Failed to call getcon : " << strerror(errno);
+ }
+ std::string result = std::string(ctx);
+ freecon(ctx);
+ return result;
+}
+
+void AddTestService(const std::string& name) {
+ static constexpr std::string_view kScriptTemplate = R"init(
+service $name /system/bin/yes
+ user shell
+ group shell
+ seclabel $selabel
+)init";
+
+ std::string script = StringReplace(StringReplace(kScriptTemplate, "$name", name, false),
+ "$selabel", GetSecurityContext(), false);
+ ServiceList& service_list = ServiceList::GetInstance();
+ Parser parser;
+ parser.AddSectionParser("service",
+ std::make_unique<ServiceParser>(&service_list, nullptr, std::nullopt));
+
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ ASSERT_TRUE(WriteStringToFd(script, tf.fd));
+ ASSERT_TRUE(parser.ParseConfig(tf.path));
+}
+
+TEST_F(RebootTest, StopServicesSIGTERM) {
+ if (getuid() != 0) {
+ GTEST_SKIP() << "Skipping test, must be run as root.";
+ return;
+ }
+
+ AddTestService("A");
+ AddTestService("B");
+
+ auto service_a = ServiceList::GetInstance().FindService("A");
+ ASSERT_NE(nullptr, service_a);
+ auto service_b = ServiceList::GetInstance().FindService("B");
+ ASSERT_NE(nullptr, service_b);
+
+ ASSERT_RESULT_OK(service_a->Start());
+ ASSERT_TRUE(service_a->IsRunning());
+ ASSERT_RESULT_OK(service_b->Start());
+ ASSERT_TRUE(service_b->IsRunning());
+
+ std::unique_ptr<Service> oneshot_service;
+ {
+ auto result = Service::MakeTemporaryOneshotService(
+ {"exec", GetSecurityContext(), "--", "/system/bin/yes"});
+ ASSERT_RESULT_OK(result);
+ oneshot_service = std::move(*result);
+ }
+ std::string oneshot_service_name = oneshot_service->name();
+ oneshot_service->Start();
+ ASSERT_TRUE(oneshot_service->IsRunning());
+ ServiceList::GetInstance().AddService(std::move(oneshot_service));
+
+ EXPECT_EQ(0, StopServicesAndLogViolations({"A", "B", oneshot_service_name}, 10s,
+ /* terminate= */ true));
+ EXPECT_FALSE(service_a->IsRunning());
+ EXPECT_FALSE(service_b->IsRunning());
+ // Oneshot services are deleted from the ServiceList after they are destroyed.
+ auto oneshot_service_after_stop = ServiceList::GetInstance().FindService(oneshot_service_name);
+ EXPECT_EQ(nullptr, oneshot_service_after_stop);
+}
+
+TEST_F(RebootTest, StopServicesSIGKILL) {
+ if (getuid() != 0) {
+ GTEST_SKIP() << "Skipping test, must be run as root.";
+ return;
+ }
+
+ AddTestService("A");
+ AddTestService("B");
+
+ auto service_a = ServiceList::GetInstance().FindService("A");
+ ASSERT_NE(nullptr, service_a);
+ auto service_b = ServiceList::GetInstance().FindService("B");
+ ASSERT_NE(nullptr, service_b);
+
+ ASSERT_RESULT_OK(service_a->Start());
+ ASSERT_TRUE(service_a->IsRunning());
+ ASSERT_RESULT_OK(service_b->Start());
+ ASSERT_TRUE(service_b->IsRunning());
+
+ std::unique_ptr<Service> oneshot_service;
+ {
+ auto result = Service::MakeTemporaryOneshotService(
+ {"exec", GetSecurityContext(), "--", "/system/bin/yes"});
+ ASSERT_RESULT_OK(result);
+ oneshot_service = std::move(*result);
+ }
+ std::string oneshot_service_name = oneshot_service->name();
+ oneshot_service->Start();
+ ASSERT_TRUE(oneshot_service->IsRunning());
+ ServiceList::GetInstance().AddService(std::move(oneshot_service));
+
+ EXPECT_EQ(0, StopServicesAndLogViolations({"A", "B", oneshot_service_name}, 10s,
+ /* terminate= */ false));
+ EXPECT_FALSE(service_a->IsRunning());
+ EXPECT_FALSE(service_b->IsRunning());
+ // Oneshot services are deleted from the ServiceList after they are destroyed.
+ auto oneshot_service_after_stop = ServiceList::GetInstance().FindService(oneshot_service_name);
+ EXPECT_EQ(nullptr, oneshot_service_after_stop);
+}
+
+} // namespace init
+} // namespace android
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index f1fbffe..6eaa80f 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -44,6 +44,7 @@
#endif
using android::base::GetExecutablePath;
+using android::base::GetProperty;
using android::base::Join;
using android::base::Socketpair;
using android::base::Split;
@@ -337,6 +338,11 @@
}
void InitializeSubcontext() {
+ if (IsMicrodroid()) {
+ LOG(INFO) << "Not using subcontext for microdroid";
+ return;
+ }
+
if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_P__) {
subcontext.reset(
new Subcontext(std::vector<std::string>{"/vendor", "/odm"}, kVendorContext));
@@ -351,6 +357,9 @@
}
bool SubcontextChildReap(pid_t pid) {
+ if (!subcontext) {
+ return false;
+ }
if (subcontext->pid() == pid) {
if (!subcontext_terminated_by_shutdown) {
subcontext->Restart();
diff --git a/init/util.cpp b/init/util.cpp
index 9f7bfdb..d1e518b 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -757,5 +757,10 @@
is_default_mount_namespace_ready = true;
}
+bool IsMicrodroid() {
+ static bool is_microdroid = android::base::GetProperty("ro.hardware", "") == "microdroid";
+ return is_microdroid;
+}
+
} // namespace init
} // namespace android
diff --git a/init/util.h b/init/util.h
index daba852..bf53675 100644
--- a/init/util.h
+++ b/init/util.h
@@ -103,5 +103,7 @@
bool IsDefaultMountNamespaceReady();
void SetDefaultMountNamespaceReady();
+
+bool IsMicrodroid();
} // namespace init
} // namespace android
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 08ef6e3..3831693 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -591,7 +591,20 @@
# Load trusted keys from dm-verity protected partitions
exec -- /system/bin/fsverity_init --load-verified-keys
-on late-fs && property:ro.product.cpu.abilist64=*
+# Only enable the bootreceiver tracing instance for kernels 5.10 and above.
+on late-fs && property:ro.kernel.version=4.9
+ setprop bootreceiver.enable 0
+on late-fs && property:ro.kernel.version=4.14
+ setprop bootreceiver.enable 0
+on late-fs && property:ro.kernel.version=4.19
+ setprop bootreceiver.enable 0
+on late-fs && property:ro.kernel.version=5.4
+ setprop bootreceiver.enable 0
+on late-fs
+ # Bootreceiver tracing instance is enabled by default.
+ setprop bootreceiver.enable ${bootreceiver.enable:-1}
+
+on property:ro.product.cpu.abilist64=* && property:bootreceiver.enable=1
# Set up a tracing instance for system_server to monitor error_report_end events.
# These are sent by kernel tools like KASAN and KFENCE when a memory corruption
# is detected. This is only needed for 64-bit systems.
diff --git a/storaged/Android.bp b/storaged/Android.bp
index 9d5cb48..b557dee 100644
--- a/storaged/Android.bp
+++ b/storaged/Android.bp
@@ -32,6 +32,7 @@
"libprotobuf-cpp-lite",
"libutils",
"libz",
+ "packagemanager_aidl-cpp",
],
cflags: [
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index 155363c..7bd1d10 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -120,6 +120,7 @@
],
required: [
"android.hardware.hardware_keystore.xml",
+ "RemoteProvisioner",
],
}