Merge "libutils_binder: isolate headers" into main
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 3b8866e..2d55e5a 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -461,6 +461,14 @@
{"reboot,smpl_timeout,pmic,main", 229},
{"reboot,ota,.*", 230},
{"reboot,periodic,.*", 231},
+ {"reboot,early,abl", 232},
+ {"reboot,early,bl2", 233},
+ {"reboot,longkey,pmic_cold", 234},
+ {"reboot,longkey,master_dc", 235},
+ {"reboot,ocp2,pmic,if", 236},
+ {"reboot,ocp,pmic,if", 237},
+ {"reboot,fship", 238},
+ {"reboot,ocp,.*", 239},
};
// Converts a string value representing the reason the system booted to an
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 56b90b9..ac2a20f 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -1053,8 +1053,10 @@
return false;
}
sparse_file_destroy(s);
+ buf->file_type = FB_BUFFER_SPARSE;
} else {
buf->image_size = sz;
+ buf->file_type = FB_BUFFER_FD;
}
lseek(fd.get(), 0, SEEK_SET);
@@ -1191,6 +1193,15 @@
should_flash_in_userspace(source, partition)) {
return;
}
+
+ // If the image is sparse, moving the footer will simply corrupt the sparse
+ // format, so currently we don't support moving the footer on sparse files.
+ if (buf->file_type == FB_BUFFER_SPARSE) {
+ LOG(ERROR) << "Warning: skip copying " << partition << " image avb footer due to sparse "
+ << "image.";
+ return;
+ }
+
// If overflows and negative, it should be < buf->sz.
int64_t partition_size = static_cast<int64_t>(get_partition_size(partition));
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 2c40890..6a49970 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -57,7 +57,8 @@
};
struct fastboot_buffer {
- enum fb_buffer_type type;
+ fb_buffer_type type;
+ fb_buffer_type file_type;
std::vector<SparsePtr> files;
int64_t sz;
unique_fd fd;
diff --git a/fs_mgr/fs_mgr_overlayfs_mount.cpp b/fs_mgr/fs_mgr_overlayfs_mount.cpp
index 0dadbff..ae7ed4c 100644
--- a/fs_mgr/fs_mgr_overlayfs_mount.cpp
+++ b/fs_mgr/fs_mgr_overlayfs_mount.cpp
@@ -381,54 +381,86 @@
auto retval = true;
- struct move_entry {
+ struct MoveEntry {
std::string mount_point;
std::string dir;
bool shared_flag;
};
- std::vector<move_entry> move;
+
+ std::vector<MoveEntry> moved_mounts;
auto parent_private = false;
auto parent_made_private = false;
auto dev_private = false;
auto dev_made_private = false;
- for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) {
+
+ // There could be multiple mount entries with the same mountpoint.
+ // Group these entries together with stable_sort, and keep only the last entry of a group.
+ // Only move mount the last entry in an over mount group, because the other entries are
+ // overshadowed and only the filesystem mounted with the last entry participates in file
+ // pathname resolution.
+ auto mountinfo = ReadMountinfoFromFile("/proc/self/mountinfo");
+ std::stable_sort(mountinfo.begin(), mountinfo.end(), [](const auto& lhs, const auto& rhs) {
+ return lhs.mount_point < rhs.mount_point;
+ });
+ std::reverse(mountinfo.begin(), mountinfo.end());
+ auto erase_from = std::unique(
+ mountinfo.begin(), mountinfo.end(),
+ [](const auto& lhs, const auto& rhs) { return lhs.mount_point == rhs.mount_point; });
+ mountinfo.erase(erase_from, mountinfo.end());
+ std::reverse(mountinfo.begin(), mountinfo.end());
+ // mountinfo is reversed twice, so still is in lexical sorted order.
+
+ for (const auto& entry : mountinfo) {
if ((entry.mount_point == mount_point) && !entry.shared_flag) {
parent_private = true;
}
if ((entry.mount_point == "/dev") && !entry.shared_flag) {
dev_private = true;
}
+ }
+ // Need to make the original mountpoint MS_PRIVATE, so that the overlayfs can be MS_MOVE.
+ // This could happen if its parent mount is remounted later.
+ if (!parent_private) {
+ parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false);
+ }
+
+ for (const auto& entry : mountinfo) {
+ // Find all immediate submounts.
if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) {
continue;
}
- if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) {
- return android::base::StartsWith(entry.mount_point, it.mount_point + "/");
- }) != move.end()) {
+ // Exclude duplicated or more specific entries.
+ if (std::find_if(moved_mounts.begin(), moved_mounts.end(), [&entry](const auto& it) {
+ return it.mount_point == entry.mount_point ||
+ android::base::StartsWith(entry.mount_point, it.mount_point + "/");
+ }) != moved_mounts.end()) {
continue;
}
+ // mountinfo is in lexical order, so no need to worry about |entry| being a parent mount of
+ // entries of |moved_mounts|.
// use as the bound directory in /dev.
- AutoSetFsCreateCon createcon;
- auto new_context = fs_mgr_get_context(entry.mount_point);
- if (new_context.empty() || !createcon.Set(new_context)) {
- continue;
- }
- move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX",
- entry.shared_flag};
- const auto target = mkdtemp(new_entry.dir.data());
- if (!createcon.Restore()) {
- return false;
- }
- if (!target) {
- retval = false;
- PERROR << "temporary directory for MS_BIND";
- continue;
+ MoveEntry new_entry{entry.mount_point, "/dev/TemporaryDir-XXXXXX", entry.shared_flag};
+ {
+ AutoSetFsCreateCon createcon;
+ auto new_context = fs_mgr_get_context(entry.mount_point);
+ if (new_context.empty() || !createcon.Set(new_context)) {
+ continue;
+ }
+ const auto target = mkdtemp(new_entry.dir.data());
+ if (!target) {
+ retval = false;
+ PERROR << "temporary directory for MS_MOVE";
+ continue;
+ }
+ if (!createcon.Restore()) {
+ retval = false;
+ rmdir(new_entry.dir.c_str());
+ continue;
+ }
}
- if (!parent_private && !parent_made_private) {
- parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false);
- }
if (new_entry.shared_flag) {
new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false);
}
@@ -437,9 +469,10 @@
if (new_entry.shared_flag) {
fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true);
}
+ rmdir(new_entry.dir.c_str());
continue;
}
- move.emplace_back(std::move(new_entry));
+ moved_mounts.push_back(std::move(new_entry));
}
// hijack __mount() report format to help triage
@@ -463,7 +496,7 @@
}
// Move submounts back.
- for (const auto& entry : move) {
+ for (const auto& entry : moved_mounts) {
if (!dev_private && !dev_made_private) {
dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false);
}
@@ -658,22 +691,13 @@
!fs_mgr_wants_overlayfs(&new_entry)) {
continue;
}
- auto new_mount_point = fs_mgr_mount_point(entry.mount_point);
- auto duplicate_or_more_specific = false;
- for (auto it = candidates.begin(); it != candidates.end();) {
- auto it_mount_point = fs_mgr_mount_point(it->mount_point);
- if ((it_mount_point == new_mount_point) ||
- (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) {
- duplicate_or_more_specific = true;
- break;
- }
- if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) {
- it = candidates.erase(it);
- } else {
- ++it;
- }
+ const auto new_mount_point = fs_mgr_mount_point(new_entry.mount_point);
+ if (std::find_if(candidates.begin(), candidates.end(), [&](const auto& it) {
+ return fs_mgr_mount_point(it.mount_point) == new_mount_point;
+ }) != candidates.end()) {
+ continue;
}
- if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry));
+ candidates.push_back(std::move(new_entry));
}
return candidates;
}
@@ -707,7 +731,7 @@
return false;
}
auto ret = true;
- auto scratch_can_be_mounted = true;
+ auto scratch_can_be_mounted = !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false);
for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
if (fs_mgr_is_verity_enabled(entry)) continue;
auto mount_point = fs_mgr_mount_point(entry.mount_point);
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 4b3a5d3..7ba4d2b 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -88,17 +88,6 @@
return entry.mount_point;
}
-const FstabEntry* GetWrappedEntry(const Fstab& overlayfs_candidates, const FstabEntry& entry) {
- auto mount_point = system_mount_point(entry);
- auto it = std::find_if(overlayfs_candidates.begin(), overlayfs_candidates.end(),
- [&mount_point](const auto& entry) {
- return android::base::StartsWith(mount_point,
- system_mount_point(entry) + "/");
- });
- if (it == overlayfs_candidates.end()) return nullptr;
- return &(*it);
-}
-
class MyLogger {
public:
explicit MyLogger(bool verbose) : verbose_(verbose) {}
@@ -169,15 +158,25 @@
// not checkpointing.
auto vold = GetVold();
bool checkpointing = false;
- if (!vold->isCheckpointing(&checkpointing).isOk()) {
- LOG(ERROR) << "Could not determine checkpointing status.";
- return false;
- }
- if (checkpointing) {
- LOG(ERROR) << "Cannot use remount when a checkpoint is in progress.";
- LOG(ERROR) << "To force end checkpointing, call 'vdc checkpoint commitChanges'";
- LOG(ERROR) << "Warning: this can lead to data corruption if rolled back.";
- return false;
+ bool show_help = true;
+
+ while (true) {
+ if (!vold->isCheckpointing(&checkpointing).isOk()) {
+ LOG(ERROR) << "Could not determine checkpointing status.";
+ return false;
+ }
+ if (!checkpointing) {
+ break;
+ }
+ if (show_help) {
+ show_help = false;
+ std::cerr << "WARNING: Userdata checkpoint is in progress. To force end checkpointing, "
+ "call 'vdc checkpoint commitChanges'. This can lead to data corruption if "
+ "rolled back."
+ << std::endl;
+ LOG(INFO) << "Waiting for checkpoint to complete and then continue remount.";
+ }
+ std::this_thread::sleep_for(4s);
}
return true;
}
@@ -196,9 +195,6 @@
if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) {
return candidate_entry->fs_type == entry.fs_type;
}
- if (GetWrappedEntry(candidates, entry)) {
- return false;
- }
return true;
}
@@ -252,11 +248,6 @@
}
const FstabEntry* entry = &*it;
- if (auto wrap = GetWrappedEntry(candidates, *entry); wrap != nullptr) {
- LOG(INFO) << "partition " << arg << " covered by overlayfs for " << wrap->mount_point
- << ", switching";
- entry = wrap;
- }
// If it's already remounted, include it so it gets gracefully skipped
// later on.
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index 2721937..debaf36 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -172,7 +172,7 @@
android::base::unique_fd owned_fd_;
android::base::borrowed_fd fd_;
- CowHeader header_;
+ CowHeaderV3 header_;
std::optional<CowFooter> footer_;
uint64_t fd_size_;
std::optional<uint64_t> last_label_;
@@ -188,7 +188,10 @@
uint8_t compression_type_ = kCowCompressNone;
};
-bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header);
+// Though this function takes in a CowHeaderV3, the struct could be populated as a v1/v2 CowHeader.
+// The extra fields will just be filled as 0. V3 header is strictly a superset of v1/v2 header and
+// contains all of the latter's field
+bool ReadCowHeader(android::base::borrowed_fd fd, CowHeaderV3* header);
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
index 607d610..3b84c95 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
@@ -28,12 +28,13 @@
#include <zlib.h>
#include "cow_decompress.h"
+#include "libsnapshot/cow_format.h"
#include "parser_v2.h"
namespace android {
namespace snapshot {
-bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header) {
+bool ReadCowHeader(android::base::borrowed_fd fd, CowHeaderV3* header) {
if (lseek(fd.get(), 0, SEEK_SET) < 0) {
PLOG(ERROR) << "lseek header failed";
return false;
@@ -49,9 +50,9 @@
<< "Expected: " << kCowMagicNumber;
return false;
}
- if (header->prefix.header_size > sizeof(CowHeader)) {
+ if (header->prefix.header_size > sizeof(CowHeaderV3)) {
LOG(ERROR) << "Unknown CowHeader size (got " << header->prefix.header_size
- << " bytes, expected at most " << sizeof(CowHeader) << " bytes)";
+ << " bytes, expected at most " << sizeof(CowHeaderV3) << " bytes)";
return false;
}
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
index 83b5a12..a291469 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
@@ -90,7 +90,7 @@
}
static bool ShowRawOpStream(borrowed_fd fd) {
- CowHeader header;
+ CowHeaderV3 header;
if (!ReadCowHeader(fd, &header)) {
LOG(ERROR) << "parse header failed";
return false;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
index 2373d4d..cc8dd83 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
@@ -26,7 +26,9 @@
#include <libsnapshot/cow_writer.h>
#include "cow_decompress.h"
#include "libsnapshot/cow_format.h"
+#include "writer_v2.h"
#include "writer_v3.h"
+
using android::base::unique_fd;
using testing::AssertionFailure;
using testing::AssertionResult;
@@ -49,5 +51,27 @@
std::unique_ptr<TemporaryFile> cow_;
};
+TEST_F(CowOperationV3Test, CowHeaderV2Test) {
+ CowOptions options;
+ options.cluster_ops = 5;
+ options.num_merge_ops = 1;
+ options.block_size = 4096;
+ std::string data = "This is some data, believe it";
+ data.resize(options.block_size, '\0');
+ auto writer_v2 = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer_v2->Initialize());
+ ASSERT_TRUE(writer_v2->Finalize());
+
+ CowReader reader;
+ ASSERT_TRUE(reader.Parse(cow_->fd));
+
+ const auto& header = reader.GetHeader();
+ ASSERT_EQ(header.prefix.magic, kCowMagicNumber);
+ ASSERT_EQ(header.prefix.major_version, kCowVersionMajor);
+ ASSERT_EQ(header.prefix.minor_version, kCowVersionMinor);
+ ASSERT_EQ(header.block_size, options.block_size);
+ ASSERT_EQ(header.cluster_ops, options.cluster_ops);
+}
+
} // namespace snapshot
} // namespace android
\ No newline at end of file
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
index 63bed07..83a9b1b 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
@@ -269,9 +269,11 @@
}
bool CowWriterV2::OpenForAppend(uint64_t label) {
- if (!ReadCowHeader(fd_, &header_)) {
+ CowHeaderV3 header_v3;
+ if (!ReadCowHeader(fd_, &header_v3)) {
return false;
}
+ header_ = header_v3;
CowParserV2 parser;
if (!parser.Parse(fd_, header_, {label})) {
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index f5732fc..eb4beb7 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -3658,7 +3658,7 @@
return nullptr;
}
- CowHeader header;
+ CowHeaderV3 header;
if (!ReadCowHeader(cow_fd, &header)) {
LOG(ERROR) << "OpenCompressedSnapshotWriter: read header failed";
return nullptr;
diff --git a/init/persistent_properties.cpp b/init/persistent_properties.cpp
index 8efb72c..e89244f 100644
--- a/init/persistent_properties.cpp
+++ b/init/persistent_properties.cpp
@@ -115,24 +115,6 @@
}
}
-PersistentProperties LoadPersistentPropertiesFromMemory() {
- PersistentProperties persistent_properties;
- __system_property_foreach(
- [](const prop_info* pi, void* cookie) {
- __system_property_read_callback(
- pi,
- [](void* cookie, const char* name, const char* value, unsigned serial) {
- if (StartsWith(name, "persist.")) {
- auto properties = reinterpret_cast<PersistentProperties*>(cookie);
- AddPersistentProperty(name, value, properties);
- }
- },
- cookie);
- },
- &persistent_properties);
- return persistent_properties;
-}
-
Result<std::string> ReadPersistentPropertyFile() {
const std::string temp_filename = persistent_property_filename + ".tmp";
if (access(temp_filename.c_str(), F_OK) == 0) {
@@ -221,6 +203,24 @@
return {};
}
+PersistentProperties LoadPersistentPropertiesFromMemory() {
+ PersistentProperties persistent_properties;
+ __system_property_foreach(
+ [](const prop_info* pi, void* cookie) {
+ __system_property_read_callback(
+ pi,
+ [](void* cookie, const char* name, const char* value, unsigned serial) {
+ if (StartsWith(name, "persist.")) {
+ auto properties = reinterpret_cast<PersistentProperties*>(cookie);
+ AddPersistentProperty(name, value, properties);
+ }
+ },
+ cookie);
+ },
+ &persistent_properties);
+ return persistent_properties;
+}
+
// Persistent properties are not written often, so we rather not keep any data in memory and read
// then rewrite the persistent property file for each update.
void WritePersistentProperty(const std::string& name, const std::string& value) {
diff --git a/init/persistent_properties.h b/init/persistent_properties.h
index a6f80e6..7e9d438 100644
--- a/init/persistent_properties.h
+++ b/init/persistent_properties.h
@@ -29,6 +29,7 @@
PersistentProperties* persistent_properties);
PersistentProperties LoadPersistentProperties();
void WritePersistentProperty(const std::string& name, const std::string& value);
+PersistentProperties LoadPersistentPropertiesFromMemory();
// Exposed only for testing
Result<PersistentProperties> LoadPersistentPropertyFile();
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 38cbea3..b08a904 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -1400,8 +1400,6 @@
// Apply staged and persistent properties
bool has_staged_prop = false;
auto const staged_prefix = std::string_view("next_boot.");
- auto const staged_persist_prefix = std::string_view("next_boot.persist.");
- auto persist_props_map = std::unordered_map<std::string, std::string>();
auto persistent_properties = LoadPersistentProperties();
for (const auto& property_record : persistent_properties.properties()) {
@@ -1412,23 +1410,16 @@
has_staged_prop = true;
auto actual_prop_name = prop_name.substr(staged_prefix.size());
InitPropertySet(actual_prop_name, prop_value);
- if (StartsWith(prop_name, staged_persist_prefix)) {
- persist_props_map[actual_prop_name] = prop_value;
- }
- } else if (!persist_props_map.count(prop_name)) {
+ } else {
InitPropertySet(prop_name, prop_value);
}
}
// Update persist prop file if there are staged props
if (has_staged_prop) {
- PersistentProperties updated_persist_props;
- for (auto const& [prop_name, prop_value] : persist_props_map) {
- AddPersistentProperty(prop_name, prop_value, &updated_persist_props);
- }
-
+ PersistentProperties props = LoadPersistentPropertiesFromMemory();
// write current updated persist prop file
- auto result = WritePersistentPropertyFile(updated_persist_props);
+ auto result = WritePersistentPropertyFile(props);
if (!result.ok()) {
LOG(ERROR) << "Could not store persistent property: " << result.error();
}
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 9095b85..1f211dd 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -503,10 +503,6 @@
<< ") failed";
}
}
-
- if (auto result = WriteFile("/sys/fs/selinux/checkreqprot", "0"); !result.ok()) {
- LOG(FATAL) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error();
- }
}
constexpr size_t kKlogMessageSize = 1024;