Merge "Fix handling of ro segments for embedded libs."
diff --git a/adb/Android.bp b/adb/Android.bp
index ae8e386..6234af1 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -24,7 +24,7 @@
"-Wno-missing-field-initializers",
"-Wvla",
],
- rtti: true,
+ cpp_std: "experimental",
use_version_lib: true,
diff --git a/adb/adb.h b/adb/adb.h
index e2911e8..cdd6346 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -149,6 +149,10 @@
#endif
#if !ADB_HOST
+asocket* daemon_service_to_socket(std::string_view name);
+#endif
+
+#if !ADB_HOST
int init_jdwp(void);
asocket* create_jdwp_service_socket();
asocket* create_jdwp_tracker_service_socket();
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 95e66ae..c8e834e 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -1275,6 +1275,42 @@
return 0;
}
+static int adb_connect_command_bidirectional(const std::string& command) {
+ std::string error;
+ int fd = adb_connect(command, &error);
+ if (fd < 0) {
+ fprintf(stderr, "error: %s\n", error.c_str());
+ return 1;
+ }
+
+ static constexpr auto forward = [](int src, int sink, bool exit_on_end) {
+ char buf[4096];
+ while (true) {
+ int rc = adb_read(src, buf, sizeof(buf));
+ if (rc == 0) {
+ if (exit_on_end) {
+ exit(0);
+ } else {
+ adb_shutdown(sink, SHUT_WR);
+ }
+ return;
+ } else if (rc < 0) {
+ perror_exit("read failed");
+ }
+ if (!WriteFdExactly(sink, buf, rc)) {
+ perror_exit("write failed");
+ }
+ }
+ };
+
+ std::thread read(forward, fd, STDOUT_FILENO, true);
+ std::thread write(forward, STDIN_FILENO, fd, false);
+ read.join();
+ write.join();
+ adb_close(fd);
+ return 0;
+}
+
static int adb_query_command(const std::string& command) {
std::string result;
std::string error;
@@ -1766,7 +1802,7 @@
if (argc != 2) {
error_exit("usage: adb raw SERVICE");
}
- return adb_connect_command(argv[1]);
+ return adb_connect_command_bidirectional(argv[1]);
}
/* "adb /?" is a common idiom under Windows */
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
index b72ed16..1a92317 100644
--- a/adb/daemon/remount_service.cpp
+++ b/adb/daemon/remount_service.cpp
@@ -245,9 +245,8 @@
// If we can use overlayfs, lets get it in place first
// before we struggle with determining deduplication operations.
if (!verity_enabled && fs_mgr_overlayfs_setup()) {
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- if (fs_mgr_overlayfs_mount_all(fstab.get())) {
+ Fstab fstab;
+ if (ReadDefaultFstab(&fstab) && fs_mgr_overlayfs_mount_all(&fstab)) {
WriteFdExactly(fd.get(), "overlayfs mounted\n");
}
}
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index b300fac..3182ddd 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -33,6 +33,7 @@
#include <thread>
#include <android-base/file.h>
+#include <android-base/parseint.h>
#include <android-base/parsenetaddress.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
@@ -223,6 +224,105 @@
WriteFdExactly(fd.get(), "spinning\n");
}
+struct ServiceSocket : public asocket {
+ ServiceSocket() {
+ install_local_socket(this);
+ this->enqueue = [](asocket* self, apacket::payload_type data) {
+ return static_cast<ServiceSocket*>(self)->Enqueue(std::move(data));
+ };
+ this->ready = [](asocket* self) { return static_cast<ServiceSocket*>(self)->Ready(); };
+ this->close = [](asocket* self) { return static_cast<ServiceSocket*>(self)->Close(); };
+ }
+ virtual ~ServiceSocket() = default;
+
+ virtual int Enqueue(apacket::payload_type data) { return -1; }
+ virtual void Ready() {}
+ virtual void Close() {
+ if (peer) {
+ peer->peer = nullptr;
+ if (peer->shutdown) {
+ peer->shutdown(peer);
+ }
+ peer->close(peer);
+ }
+
+ remove_socket(this);
+ delete this;
+ }
+};
+
+struct SinkSocket : public ServiceSocket {
+ explicit SinkSocket(size_t byte_count) {
+ LOG(INFO) << "Creating new SinkSocket with capacity " << byte_count;
+ bytes_left_ = byte_count;
+ }
+
+ virtual ~SinkSocket() { LOG(INFO) << "SinkSocket destroyed"; }
+
+ virtual int Enqueue(apacket::payload_type data) override final {
+ if (bytes_left_ <= data.size()) {
+ // Done reading.
+ Close();
+ return -1;
+ }
+
+ bytes_left_ -= data.size();
+ return 0;
+ }
+
+ size_t bytes_left_;
+};
+
+struct SourceSocket : public ServiceSocket {
+ explicit SourceSocket(size_t byte_count) {
+ LOG(INFO) << "Creating new SourceSocket with capacity " << byte_count;
+ bytes_left_ = byte_count;
+ }
+
+ virtual ~SourceSocket() { LOG(INFO) << "SourceSocket destroyed"; }
+
+ void Ready() {
+ size_t len = std::min(bytes_left_, get_max_payload());
+ if (len == 0) {
+ Close();
+ return;
+ }
+
+ Block block(len);
+ memset(block.data(), 0, block.size());
+ peer->enqueue(peer, std::move(block));
+ bytes_left_ -= len;
+ }
+
+ int Enqueue(apacket::payload_type data) { return -1; }
+
+ size_t bytes_left_;
+};
+
+asocket* daemon_service_to_socket(std::string_view name) {
+ if (name == "jdwp") {
+ return create_jdwp_service_socket();
+ } else if (name == "track-jdwp") {
+ return create_jdwp_tracker_service_socket();
+ } else if (name.starts_with("sink:")) {
+ name.remove_prefix(strlen("sink:"));
+ uint64_t byte_count = 0;
+ if (!android::base::ParseUint(name.data(), &byte_count)) {
+ return nullptr;
+ }
+ return new SinkSocket(byte_count);
+ } else if (name.starts_with("source:")) {
+ name.remove_prefix(strlen("source:"));
+ uint64_t byte_count = 0;
+ if (!android::base::ParseUint(name.data(), &byte_count)) {
+ return nullptr;
+ }
+ return new SourceSocket(byte_count);
+ }
+
+ return nullptr;
+}
+
unique_fd daemon_service_to_fd(const char* name, atransport* transport) {
if (!strncmp("dev:", name, 4)) {
return unique_fd{unix_open(name + 4, O_RDWR | O_CLOEXEC)};
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp
index 01097ac..8805fc1 100644
--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -273,7 +273,7 @@
}
std::vector<std::string> joined_env;
- for (auto it : env) {
+ for (const auto& it : env) {
const char* key = it.first.c_str();
const char* value = it.second.c_str();
joined_env.push_back(android::base::StringPrintf("%s=%s", key, value));
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 8b07f74..1bd57c1 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -348,11 +348,8 @@
asocket* create_local_service_socket(const char* name, atransport* transport) {
#if !ADB_HOST
- if (!strcmp(name, "jdwp")) {
- return create_jdwp_service_socket();
- }
- if (!strcmp(name, "track-jdwp")) {
- return create_jdwp_tracker_service_socket();
+ if (asocket* s = daemon_service_to_socket(name); s) {
+ return s;
}
#endif
int fd = service_to_fd(name, transport);
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 8741654..f59a135 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -1305,11 +1305,7 @@
void unregister_usb_transport(usb_handle* usb) {
std::lock_guard<std::recursive_mutex> lock(transport_lock);
transport_list.remove_if([usb](atransport* t) {
- auto connection = t->connection();
- if (auto usb_connection = dynamic_cast<UsbConnection*>(connection.get())) {
- return usb_connection->handle_ == usb && t->GetConnectionState() == kCsNoPerm;
- }
- return false;
+ return t->GetUsbHandle() == usb && t->GetConnectionState() == kCsNoPerm;
});
}
#endif
diff --git a/adb/transport.h b/adb/transport.h
index d593700..790004f 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -37,6 +37,7 @@
#include "adb.h"
#include "adb_unique_fd.h"
+#include "usb.h"
typedef std::unordered_set<std::string> FeatureSet;
@@ -242,6 +243,9 @@
return connection_;
}
+ void SetUsbHandle(usb_handle* h) { usb_handle_ = h; }
+ usb_handle* GetUsbHandle() { return usb_handle_; }
+
const TransportId id;
size_t ref_count = 0;
bool online = false;
@@ -333,6 +337,9 @@
// The underlying connection object.
std::shared_ptr<Connection> connection_ GUARDED_BY(mutex_);
+ // USB handle for the connection, if available.
+ usb_handle* usb_handle_ = nullptr;
+
// A callback that will be invoked when the atransport needs to reconnect.
ReconnectCallback reconnect_;
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index c471bf9..2e5918a 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -180,6 +180,7 @@
auto connection = std::make_unique<UsbConnection>(h);
t->SetConnection(std::make_unique<BlockingConnectionAdapter>(std::move(connection)));
t->type = kTransportUsb;
+ t->SetUsbHandle(h);
}
int is_adb_interface(int usb_class, int usb_subclass, int usb_protocol) {
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index 479a06a..ef34771 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -281,7 +281,7 @@
std::vector<std::string> vars;
EXPECT_EQ(fb->GetVarAll(&vars), SUCCESS) << "getvar:all failed";
EXPECT_GT(vars.size(), 0) << "getvar:all did not respond with any INFO responses";
- for (const auto s : vars) {
+ for (const auto& s : vars) {
EXPECT_LE(s.size(), FB_RESPONSE_SZ - 4)
<< "getvar:all included an INFO response: 'INFO" + s << "' which is too long";
}
@@ -316,7 +316,7 @@
EXPECT_GT(parts.size(), 0)
<< "getvar:all did not report any partition-size: through INFO responses";
std::set<std::string> allowed{"ext4", "f2fs", "raw"};
- for (const auto p : parts) {
+ for (const auto& p : parts) {
EXPECT_GE(std::get<1>(p), 0);
std::string part(std::get<0>(p));
std::set<std::string> allowed{"ext4", "f2fs", "raw"};
@@ -355,7 +355,7 @@
if (num_slots > 0) {
EXPECT_EQ(fb->GetVar("current-slot", &var), SUCCESS) << "getvar:current-slot failed";
- for (const auto p : parts) {
+ for (const auto& p : parts) {
std::string part(std::get<0>(p));
std::regex reg("([[:graph:]]*)_([[:lower:]])");
std::smatch sm;
@@ -378,7 +378,7 @@
}
}
// Ensure each partition has the correct slot suffix
- for (const auto iter : part_slots) {
+ for (const auto& iter : part_slots) {
const std::set<char>& char_set = iter.second;
std::string chars;
for (char c : char_set) {
@@ -572,7 +572,7 @@
std::vector<std::tuple<std::string, uint64_t>> parts;
EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed in locked mode";
std::string resp;
- for (const auto tup : parts) {
+ for (const auto& tup : parts) {
EXPECT_EQ(fb->Flash(std::get<0>(tup), &resp), DEVICE_FAIL)
<< "Device did not respond with FAIL when trying to flash '" << std::get<0>(tup)
<< "' in locked mode";
@@ -585,7 +585,7 @@
std::vector<std::tuple<std::string, uint64_t>> parts;
EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed";
std::string resp;
- for (const auto tup : parts) {
+ for (const auto& tup : parts) {
EXPECT_EQ(fb->Erase(std::get<0>(tup), &resp), DEVICE_FAIL)
<< "Device did not respond with FAIL when trying to erase '" << std::get<0>(tup)
<< "' in locked mode";
@@ -601,7 +601,7 @@
EXPECT_EQ(fb->GetVar("slot-count", &resp), SUCCESS) << "getvar:slot-count failed";
int32_t num_slots = strtol(resp.c_str(), nullptr, 10);
- for (const auto tup : parts) {
+ for (const auto& tup : parts) {
std::string part(std::get<0>(tup));
std::regex reg("([[:graph:]]*)_([[:lower:]])");
std::smatch sm;
@@ -1554,12 +1554,12 @@
void GenerateXmlTests(const extension::Configuration& config) {
// Build the getvar tests
- for (const auto it : config.getvars) {
+ for (const auto& it : config.getvars) {
GETVAR_XML_TESTS.push_back(std::make_pair(it.first, it.second));
}
// Build the partition tests, to interface with gtest we need to do it this way
- for (const auto it : config.partitions) {
+ for (const auto& it : config.partitions) {
const auto tup = std::make_tuple(it.first, it.second);
PARTITION_XML_TESTS.push_back(tup); // All partitions
@@ -1581,7 +1581,7 @@
// Build the packed tests, only useful if we have a hash
if (!config.checksum.empty()) {
- for (const auto it : config.packed) {
+ for (const auto& it : config.packed) {
for (const auto& test : it.second.tests) {
const auto tup = std::make_tuple(it.first, test);
if (test.expect == extension::OKAY) { // only testing the success case
@@ -1608,7 +1608,7 @@
}
// Build oem tests
- for (const auto it : config.oem) {
+ for (const auto& it : config.oem) {
auto oem_cmd = it.second;
for (const auto& t : oem_cmd.tests) {
OEM_XML_TESTS.push_back(std::make_tuple(it.first, oem_cmd.restricted, t));
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index 99231ac..ac138a3 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -23,7 +23,6 @@
cflags: [
"-Wall",
"-Werror",
- "-Wno-unused-variable",
],
}
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 4e1360e..8757689 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -336,10 +336,10 @@
}
// Enable/disable quota support on the filesystem if needed.
-static void tune_quota(const std::string& blk_device, const struct fstab_rec* rec,
+static void tune_quota(const std::string& blk_device, const FstabEntry& entry,
const struct ext4_super_block* sb, int* fs_stat) {
bool has_quota = (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_QUOTA)) != 0;
- bool want_quota = fs_mgr_is_quota(rec) != 0;
+ bool want_quota = entry.fs_mgr_flags.quota;
if (has_quota == want_quota) {
return;
@@ -372,16 +372,16 @@
}
// Set the number of reserved filesystem blocks if needed.
-static void tune_reserved_size(const std::string& blk_device, const struct fstab_rec* rec,
+static void tune_reserved_size(const std::string& blk_device, const FstabEntry& entry,
const struct ext4_super_block* sb, int* fs_stat) {
- if (!(rec->fs_mgr_flags & MF_RESERVEDSIZE)) {
+ if (!entry.fs_mgr_flags.reserved_size) {
return;
}
// The size to reserve is given in the fstab, but we won't reserve more
// than 2% of the filesystem.
const uint64_t max_reserved_blocks = ext4_blocks_count(sb) * 0.02;
- uint64_t reserved_blocks = rec->reserved_size / EXT4_BLOCK_SIZE(sb);
+ uint64_t reserved_blocks = entry.reserved_size / EXT4_BLOCK_SIZE(sb);
if (reserved_blocks > max_reserved_blocks) {
LWARNING << "Reserved blocks " << reserved_blocks << " is too large; "
@@ -414,10 +414,10 @@
}
// Enable file-based encryption if needed.
-static void tune_encrypt(const std::string& blk_device, const struct fstab_rec* rec,
+static void tune_encrypt(const std::string& blk_device, const FstabEntry& entry,
const struct ext4_super_block* sb, int* fs_stat) {
bool has_encrypt = (sb->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_ENCRYPT)) != 0;
- bool want_encrypt = fs_mgr_is_file_encrypted(rec) != 0;
+ bool want_encrypt = entry.fs_mgr_flags.file_encryption;
if (has_encrypt || !want_encrypt) {
return;
@@ -478,10 +478,10 @@
// If needed, we'll also enable (or disable) filesystem features as specified by
// the fstab record.
//
-static int prepare_fs_for_mount(const std::string& blk_device, const struct fstab_rec* rec) {
+static int prepare_fs_for_mount(const std::string& blk_device, const FstabEntry& entry) {
int fs_stat = 0;
- if (is_extfs(rec->fs_type)) {
+ if (is_extfs(entry.fs_type)) {
struct ext4_super_block sb;
if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
@@ -494,27 +494,28 @@
}
// Note: quotas should be enabled before running fsck.
- tune_quota(blk_device, rec, &sb, &fs_stat);
+ tune_quota(blk_device, entry, &sb, &fs_stat);
} else {
return fs_stat;
}
- } else if (is_f2fs(rec->fs_type)) {
+ } else if (is_f2fs(entry.fs_type)) {
if (!read_f2fs_superblock(blk_device, &fs_stat)) {
return fs_stat;
}
}
- if ((rec->fs_mgr_flags & MF_CHECK) ||
+ if (entry.fs_mgr_flags.check ||
(fs_stat & (FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED))) {
- check_fs(blk_device, rec->fs_type, rec->mount_point, &fs_stat);
+ check_fs(blk_device, entry.fs_type, entry.mount_point, &fs_stat);
}
- if (is_extfs(rec->fs_type) && (rec->fs_mgr_flags & (MF_RESERVEDSIZE | MF_FILEENCRYPTION))) {
+ if (is_extfs(entry.fs_type) &&
+ (entry.fs_mgr_flags.reserved_size || entry.fs_mgr_flags.file_encryption)) {
struct ext4_super_block sb;
if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
- tune_reserved_size(blk_device, rec, &sb, &fs_stat);
- tune_encrypt(blk_device, rec, &sb, &fs_stat);
+ tune_reserved_size(blk_device, entry, &sb, &fs_stat);
+ tune_encrypt(blk_device, entry, &sb, &fs_stat);
}
}
@@ -545,8 +546,7 @@
// __mount(): wrapper around the mount() system call which also
// sets the underlying block device to read-only if the mount is read-only.
// See "man 2 mount" for return values.
-static int __mount(const std::string& source, const std::string& target,
- const struct fstab_rec* rec) {
+static int __mount(const std::string& source, const std::string& target, const FstabEntry& entry) {
// We need this because sometimes we have legacy symlinks that are
// lingering around and need cleaning up.
struct stat info;
@@ -555,8 +555,9 @@
}
mkdir(target.c_str(), 0755);
errno = 0;
- unsigned long mountflags = rec->flags;
- int ret = mount(source.c_str(), target.c_str(), rec->fs_type, mountflags, rec->fs_options);
+ unsigned long mountflags = entry.flags;
+ int ret = mount(source.c_str(), target.c_str(), entry.fs_type.c_str(), mountflags,
+ entry.fs_options.c_str());
int save_errno = errno;
const char* target_missing = "";
const char* source_missing = "";
@@ -569,7 +570,7 @@
errno = save_errno;
}
PINFO << __FUNCTION__ << "(source=" << source << source_missing << ",target=" << target
- << target_missing << ",type=" << rec->fs_type << ")=" << ret;
+ << target_missing << ",type=" << entry.fs_type << ")=" << ret;
if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
fs_mgr_set_blk_ro(source);
}
@@ -605,106 +606,88 @@
return true;
}
-/*
- * Tries to mount any of the consecutive fstab entries that match
- * the mountpoint of the one given by fstab->recs[start_idx].
- *
- * end_idx: On return, will be the last rec that was looked at.
- * attempted_idx: On return, will indicate which fstab rec
- * succeeded. In case of failure, it will be the start_idx.
- * Returns
- * -1 on failure with errno set to match the 1st mount failure.
- * 0 on success.
- */
-static int mount_with_alternatives(fstab* fstab, int start_idx, int* end_idx, int* attempted_idx) {
+// Tries to mount any of the consecutive fstab entries that match
+// the mountpoint of the one given by fstab[start_idx].
+//
+// end_idx: On return, will be the last entry that was looked at.
+// attempted_idx: On return, will indicate which fstab entry
+// succeeded. In case of failure, it will be the start_idx.
+// Sets errno to match the 1st mount failure on failure.
+static bool mount_with_alternatives(const Fstab& fstab, int start_idx, int* end_idx,
+ int* attempted_idx) {
int i;
int mount_errno = 0;
- int mounted = 0;
+ bool mounted = false;
- if (!end_idx || !attempted_idx || start_idx >= fstab->num_entries) {
- errno = EINVAL;
- if (end_idx) *end_idx = start_idx;
- if (attempted_idx) *attempted_idx = start_idx;
- return -1;
- }
-
- /* Hunt down an fstab entry for the same mount point that might succeed */
+ // Hunt down an fstab entry for the same mount point that might succeed.
for (i = start_idx;
- /* We required that fstab entries for the same mountpoint be consecutive */
- i < fstab->num_entries && !strcmp(fstab->recs[start_idx].mount_point, fstab->recs[i].mount_point);
- i++) {
- /*
- * Don't try to mount/encrypt the same mount point again.
- * Deal with alternate entries for the same point which are required to be all following
- * each other.
- */
- if (mounted) {
- LERROR << __FUNCTION__ << "(): skipping fstab dup mountpoint="
- << fstab->recs[i].mount_point << " rec[" << i
- << "].fs_type=" << fstab->recs[i].fs_type
- << " already mounted as "
- << fstab->recs[*attempted_idx].fs_type;
- continue;
- }
+ // We required that fstab entries for the same mountpoint be consecutive.
+ i < fstab.size() && fstab[start_idx].mount_point == fstab[i].mount_point; i++) {
+ // Don't try to mount/encrypt the same mount point again.
+ // Deal with alternate entries for the same point which are required to be all following
+ // each other.
+ if (mounted) {
+ LERROR << __FUNCTION__ << "(): skipping fstab dup mountpoint=" << fstab[i].mount_point
+ << " rec[" << i << "].fs_type=" << fstab[i].fs_type << " already mounted as "
+ << fstab[*attempted_idx].fs_type;
+ continue;
+ }
- int fs_stat = prepare_fs_for_mount(fstab->recs[i].blk_device, &fstab->recs[i]);
- if (fs_stat & FS_STAT_INVALID_MAGIC) {
- LERROR << __FUNCTION__ << "(): skipping mount due to invalid magic, mountpoint="
- << fstab->recs[i].mount_point
- << " blk_dev=" << realpath(fstab->recs[i].blk_device) << " rec[" << i
- << "].fs_type=" << fstab->recs[i].fs_type;
- mount_errno = EINVAL; // continue bootup for FDE
- continue;
- }
+ int fs_stat = prepare_fs_for_mount(fstab[i].blk_device, fstab[i]);
+ if (fs_stat & FS_STAT_INVALID_MAGIC) {
+ LERROR << __FUNCTION__
+ << "(): skipping mount due to invalid magic, mountpoint=" << fstab[i].mount_point
+ << " blk_dev=" << realpath(fstab[i].blk_device) << " rec[" << i
+ << "].fs_type=" << fstab[i].fs_type;
+ mount_errno = EINVAL; // continue bootup for FDE
+ continue;
+ }
- int retry_count = 2;
- while (retry_count-- > 0) {
- if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point,
- &fstab->recs[i])) {
- *attempted_idx = i;
- mounted = 1;
- if (i != start_idx) {
- LERROR << __FUNCTION__ << "(): Mounted " << fstab->recs[i].blk_device
- << " on " << fstab->recs[i].mount_point
- << " with fs_type=" << fstab->recs[i].fs_type << " instead of "
- << fstab->recs[start_idx].fs_type;
- }
- fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
- mount_errno = 0;
- break;
- } else {
- if (retry_count <= 0) break; // run check_fs only once
- fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
- /* back up the first errno for crypto decisions */
- if (mount_errno == 0) {
- mount_errno = errno;
- }
- // retry after fsck
- check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
- fstab->recs[i].mount_point, &fs_stat);
+ int retry_count = 2;
+ while (retry_count-- > 0) {
+ if (!__mount(fstab[i].blk_device, fstab[i].mount_point, fstab[i])) {
+ *attempted_idx = i;
+ mounted = true;
+ if (i != start_idx) {
+ LERROR << __FUNCTION__ << "(): Mounted " << fstab[i].blk_device << " on "
+ << fstab[i].mount_point << " with fs_type=" << fstab[i].fs_type
+ << " instead of " << fstab[start_idx].fs_type;
}
+ fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
+ mount_errno = 0;
+ break;
+ } else {
+ if (retry_count <= 0) break; // run check_fs only once
+ fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
+ // back up the first errno for crypto decisions.
+ if (mount_errno == 0) {
+ mount_errno = errno;
+ }
+ // retry after fsck
+ check_fs(fstab[i].blk_device, fstab[i].fs_type, fstab[i].mount_point, &fs_stat);
}
- log_fs_stat(fstab->recs[i].blk_device, fs_stat);
+ }
+ log_fs_stat(fstab[i].blk_device, fs_stat);
}
/* Adjust i for the case where it was still withing the recs[] */
- if (i < fstab->num_entries) --i;
+ if (i < fstab.size()) --i;
*end_idx = i;
if (!mounted) {
*attempted_idx = start_idx;
errno = mount_errno;
- return -1;
+ return false;
}
- return 0;
+ return true;
}
-static bool TranslateExtLabels(fstab_rec* rec) {
- if (!StartsWith(rec->blk_device, "LABEL=")) {
+static bool TranslateExtLabels(FstabEntry* entry) {
+ if (!StartsWith(entry->blk_device, "LABEL=")) {
return true;
}
- std::string label = rec->blk_device + 6;
+ std::string label = entry->blk_device.substr(6);
if (label.size() > 16) {
LERROR << "FS label is longer than allowed by filesystem";
return false;
@@ -744,10 +727,9 @@
if (label == super_block.s_volume_name) {
std::string new_blk_device = "/dev/block/"s + ent->d_name;
- LINFO << "resolved label " << rec->blk_device << " to " << new_blk_device;
+ LINFO << "resolved label " << entry->blk_device << " to " << new_blk_device;
- free(rec->blk_device);
- rec->blk_device = strdup(new_blk_device.c_str());
+ entry->blk_device = new_blk_device;
return true;
}
}
@@ -755,54 +737,49 @@
return false;
}
-static bool needs_block_encryption(const struct fstab_rec* rec)
-{
- if (android::base::GetBoolProperty("ro.vold.forceencryption", false) &&
- fs_mgr_is_encryptable(rec))
+static bool needs_block_encryption(const FstabEntry& entry) {
+ if (android::base::GetBoolProperty("ro.vold.forceencryption", false) && entry.is_encryptable())
return true;
- if (rec->fs_mgr_flags & MF_FORCECRYPT) return true;
- if (rec->fs_mgr_flags & MF_CRYPT) {
+ if (entry.fs_mgr_flags.force_crypt) return true;
+ if (entry.fs_mgr_flags.crypt) {
// Check for existence of convert_fde breadcrumb file.
- auto convert_fde_name = rec->mount_point + "%s/misc/vold/convert_fde"s;
+ auto convert_fde_name = entry.mount_point + "/misc/vold/convert_fde";
if (access(convert_fde_name.c_str(), F_OK) == 0) return true;
}
- if (rec->fs_mgr_flags & MF_FORCEFDEORFBE) {
+ if (entry.fs_mgr_flags.force_fde_or_fbe) {
// Check for absence of convert_fbe breadcrumb file.
- auto convert_fbe_name = rec->mount_point + "/convert_fbe"s;
+ auto convert_fbe_name = entry.mount_point + "/convert_fbe";
if (access(convert_fbe_name.c_str(), F_OK) != 0) return true;
}
return false;
}
-static bool should_use_metadata_encryption(const struct fstab_rec* rec) {
- if (!(rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE))) return false;
- if (!(rec->fs_mgr_flags & MF_KEYDIRECTORY)) return false;
- return true;
+static bool should_use_metadata_encryption(const FstabEntry& entry) {
+ return entry.fs_mgr_flags.key_directory &&
+ (entry.fs_mgr_flags.file_encryption || entry.fs_mgr_flags.force_fde_or_fbe);
}
// Check to see if a mountable volume has encryption requirements
-static int handle_encryptable(const struct fstab_rec* rec)
-{
- /* If this is block encryptable, need to trigger encryption */
- if (needs_block_encryption(rec)) {
- if (umount(rec->mount_point) == 0) {
+static int handle_encryptable(const FstabEntry& entry) {
+ // If this is block encryptable, need to trigger encryption.
+ if (needs_block_encryption(entry)) {
+ if (umount(entry.mount_point.c_str()) == 0) {
return FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION;
} else {
- PWARNING << "Could not umount " << rec->mount_point
- << " - allow continue unencrypted";
+ PWARNING << "Could not umount " << entry.mount_point << " - allow continue unencrypted";
return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
}
- } else if (should_use_metadata_encryption(rec)) {
- if (umount(rec->mount_point) == 0) {
+ } else if (should_use_metadata_encryption(entry)) {
+ if (umount(entry.mount_point.c_str()) == 0) {
return FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION;
} else {
- PERROR << "Could not umount " << rec->mount_point << " - fail since can't encrypt";
+ PERROR << "Could not umount " << entry.mount_point << " - fail since can't encrypt";
return FS_MGR_MNTALL_FAIL;
}
- } else if (rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE)) {
- LINFO << rec->mount_point << " is file encrypted";
+ } else if (entry.fs_mgr_flags.file_encryption || entry.fs_mgr_flags.force_fde_or_fbe) {
+ LINFO << entry.mount_point << " is file encrypted";
return FS_MGR_MNTALL_DEV_FILE_ENCRYPTED;
- } else if (fs_mgr_is_encryptable(rec)) {
+ } else if (entry.is_encryptable()) {
return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
} else {
return FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE;
@@ -843,21 +820,34 @@
return true;
}
-bool fs_mgr_update_logical_partition(struct fstab_rec* rec) {
+bool fs_mgr_update_logical_partition(FstabEntry* entry) {
// Logical partitions are specified with a named partition rather than a
// block device, so if the block device is a path, then it has already
// been updated.
- if (rec->blk_device[0] == '/') {
+ if (entry->blk_device[0] == '/') {
return true;
}
DeviceMapper& dm = DeviceMapper::Instance();
std::string device_name;
- if (!dm.GetDmDevicePathByName(rec->blk_device, &device_name)) {
+ if (!dm.GetDmDevicePathByName(entry->blk_device, &device_name)) {
return false;
}
+
+ entry->blk_device = device_name;
+ return true;
+}
+
+bool fs_mgr_update_logical_partition(struct fstab_rec* rec) {
+ auto entry = FstabRecToFstabEntry(rec);
+
+ if (!fs_mgr_update_logical_partition(&entry)) {
+ return false;
+ }
+
free(rec->blk_device);
- rec->blk_device = strdup(device_name.c_str());
+ rec->blk_device = strdup(entry.blk_device.c_str());
+
return true;
}
@@ -865,13 +855,13 @@
public:
CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}
- bool Update(struct fstab_rec* rec) {
- if (!fs_mgr_is_checkpoint(rec)) {
+ bool Update(FstabEntry* entry) {
+ if (!entry->fs_mgr_flags.checkpoint_blk && !entry->fs_mgr_flags.checkpoint_fs) {
return true;
}
- if (fs_mgr_is_checkpoint_blk(rec)) {
- call_vdc({"checkpoint", "restoreCheckpoint", rec->blk_device});
+ if (entry->fs_mgr_flags.checkpoint_blk) {
+ call_vdc({"checkpoint", "restoreCheckpoint", entry->blk_device});
}
if (needs_checkpoint_ == UNKNOWN &&
@@ -884,7 +874,7 @@
return true;
}
- if (!UpdateCheckpointPartition(rec)) {
+ if (!UpdateCheckpointPartition(entry)) {
LERROR << "Could not set up checkpoint partition, skipping!";
return false;
}
@@ -892,18 +882,17 @@
return true;
}
- bool Revert(struct fstab_rec* rec) {
- if (!fs_mgr_is_checkpoint(rec)) {
+ bool Revert(FstabEntry* entry) {
+ if (!entry->fs_mgr_flags.checkpoint_blk && !entry->fs_mgr_flags.checkpoint_fs) {
return true;
}
- if (device_map_.find(rec->blk_device) == device_map_.end()) {
+ if (device_map_.find(entry->blk_device) == device_map_.end()) {
return true;
}
- std::string bow_device = rec->blk_device;
- free(rec->blk_device);
- rec->blk_device = strdup(device_map_[bow_device].c_str());
+ std::string bow_device = entry->blk_device;
+ entry->blk_device = device_map_[bow_device];
device_map_.erase(bow_device);
DeviceMapper& dm = DeviceMapper::Instance();
@@ -915,21 +904,17 @@
}
private:
- bool UpdateCheckpointPartition(struct fstab_rec* rec) {
- if (fs_mgr_is_checkpoint_fs(rec)) {
- if (is_f2fs(rec->fs_type)) {
- std::string opts(rec->fs_options);
-
- opts += ",checkpoint=disable";
- free(rec->fs_options);
- rec->fs_options = strdup(opts.c_str());
+ bool UpdateCheckpointPartition(FstabEntry* entry) {
+ if (entry->fs_mgr_flags.checkpoint_fs) {
+ if (is_f2fs(entry->fs_type)) {
+ entry->fs_options += ",checkpoint=disable";
} else {
- LERROR << rec->fs_type << " does not implement checkpoints.";
+ LERROR << entry->fs_type << " does not implement checkpoints.";
}
- } else if (fs_mgr_is_checkpoint_blk(rec)) {
- unique_fd fd(TEMP_FAILURE_RETRY(open(rec->blk_device, O_RDONLY | O_CLOEXEC)));
+ } else if (entry->fs_mgr_flags.checkpoint_blk) {
+ unique_fd fd(TEMP_FAILURE_RETRY(open(entry->blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
if (fd < 0) {
- PERROR << "Cannot open device " << rec->blk_device;
+ PERROR << "Cannot open device " << entry->blk_device;
return false;
}
@@ -941,7 +926,7 @@
android::dm::DmTable table;
if (!table.AddTarget(
- std::make_unique<android::dm::DmTargetBow>(0, size, rec->blk_device))) {
+ std::make_unique<android::dm::DmTargetBow>(0, size, entry->blk_device))) {
LERROR << "Failed to add bow target";
return false;
}
@@ -958,9 +943,8 @@
return false;
}
- device_map_[name] = rec->blk_device;
- free(rec->blk_device);
- rec->blk_device = strdup(name.c_str());
+ device_map_[name] = entry->blk_device;
+ entry->blk_device = name;
}
return true;
}
@@ -970,76 +954,70 @@
std::map<std::string, std::string> device_map_;
};
-/* When multiple fstab records share the same mount_point, it will
- * try to mount each one in turn, and ignore any duplicates after a
- * first successful mount.
- * Returns -1 on error, and FS_MGR_MNTALL_* otherwise.
- */
-int fs_mgr_mount_all(fstab* fstab, int mount_mode) {
- int i = 0;
+// When multiple fstab records share the same mount_point, it will try to mount each
+// one in turn, and ignore any duplicates after a first successful mount.
+// Returns -1 on error, and FS_MGR_MNTALL_* otherwise.
+int fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE;
int error_count = 0;
- int mret = -1;
- int mount_errno = 0;
- int attempted_idx = -1;
CheckpointManager checkpoint_manager;
AvbUniquePtr avb_handle(nullptr);
- if (!fstab) {
+ if (fstab->empty()) {
return FS_MGR_MNTALL_FAIL;
}
- for (i = 0; i < fstab->num_entries; i++) {
- /* Don't mount entries that are managed by vold or not for the mount mode*/
- if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) ||
- ((mount_mode == MOUNT_MODE_LATE) && !fs_mgr_is_latemount(&fstab->recs[i])) ||
- ((mount_mode == MOUNT_MODE_EARLY) && fs_mgr_is_latemount(&fstab->recs[i])) ||
- fs_mgr_is_first_stage_mount(&fstab->recs[i])) {
+ for (size_t i = 0; i < fstab->size(); i++) {
+ auto& current_entry = (*fstab)[i];
+
+ // Don't mount entries that are managed by vold or not for the mount mode.
+ if (current_entry.fs_mgr_flags.vold_managed || current_entry.fs_mgr_flags.recovery_only ||
+ current_entry.fs_mgr_flags.first_stage_mount ||
+ ((mount_mode == MOUNT_MODE_LATE) && !current_entry.fs_mgr_flags.late_mount) ||
+ ((mount_mode == MOUNT_MODE_EARLY) && current_entry.fs_mgr_flags.late_mount)) {
continue;
}
- /* Skip swap and raw partition entries such as boot, recovery, etc */
- if (!strcmp(fstab->recs[i].fs_type, "swap") ||
- !strcmp(fstab->recs[i].fs_type, "emmc") ||
- !strcmp(fstab->recs[i].fs_type, "mtd")) {
+ // Skip swap and raw partition entries such as boot, recovery, etc.
+ if (current_entry.fs_type == "swap" || current_entry.fs_type == "emmc" ||
+ current_entry.fs_type == "mtd") {
continue;
}
- /* Skip mounting the root partition, as it will already have been mounted */
- if (!strcmp(fstab->recs[i].mount_point, "/") ||
- !strcmp(fstab->recs[i].mount_point, "/system")) {
- if ((fstab->recs[i].flags & MS_RDONLY) != 0) {
- fs_mgr_set_blk_ro(fstab->recs[i].blk_device);
+ // Skip mounting the root partition, as it will already have been mounted.
+ if (current_entry.mount_point == "/" || current_entry.mount_point == "/system") {
+ if ((current_entry.flags & MS_RDONLY) != 0) {
+ fs_mgr_set_blk_ro(current_entry.blk_device);
}
continue;
}
- /* Translate LABEL= file system labels into block devices */
- if (is_extfs(fstab->recs[i].fs_type)) {
- if (!TranslateExtLabels(&fstab->recs[i])) {
+ // Translate LABEL= file system labels into block devices.
+ if (is_extfs(current_entry.fs_type)) {
+ if (!TranslateExtLabels(¤t_entry)) {
LERROR << "Could not translate label to block device";
continue;
}
}
- if ((fstab->recs[i].fs_mgr_flags & MF_LOGICAL)) {
- if (!fs_mgr_update_logical_partition(&fstab->recs[i])) {
+ if (current_entry.fs_mgr_flags.logical) {
+ if (!fs_mgr_update_logical_partition(¤t_entry)) {
LERROR << "Could not set up logical partition, skipping!";
continue;
}
}
- if (!checkpoint_manager.Update(&fstab->recs[i])) {
+ if (!checkpoint_manager.Update(¤t_entry)) {
continue;
}
- if (fstab->recs[i].fs_mgr_flags & MF_WAIT &&
- !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) {
- LERROR << "Skipping '" << fstab->recs[i].blk_device << "' during mount_all";
+ if (current_entry.fs_mgr_flags.wait &&
+ !fs_mgr_wait_for_file(current_entry.blk_device, 20s)) {
+ LERROR << "Skipping '" << current_entry.blk_device << "' during mount_all";
continue;
}
- if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
+ if (current_entry.fs_mgr_flags.avb) {
if (!avb_handle) {
avb_handle = AvbHandle::Open();
if (!avb_handle) {
@@ -1047,15 +1025,15 @@
return FS_MGR_MNTALL_FAIL;
}
}
- if (avb_handle->SetUpAvbHashtree(&fstab->recs[i], true /* wait_for_verity_dev */) ==
+ if (avb_handle->SetUpAvbHashtree(¤t_entry, true /* wait_for_verity_dev */) ==
AvbHashtreeResult::kFail) {
- LERROR << "Failed to set up AVB on partition: "
- << fstab->recs[i].mount_point << ", skipping!";
- /* Skips mounting the device. */
+ LERROR << "Failed to set up AVB on partition: " << current_entry.mount_point
+ << ", skipping!";
+ // Skips mounting the device.
continue;
}
- } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY)) {
- int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
+ } else if ((current_entry.fs_mgr_flags.verify)) {
+ int rc = fs_mgr_setup_verity(¤t_entry, true);
if (__android_log_is_debuggable() &&
(rc == FS_MGR_SETUP_VERITY_DISABLED ||
rc == FS_MGR_SETUP_VERITY_SKIPPED)) {
@@ -1068,17 +1046,19 @@
int last_idx_inspected;
int top_idx = i;
+ int attempted_idx = -1;
- mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx);
+ bool mret = mount_with_alternatives(*fstab, i, &last_idx_inspected, &attempted_idx);
+ auto& attempted_entry = (*fstab)[attempted_idx];
i = last_idx_inspected;
- mount_errno = errno;
+ int mount_errno = errno;
- /* Deal with encryptability. */
- if (!mret) {
- int status = handle_encryptable(&fstab->recs[attempted_idx]);
+ // Handle success and deal with encryptability.
+ if (mret) {
+ int status = handle_encryptable(attempted_entry);
if (status == FS_MGR_MNTALL_FAIL) {
- /* Fatal error - no point continuing */
+ // Fatal error - no point continuing.
return status;
}
@@ -1089,50 +1069,45 @@
}
encryptable = status;
if (status == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
- if (!call_vdc(
- {"cryptfs", "encryptFstab", fstab->recs[attempted_idx].mount_point})) {
+ if (!call_vdc({"cryptfs", "encryptFstab", attempted_entry.mount_point})) {
LERROR << "Encryption failed";
return FS_MGR_MNTALL_FAIL;
}
}
}
- /* Success! Go get the next one */
+ // Success! Go get the next one.
continue;
}
- bool wiped = partition_wiped(fstab->recs[top_idx].blk_device);
+ // Mounting failed, understand why and retry.
+ bool wiped = partition_wiped(current_entry.blk_device.c_str());
bool crypt_footer = false;
- if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
- fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) {
- /* top_idx and attempted_idx point at the same partition, but sometimes
- * at two different lines in the fstab. Use the top one for formatting
- * as that is the preferred one.
- */
- LERROR << __FUNCTION__ << "(): " << realpath(fstab->recs[top_idx].blk_device)
- << " is wiped and " << fstab->recs[top_idx].mount_point << " "
- << fstab->recs[top_idx].fs_type << " is formattable. Format it.";
+ if (mount_errno != EBUSY && mount_errno != EACCES &&
+ current_entry.fs_mgr_flags.formattable && wiped) {
+ // current_entry and attempted_entry point at the same partition, but sometimes
+ // at two different lines in the fstab. Use current_entry for formatting
+ // as that is the preferred one.
+ LERROR << __FUNCTION__ << "(): " << realpath(current_entry.blk_device)
+ << " is wiped and " << current_entry.mount_point << " " << current_entry.fs_type
+ << " is formattable. Format it.";
- checkpoint_manager.Revert(&fstab->recs[top_idx]);
+ checkpoint_manager.Revert(¤t_entry);
- if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
- strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
+ if (current_entry.is_encryptable() && current_entry.key_loc != KEY_IN_FOOTER) {
unique_fd fd(TEMP_FAILURE_RETRY(
- open(fstab->recs[top_idx].key_loc, O_WRONLY | O_CLOEXEC)));
+ open(current_entry.key_loc.c_str(), O_WRONLY | O_CLOEXEC)));
if (fd >= 0) {
- LINFO << __FUNCTION__ << "(): also wipe "
- << fstab->recs[top_idx].key_loc;
+ LINFO << __FUNCTION__ << "(): also wipe " << current_entry.key_loc;
wipe_block_device(fd, get_file_size(fd));
} else {
- PERROR << __FUNCTION__ << "(): "
- << fstab->recs[top_idx].key_loc << " wouldn't open";
+ PERROR << __FUNCTION__ << "(): " << current_entry.key_loc << " wouldn't open";
}
- } else if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
- !strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
+ } else if (current_entry.is_encryptable() && current_entry.key_loc == KEY_IN_FOOTER) {
crypt_footer = true;
}
- if (fs_mgr_do_format(&fstab->recs[top_idx], crypt_footer) == 0) {
- /* Let's replay the mount actions. */
+ if (fs_mgr_do_format(current_entry, crypt_footer) == 0) {
+ // Let's replay the mount actions.
i = top_idx - 1;
continue;
} else {
@@ -1143,35 +1118,29 @@
}
}
- /* mount(2) returned an error, handle the encryptable/formattable case */
- if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
- fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) {
+ // mount(2) returned an error, handle the encryptable/formattable case.
+ if (mount_errno != EBUSY && mount_errno != EACCES && attempted_entry.is_encryptable()) {
if (wiped) {
- LERROR << __FUNCTION__ << "(): "
- << fstab->recs[attempted_idx].blk_device
- << " is wiped and "
- << fstab->recs[attempted_idx].mount_point << " "
- << fstab->recs[attempted_idx].fs_type
+ LERROR << __FUNCTION__ << "(): " << attempted_entry.blk_device << " is wiped and "
+ << attempted_entry.mount_point << " " << attempted_entry.fs_type
<< " is encryptable. Suggest recovery...";
encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY;
continue;
} else {
- /* Need to mount a tmpfs at this mountpoint for now, and set
- * properties that vold will query later for decrypting
- */
+ // Need to mount a tmpfs at this mountpoint for now, and set
+ // properties that vold will query later for decrypting
LERROR << __FUNCTION__ << "(): possibly an encryptable blkdev "
- << fstab->recs[attempted_idx].blk_device
- << " for mount " << fstab->recs[attempted_idx].mount_point
- << " type " << fstab->recs[attempted_idx].fs_type;
- if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) {
+ << attempted_entry.blk_device << " for mount " << attempted_entry.mount_point
+ << " type " << attempted_entry.fs_type;
+ if (fs_mgr_do_tmpfs_mount(attempted_entry.mount_point.c_str()) < 0) {
++error_count;
continue;
}
}
encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
- } else if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
- should_use_metadata_encryption(&fstab->recs[attempted_idx])) {
- if (!call_vdc({"cryptfs", "mountFstab", fstab->recs[attempted_idx].mount_point})) {
+ } else if (mount_errno != EBUSY && mount_errno != EACCES &&
+ should_use_metadata_encryption(attempted_entry)) {
+ if (!call_vdc({"cryptfs", "mountFstab", attempted_entry.mount_point})) {
++error_count;
}
encryptable = FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED;
@@ -1179,18 +1148,18 @@
} else {
// fs_options might be null so we cannot use PERROR << directly.
// Use StringPrintf to output "(null)" instead.
- if (fs_mgr_is_nofail(&fstab->recs[attempted_idx])) {
+ if (attempted_entry.fs_mgr_flags.no_fail) {
PERROR << android::base::StringPrintf(
- "Ignoring failure to mount an un-encryptable or wiped "
- "partition on %s at %s options: %s",
- fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
- fstab->recs[attempted_idx].fs_options);
+ "Ignoring failure to mount an un-encryptable or wiped "
+ "partition on %s at %s options: %s",
+ attempted_entry.blk_device.c_str(), attempted_entry.mount_point.c_str(),
+ attempted_entry.fs_options.c_str());
} else {
PERROR << android::base::StringPrintf(
- "Failed to mount an un-encryptable or wiped partition "
- "on %s at %s options: %s",
- fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
- fstab->recs[attempted_idx].fs_options);
+ "Failed to mount an un-encryptable or wiped partition "
+ "on %s at %s options: %s",
+ attempted_entry.blk_device.c_str(), attempted_entry.mount_point.c_str(),
+ attempted_entry.fs_options.c_str());
++error_count;
}
continue;
@@ -1208,20 +1177,13 @@
}
}
-/* wrapper to __mount() and expects a fully prepared fstab_rec,
- * unlike fs_mgr_do_mount which does more things with avb / verity
- * etc.
- */
-int fs_mgr_do_mount_one(struct fstab_rec *rec)
-{
- if (!rec) {
- return FS_MGR_DOMNT_FAILED;
- }
-
+// wrapper to __mount() and expects a fully prepared fstab_rec,
+// unlike fs_mgr_do_mount which does more things with avb / verity etc.
+int fs_mgr_do_mount_one(const FstabEntry& entry) {
// Run fsck if needed
- prepare_fs_for_mount(rec->blk_device, rec);
+ prepare_fs_for_mount(entry.blk_device, entry);
- int ret = __mount(rec->blk_device, rec->mount_point, rec);
+ int ret = __mount(entry.blk_device, entry.mount_point, entry);
if (ret) {
ret = (errno == EBUSY) ? FS_MGR_DOMNT_BUSY : FS_MGR_DOMNT_FAILED;
}
@@ -1229,17 +1191,26 @@
return ret;
}
-/* If tmp_mount_point is non-null, mount the filesystem there. This is for the
- * tmp mount we do to check the user password
- * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
- * in turn, and stop on 1st success, or no more match.
- */
-static int fs_mgr_do_mount_helper(fstab* fstab, const char* n_name, char* n_blk_device,
- char* tmp_mount_point, int needs_checkpoint) {
- int i = 0;
+int fs_mgr_do_mount_one(struct fstab_rec* rec) {
+ if (!rec) {
+ return FS_MGR_DOMNT_FAILED;
+ }
+
+ auto entry = FstabRecToFstabEntry(rec);
+
+ return fs_mgr_do_mount_one(entry);
+}
+
+// If tmp_mount_point is non-null, mount the filesystem there. This is for the
+// tmp mount we do to check the user password
+// If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
+// in turn, and stop on 1st success, or no more match.
+static int fs_mgr_do_mount_helper(Fstab* fstab, const std::string& n_name,
+ const std::string& n_blk_device, const char* tmp_mount_point,
+ int needs_checkpoint) {
int mount_errors = 0;
int first_mount_errno = 0;
- char* mount_point;
+ std::string mount_point;
CheckpointManager checkpoint_manager(needs_checkpoint);
AvbUniquePtr avb_handle(nullptr);
@@ -1247,42 +1218,41 @@
return FS_MGR_DOMNT_FAILED;
}
- for (i = 0; i < fstab->num_entries; i++) {
- if (!fs_match(fstab->recs[i].mount_point, n_name)) {
+ for (auto& fstab_entry : *fstab) {
+ if (!fs_match(fstab_entry.mount_point, n_name)) {
continue;
}
- /* We found our match */
- /* If this swap or a raw partition, report an error */
- if (!strcmp(fstab->recs[i].fs_type, "swap") ||
- !strcmp(fstab->recs[i].fs_type, "emmc") ||
- !strcmp(fstab->recs[i].fs_type, "mtd")) {
- LERROR << "Cannot mount filesystem of type "
- << fstab->recs[i].fs_type << " on " << n_blk_device;
+ // We found our match.
+ // If this swap or a raw partition, report an error.
+ if (fstab_entry.fs_type == "swap" || fstab_entry.fs_type == "emmc" ||
+ fstab_entry.fs_type == "mtd") {
+ LERROR << "Cannot mount filesystem of type " << fstab_entry.fs_type << " on "
+ << n_blk_device;
return FS_MGR_DOMNT_FAILED;
}
- if ((fstab->recs[i].fs_mgr_flags & MF_LOGICAL)) {
- if (!fs_mgr_update_logical_partition(&fstab->recs[i])) {
+ if (fstab_entry.fs_mgr_flags.logical) {
+ if (!fs_mgr_update_logical_partition(&fstab_entry)) {
LERROR << "Could not set up logical partition, skipping!";
continue;
}
}
- if (!checkpoint_manager.Update(&fstab->recs[i])) {
+ if (!checkpoint_manager.Update(&fstab_entry)) {
LERROR << "Could not set up checkpoint partition, skipping!";
continue;
}
- /* First check the filesystem if requested */
- if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(n_blk_device, 20s)) {
+ // First check the filesystem if requested.
+ if (fstab_entry.fs_mgr_flags.wait && !fs_mgr_wait_for_file(n_blk_device, 20s)) {
LERROR << "Skipping mounting '" << n_blk_device << "'";
continue;
}
- int fs_stat = prepare_fs_for_mount(n_blk_device, &fstab->recs[i]);
+ int fs_stat = prepare_fs_for_mount(n_blk_device, fstab_entry);
- if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
+ if (fstab_entry.fs_mgr_flags.avb) {
if (!avb_handle) {
avb_handle = AvbHandle::Open();
if (!avb_handle) {
@@ -1290,15 +1260,15 @@
return FS_MGR_DOMNT_FAILED;
}
}
- if (avb_handle->SetUpAvbHashtree(&fstab->recs[i], true /* wait_for_verity_dev */) ==
+ if (avb_handle->SetUpAvbHashtree(&fstab_entry, true /* wait_for_verity_dev */) ==
AvbHashtreeResult::kFail) {
- LERROR << "Failed to set up AVB on partition: "
- << fstab->recs[i].mount_point << ", skipping!";
- /* Skips mounting the device. */
+ LERROR << "Failed to set up AVB on partition: " << fstab_entry.mount_point
+ << ", skipping!";
+ // Skips mounting the device.
continue;
}
- } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY)) {
- int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
+ } else if (fstab_entry.fs_mgr_flags.verify) {
+ int rc = fs_mgr_setup_verity(&fstab_entry, true);
if (__android_log_is_debuggable() &&
(rc == FS_MGR_SETUP_VERITY_DISABLED ||
rc == FS_MGR_SETUP_VERITY_SKIPPED)) {
@@ -1309,15 +1279,15 @@
}
}
- /* Now mount it where requested */
+ // Now mount it where requested */
if (tmp_mount_point) {
mount_point = tmp_mount_point;
} else {
- mount_point = fstab->recs[i].mount_point;
+ mount_point = fstab_entry.mount_point;
}
int retry_count = 2;
while (retry_count-- > 0) {
- if (!__mount(n_blk_device, mount_point, &fstab->recs[i])) {
+ if (!__mount(n_blk_device, mount_point, fstab_entry)) {
fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
return FS_MGR_DOMNT_SUCCESS;
} else {
@@ -1326,10 +1296,10 @@
mount_errors++;
fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
// try again after fsck
- check_fs(n_blk_device, fstab->recs[i].fs_type, fstab->recs[i].mount_point, &fs_stat);
+ check_fs(n_blk_device, fstab_entry.fs_type, fstab_entry.mount_point, &fs_stat);
}
}
- log_fs_stat(fstab->recs[i].blk_device, fs_stat);
+ log_fs_stat(fstab_entry.blk_device, fs_stat);
}
// Reach here means the mount attempt fails.
@@ -1337,19 +1307,22 @@
PERROR << "Cannot mount filesystem on " << n_blk_device << " at " << mount_point;
if (first_mount_errno == EBUSY) return FS_MGR_DOMNT_BUSY;
} else {
- /* We didn't find a match, say so and return an error */
+ // We didn't find a match, say so and return an error.
LERROR << "Cannot find mount point " << n_name << " in fstab";
}
return FS_MGR_DOMNT_FAILED;
}
int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point) {
- return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1);
+ auto new_fstab = LegacyFstabToFstab(fstab);
+ return fs_mgr_do_mount_helper(&new_fstab, n_name, n_blk_device, tmp_mount_point, -1);
}
int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
bool needs_checkpoint) {
- return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_checkpoint);
+ auto new_fstab = LegacyFstabToFstab(fstab);
+ return fs_mgr_do_mount_helper(&new_fstab, n_name, n_blk_device, tmp_mount_point,
+ needs_checkpoint);
}
/*
@@ -1492,23 +1465,22 @@
* logging mode, in which case return that */
*mode = VERITY_MODE_DEFAULT;
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- if (!fstab) {
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
LERROR << "Failed to read default fstab";
return false;
}
- for (int i = 0; i < fstab->num_entries; i++) {
- if (fs_mgr_is_avb(&fstab->recs[i])) {
+ for (const auto& entry : fstab) {
+ if (entry.fs_mgr_flags.avb) {
*mode = VERITY_MODE_RESTART; // avb only supports restart mode.
break;
- } else if (!fs_mgr_is_verified(&fstab->recs[i])) {
+ } else if (!entry.fs_mgr_flags.verify) {
continue;
}
int current;
- if (load_verity_state(&fstab->recs[i], ¤t) < 0) {
+ if (load_verity_state(entry, ¤t) < 0) {
continue;
}
if (current != VERITY_MODE_DEFAULT) {
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index 737deca..1a0e7ab 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -120,20 +120,21 @@
LOG_KLOG, true, nullptr, nullptr, 0);
}
-int fs_mgr_do_format(struct fstab_rec *fstab, bool crypt_footer)
-{
- int rc = -EINVAL;
+int fs_mgr_do_format(const FstabEntry& entry, bool crypt_footer) {
+ LERROR << __FUNCTION__ << ": Format " << entry.blk_device << " as '" << entry.fs_type << "'";
- LERROR << __FUNCTION__ << ": Format " << fstab->blk_device
- << " as '" << fstab->fs_type << "'";
-
- if (!strncmp(fstab->fs_type, "f2fs", 4)) {
- rc = format_f2fs(fstab->blk_device, fstab->length, crypt_footer);
- } else if (!strncmp(fstab->fs_type, "ext4", 4)) {
- rc = format_ext4(fstab->blk_device, fstab->mount_point, crypt_footer);
+ if (entry.fs_type == "f2fs") {
+ return format_f2fs(entry.blk_device, entry.length, crypt_footer);
+ } else if (entry.fs_type == "ext4") {
+ return format_ext4(entry.blk_device, entry.mount_point, crypt_footer);
} else {
- LERROR << "File system type '" << fstab->fs_type << "' is not supported";
+ LERROR << "File system type '" << entry.fs_type << "' is not supported";
+ return -EINVAL;
}
+}
- return rc;
+int fs_mgr_do_format(struct fstab_rec* rec, bool crypt_footer) {
+ auto entry = FstabRecToFstabEntry(rec);
+
+ return fs_mgr_do_format(entry, crypt_footer);
}
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 0fde22e..f00983a 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -120,9 +120,11 @@
#define EM_ICE 2
#define EM_AES_256_CTS 3
#define EM_AES_256_HEH 4
+#define EM_ADIANTUM 5
static const struct flag_list file_contents_encryption_modes[] = {
{"aes-256-xts", EM_AES_256_XTS},
+ {"adiantum", EM_ADIANTUM},
{"software", EM_AES_256_XTS}, /* alias for backwards compatibility */
{"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
{0, 0},
@@ -131,6 +133,7 @@
static const struct flag_list file_names_encryption_modes[] = {
{"aes-256-cts", EM_AES_256_CTS},
{"aes-256-heh", EM_AES_256_HEH},
+ {"adiantum", EM_ADIANTUM},
{0, 0},
};
@@ -271,6 +274,8 @@
flag_vals->file_names_mode =
encryption_mode_to_flag(file_names_encryption_modes,
colon + 1, "file names");
+ } else if (flag_vals->file_contents_mode == EM_ADIANTUM) {
+ flag_vals->file_names_mode = EM_ADIANTUM;
} else {
flag_vals->file_names_mode = EM_AES_256_CTS;
}
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index d2d8dc1..ef043f9 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -70,19 +70,11 @@
#if ALLOW_ADBD_DISABLE_VERITY == 0 // If we are a user build, provide stubs
-bool fs_mgr_overlayfs_mount_all(fstab*) {
+bool fs_mgr_overlayfs_mount_all(Fstab*) {
return false;
}
-bool fs_mgr_overlayfs_mount_all(const std::vector<fstab_rec*>&) {
- return false;
-}
-
-std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab*) {
- return {};
-}
-
-std::vector<std::string> fs_mgr_overlayfs_required_devices(const std::vector<fstab_rec*>&) {
+std::vector<std::string> fs_mgr_overlayfs_required_devices(Fstab*) {
return {};
}
@@ -131,28 +123,28 @@
// At less than 1% free space return value of false,
// means we will try to wrap with overlayfs.
-bool fs_mgr_filesystem_has_space(const char* mount_point) {
+bool fs_mgr_filesystem_has_space(const std::string& mount_point) {
// If we have access issues to find out space remaining, return true
// to prevent us trying to override with overlayfs.
struct statvfs vst;
- if (statvfs(mount_point, &vst)) return true;
+ if (statvfs(mount_point.c_str(), &vst)) return true;
static constexpr int kPercentThreshold = 1; // 1%
return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100));
}
-bool fs_mgr_overlayfs_enabled(struct fstab_rec* fsrec) {
+bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
// readonly filesystem, can not be mount -o remount,rw
// if squashfs or if free space is (near) zero making such a remount
// virtually useless, or if there are shared blocks that prevent remount,rw
- if (("squashfs"s == fsrec->fs_type) || !fs_mgr_filesystem_has_space(fsrec->mount_point)) {
+ if ("squashfs" == entry->fs_type || !fs_mgr_filesystem_has_space(entry->mount_point)) {
return true;
}
- if (fs_mgr_is_logical(fsrec)) {
- fs_mgr_update_logical_partition(fsrec);
+ if (entry->fs_mgr_flags.logical) {
+ fs_mgr_update_logical_partition(entry);
}
- return fs_mgr_has_shared_blocks(fsrec->mount_point, fsrec->blk_device);
+ return fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device);
}
bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) {
@@ -250,22 +242,16 @@
}
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true) {
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab("/proc/mounts"),
- fs_mgr_free_fstab);
- if (!fstab) return false;
+ Fstab fstab;
+ if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
+ return false;
+ }
const auto lowerdir = kLowerdirOption + mount_point;
- for (auto i = 0; i < fstab->num_entries; ++i) {
- const auto fsrec = &fstab->recs[i];
- const auto fs_type = fsrec->fs_type;
- if (!fs_type) continue;
- if (overlay_only && ("overlay"s != fs_type) && ("overlayfs"s != fs_type)) continue;
- auto fsrec_mount_point = fsrec->mount_point;
- if (!fsrec_mount_point) continue;
- if (mount_point != fsrec_mount_point) continue;
+ for (const auto& entry : fstab) {
+ if (overlay_only && "overlay" != entry.fs_type && "overlayfs" != entry.fs_type) continue;
+ if (mount_point != entry.mount_point) continue;
if (!overlay_only) return true;
- const auto fs_options = fsrec->fs_options;
- if (!fs_options) continue;
- const auto options = android::base::Split(fs_options, ",");
+ const auto options = android::base::Split(entry.fs_options, ",");
for (const auto& opt : options) {
if (opt == lowerdir) {
return true;
@@ -282,28 +268,20 @@
return ret;
}
-bool fs_mgr_wants_overlayfs(fstab_rec* fsrec) {
- if (!fsrec) return false;
-
- auto fsrec_mount_point = fsrec->mount_point;
- if (!fsrec_mount_point || !fsrec_mount_point[0]) return false;
- if (!fsrec->blk_device) return false;
-
- if (!fsrec->fs_type) return false;
-
+bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
// Don't check entries that are managed by vold.
- if (fsrec->fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) return false;
+ if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
// Only concerned with readonly partitions.
- if (!(fsrec->flags & MS_RDONLY)) return false;
+ if (!(entry->flags & MS_RDONLY)) return false;
// If unbindable, do not allow overlayfs as this could expose us to
// security issues. On Android, this could also be used to turn off
// the ability to overlay an otherwise acceptable filesystem since
// /system and /vendor are never bound(sic) to.
- if (fsrec->flags & MS_UNBINDABLE) return false;
+ if (entry->flags & MS_UNBINDABLE) return false;
- if (!fs_mgr_overlayfs_enabled(fsrec)) return false;
+ if (!fs_mgr_overlayfs_enabled(entry)) return false;
return true;
}
@@ -391,11 +369,11 @@
return kPhysicalDevice + fs_mgr_get_super_partition_name(slot_number);
}
-bool fs_mgr_overlayfs_has_logical(const fstab* fstab) {
- if (!fstab) return false;
- for (auto i = 0; i < fstab->num_entries; i++) {
- const auto fsrec = &fstab->recs[i];
- if (fs_mgr_is_logical(fsrec)) return true;
+bool fs_mgr_overlayfs_has_logical(const Fstab& fstab) {
+ for (const auto& entry : fstab) {
+ if (entry.fs_mgr_flags.logical) {
+ return true;
+ }
}
return false;
}
@@ -521,7 +499,7 @@
// hijack __mount() report format to help triage
auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay";
const auto opt_list = android::base::Split(options, ",");
- for (const auto opt : opt_list) {
+ for (const auto& opt : opt_list) {
if (android::base::StartsWith(opt, kUpperdirOption)) {
report = report + "," + opt;
break;
@@ -540,15 +518,12 @@
}
}
-std::vector<std::string> fs_mgr_candidate_list(fstab* fstab, const char* mount_point = nullptr) {
+std::vector<std::string> fs_mgr_candidate_list(Fstab* fstab, const char* mount_point = nullptr) {
std::vector<std::string> mounts;
- if (!fstab) return mounts;
-
auto verity = fs_mgr_overlayfs_verity_enabled_list();
- for (auto i = 0; i < fstab->num_entries; i++) {
- const auto fsrec = &fstab->recs[i];
- if (!fs_mgr_wants_overlayfs(fsrec)) continue;
- std::string new_mount_point(fs_mgr_mount_point(fsrec->mount_point));
+ for (auto& entry : *fstab) {
+ if (!fs_mgr_wants_overlayfs(&entry)) continue;
+ std::string new_mount_point(fs_mgr_mount_point(entry.mount_point.c_str()));
if (mount_point && (new_mount_point != mount_point)) continue;
if (std::find(verity.begin(), verity.end(), android::base::Basename(new_mount_point)) !=
verity.end()) {
@@ -580,10 +555,9 @@
if (std::find(verity.begin(), verity.end(), "system") != verity.end()) return mounts;
// confirm that fstab is missing system
- if (fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), "/")) {
- return mounts;
- }
- if (fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), "/system")) {
+ if (std::find_if(fstab->begin(), fstab->end(), [](const auto& entry) {
+ return entry.mount_point == "/" || entry.mount_point == "/system ";
+ }) != fstab->end()) {
return mounts;
}
@@ -605,26 +579,20 @@
PERROR << "create " << kScratchMountPoint;
}
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> local_fstab(
- static_cast<fstab*>(calloc(1, sizeof(fstab))), fs_mgr_free_fstab);
- auto fsrec = static_cast<fstab_rec*>(calloc(1, sizeof(fstab_rec)));
- local_fstab->num_entries = 1;
- local_fstab->recs = fsrec;
- fsrec->blk_device = strdup(device_path.c_str());
- fsrec->mount_point = strdup(kScratchMountPoint.c_str());
- fsrec->fs_type = strdup(mnt_type.c_str());
- fsrec->flags = MS_RELATIME;
- fsrec->fs_options = strdup("");
+ FstabEntry entry;
+ entry.blk_device = device_path;
+ entry.mount_point = kScratchMountPoint;
+ entry.fs_type = mnt_type;
+ entry.flags = MS_RELATIME;
auto save_errno = errno;
- auto mounted = fs_mgr_do_mount_one(fsrec) == 0;
+ auto mounted = fs_mgr_do_mount_one(entry) == 0;
if (!mounted) {
- free(fsrec->fs_type);
if (mnt_type == "f2fs") {
- fsrec->fs_type = strdup("ext4");
+ entry.fs_type = "ext4";
} else {
- fsrec->fs_type = strdup("f2fs");
+ entry.fs_type = "f2fs";
}
- mounted = fs_mgr_do_mount_one(fsrec) == 0;
+ mounted = fs_mgr_do_mount_one(entry) == 0;
if (!mounted) save_errno = errno;
}
setfscreatecon(nullptr);
@@ -681,7 +649,7 @@
return true;
}
-bool fs_mgr_overlayfs_create_scratch(const fstab* fstab, std::string* scratch_device,
+bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_device,
bool* partition_exists, bool* change) {
*scratch_device = fs_mgr_overlayfs_scratch_device();
*partition_exists = fs_mgr_rw_access(*scratch_device);
@@ -765,7 +733,7 @@
}
// Create and mount kScratchMountPoint storage if we have logical partitions
-bool fs_mgr_overlayfs_setup_scratch(const fstab* fstab, bool* change) {
+bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab, bool* change) {
if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
std::string scratch_device;
@@ -805,20 +773,20 @@
return builder->FindPartition(android::base::Basename(kScratchMountPoint)) != nullptr;
}
-bool fs_mgr_overlayfs_invalid(const fstab* fstab) {
+bool fs_mgr_overlayfs_invalid() {
if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return true;
// in recovery or fastbootd mode, not allowed!
if (fs_mgr_access("/system/bin/recovery")) return true;
- return !fstab;
+ return false;
}
} // namespace
-bool fs_mgr_overlayfs_mount_all(fstab* fstab) {
+bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
auto ret = false;
- if (fs_mgr_overlayfs_invalid(fstab)) return ret;
+ if (fs_mgr_overlayfs_invalid()) return ret;
auto scratch_can_be_mounted = true;
for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
@@ -839,17 +807,12 @@
return ret;
}
-bool fs_mgr_overlayfs_mount_all(const std::vector<fstab_rec*>& fsrecs) {
- std::vector<fstab_rec> recs;
- for (const auto& rec : fsrecs) recs.push_back(*rec);
- fstab fstab = {static_cast<int>(fsrecs.size()), &recs[0]};
- return fs_mgr_overlayfs_mount_all(&fstab);
-}
+std::vector<std::string> fs_mgr_overlayfs_required_devices(Fstab* fstab) {
+ if (fs_mgr_overlayfs_invalid()) return {};
-std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab* fstab) {
- if (fs_mgr_overlayfs_invalid(fstab)) return {};
-
- if (fs_mgr_get_entry_for_mount_point(fstab, kScratchMountPoint)) {
+ if (std::find_if(fstab->begin(), fstab->end(), [](const auto& entry) {
+ return entry.mount_point == kScratchMountPoint;
+ }) != fstab->end()) {
return {};
}
@@ -862,13 +825,6 @@
return {};
}
-std::vector<std::string> fs_mgr_overlayfs_required_devices(const std::vector<fstab_rec*>& fsrecs) {
- std::vector<fstab_rec> recs;
- for (const auto& rec : fsrecs) recs.push_back(*rec);
- fstab fstab = {static_cast<int>(fsrecs.size()), &recs[0]};
- return fs_mgr_overlayfs_required_devices(&fstab);
-}
-
// Returns false if setup not permitted, errno set to last error.
// If something is altered, set *change.
bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* change) {
@@ -881,10 +837,11 @@
return ret;
}
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- if (!fstab) return ret;
- auto mounts = fs_mgr_candidate_list(fstab.get(), fs_mgr_mount_point(mount_point));
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
+ return false;
+ }
+ auto mounts = fs_mgr_candidate_list(&fstab, fs_mgr_mount_point(mount_point));
if (mounts.empty()) return ret;
std::string dir;
@@ -892,12 +849,16 @@
if (backing && backing[0] && (overlay_mount_point != backing)) continue;
if (overlay_mount_point == kScratchMountPoint) {
if (!fs_mgr_rw_access(fs_mgr_overlayfs_super_device(fs_mgr_overlayfs_slot_number())) ||
- !fs_mgr_overlayfs_has_logical(fstab.get())) {
+ !fs_mgr_overlayfs_has_logical(fstab)) {
continue;
}
- if (!fs_mgr_overlayfs_setup_scratch(fstab.get(), change)) continue;
+ if (!fs_mgr_overlayfs_setup_scratch(fstab, change)) continue;
} else {
- if (!fs_mgr_get_entry_for_mount_point(fstab.get(), overlay_mount_point)) continue;
+ if (std::find_if(fstab.begin(), fstab.end(), [&overlay_mount_point](const auto& entry) {
+ return entry.mount_point == overlay_mount_point;
+ }) == fstab.end()) {
+ continue;
+ }
}
dir = overlay_mount_point;
break;
@@ -959,10 +920,12 @@
bool fs_mgr_overlayfs_is_setup() {
if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- if (fs_mgr_overlayfs_invalid(fstab.get())) return false;
- for (const auto& mount_point : fs_mgr_candidate_list(fstab.get())) {
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
+ return false;
+ }
+ if (fs_mgr_overlayfs_invalid()) return false;
+ for (const auto& mount_point : fs_mgr_candidate_list(&fstab)) {
if (fs_mgr_overlayfs_already_mounted(mount_point)) return true;
}
return false;
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index faef34b..072da97 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -137,6 +137,6 @@
bool fs_mgr_is_device_unlocked();
const std::string& get_android_dt_dir();
bool is_dt_compatible();
-int load_verity_state(fstab_rec* fstab, int* mode);
+int load_verity_state(const FstabEntry& entry, int* mode);
#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/fs_mgr_slotselect.cpp b/fs_mgr/fs_mgr_slotselect.cpp
index 20d60ae..efc29bd 100644
--- a/fs_mgr/fs_mgr_slotselect.cpp
+++ b/fs_mgr/fs_mgr_slotselect.cpp
@@ -32,7 +32,6 @@
// Updates |fstab| for slot_suffix. Returns true on success, false on error.
bool fs_mgr_update_for_slotselect(Fstab* fstab) {
- int n;
std::string ab_suffix;
for (auto& entry : *fstab) {
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 2727a6d..9adf8cc 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -536,8 +536,7 @@
return 0;
}
-static int compare_last_signature(struct fstab_rec *fstab, int *match)
-{
+static int compare_last_signature(const FstabEntry& entry, int* match) {
char tag[METADATA_TAG_MAX_LENGTH + 1];
int fd = -1;
int rc = -1;
@@ -549,42 +548,40 @@
*match = 1;
- if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
- FEC_DEFAULT_ROOTS) == -1) {
- PERROR << "Failed to open '" << fstab->blk_device << "'";
+ if (fec_open(&f, entry.blk_device.c_str(), O_RDONLY, FEC_VERITY_DISABLE, FEC_DEFAULT_ROOTS) ==
+ -1) {
+ PERROR << "Failed to open '" << entry.blk_device << "'";
return rc;
}
// read verity metadata
if (fec_verity_get_metadata(f, &verity) == -1) {
- PERROR << "Failed to get verity metadata '" << fstab->blk_device << "'";
+ PERROR << "Failed to get verity metadata '" << entry.blk_device << "'";
goto out;
}
SHA256(verity.signature, sizeof(verity.signature), curr);
- if (snprintf(tag, sizeof(tag), VERITY_LASTSIG_TAG "_%s",
- basename(fstab->mount_point)) >= (int)sizeof(tag)) {
- LERROR << "Metadata tag name too long for " << fstab->mount_point;
+ if (snprintf(tag, sizeof(tag), VERITY_LASTSIG_TAG "_%s", basename(entry.mount_point.c_str())) >=
+ (int)sizeof(tag)) {
+ LERROR << "Metadata tag name too long for " << entry.mount_point;
goto out;
}
- if (metadata_find(fstab->verity_loc, tag, SHA256_DIGEST_LENGTH,
- &offset) < 0) {
+ if (metadata_find(entry.verity_loc.c_str(), tag, SHA256_DIGEST_LENGTH, &offset) < 0) {
goto out;
}
- fd = TEMP_FAILURE_RETRY(open(fstab->verity_loc, O_RDWR | O_SYNC | O_CLOEXEC));
+ fd = TEMP_FAILURE_RETRY(open(entry.verity_loc.c_str(), O_RDWR | O_SYNC | O_CLOEXEC));
if (fd == -1) {
- PERROR << "Failed to open " << fstab->verity_loc;
+ PERROR << "Failed to open " << entry.verity_loc;
goto out;
}
- if (TEMP_FAILURE_RETRY(pread64(fd, prev, sizeof(prev),
- offset)) != sizeof(prev)) {
- PERROR << "Failed to read " << sizeof(prev) << " bytes from "
- << fstab->verity_loc << " offset " << offset;
+ if (TEMP_FAILURE_RETRY(pread64(fd, prev, sizeof(prev), offset)) != sizeof(prev)) {
+ PERROR << "Failed to read " << sizeof(prev) << " bytes from " << entry.verity_loc
+ << " offset " << offset;
goto out;
}
@@ -594,8 +591,8 @@
/* update current signature hash */
if (TEMP_FAILURE_RETRY(pwrite64(fd, curr, sizeof(curr),
offset)) != sizeof(curr)) {
- PERROR << "Failed to write " << sizeof(curr) << " bytes to "
- << fstab->verity_loc << " offset " << offset;
+ PERROR << "Failed to write " << sizeof(curr) << " bytes to " << entry.verity_loc
+ << " offset " << offset;
goto out;
}
}
@@ -607,28 +604,23 @@
return rc;
}
-static int get_verity_state_offset(struct fstab_rec *fstab, off64_t *offset)
-{
+static int get_verity_state_offset(const FstabEntry& entry, off64_t* offset) {
char tag[METADATA_TAG_MAX_LENGTH + 1];
- if (snprintf(tag, sizeof(tag), VERITY_STATE_TAG "_%s",
- basename(fstab->mount_point)) >= (int)sizeof(tag)) {
- LERROR << "Metadata tag name too long for " << fstab->mount_point;
+ if (snprintf(tag, sizeof(tag), VERITY_STATE_TAG "_%s", basename(entry.mount_point.c_str())) >=
+ (int)sizeof(tag)) {
+ LERROR << "Metadata tag name too long for " << entry.mount_point;
return -1;
}
- return metadata_find(fstab->verity_loc, tag, sizeof(struct verity_state),
- offset);
+ return metadata_find(entry.verity_loc.c_str(), tag, sizeof(struct verity_state), offset);
}
-int load_verity_state(struct fstab_rec* fstab, int* mode) {
- int match = 0;
- off64_t offset = 0;
-
- /* unless otherwise specified, use EIO mode */
+int load_verity_state(const FstabEntry& entry, int* mode) {
+ // unless otherwise specified, use EIO mode.
*mode = VERITY_MODE_EIO;
- /* use the kernel parameter if set */
+ // use the kernel parameter if set.
std::string veritymode;
if (fs_mgr_get_boot_config("veritymode", &veritymode)) {
if (veritymode == "enforcing") {
@@ -637,7 +629,8 @@
return 0;
}
- if (get_verity_state_offset(fstab, &offset) < 0) {
+ off64_t offset = 0;
+ if (get_verity_state_offset(entry, &offset) < 0) {
/* fall back to stateless behavior */
return 0;
}
@@ -645,16 +638,17 @@
if (was_verity_restart()) {
/* device was restarted after dm-verity detected a corrupted
* block, so use EIO mode */
- return write_verity_state(fstab->verity_loc, offset, *mode);
+ return write_verity_state(entry.verity_loc.c_str(), offset, *mode);
}
- if (!compare_last_signature(fstab, &match) && !match) {
+ int match = 0;
+ if (!compare_last_signature(entry, &match) && !match) {
/* partition has been reflashed, reset dm-verity state */
*mode = VERITY_MODE_DEFAULT;
- return write_verity_state(fstab->verity_loc, offset, *mode);
+ return write_verity_state(entry.verity_loc.c_str(), offset, *mode);
}
- return read_verity_state(fstab->verity_loc, offset, mode);
+ return read_verity_state(entry.verity_loc.c_str(), offset, mode);
}
// Update the verity table using the actual block device path.
@@ -716,8 +710,7 @@
// prepares the verity enabled (MF_VERIFY / MF_VERIFYATBOOT) fstab record for
// mount. The 'wait_for_verity_dev' parameter makes this function wait for the
// verity device to get created before return
-int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev)
-{
+int fs_mgr_setup_verity(FstabEntry* entry, bool wait_for_verity_dev) {
int retval = FS_MGR_SETUP_VERITY_FAIL;
int fd = -1;
std::string verity_blk_name;
@@ -725,20 +718,20 @@
struct fec_verity_metadata verity;
struct verity_table_params params = { .table = NULL };
- const std::string mount_point(basename(fstab->mount_point));
+ const std::string mount_point(basename(entry->mount_point.c_str()));
bool verified_at_boot = false;
android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
- if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
- FEC_DEFAULT_ROOTS) < 0) {
- PERROR << "Failed to open '" << fstab->blk_device << "'";
+ if (fec_open(&f, entry->blk_device.c_str(), O_RDONLY, FEC_VERITY_DISABLE, FEC_DEFAULT_ROOTS) <
+ 0) {
+ PERROR << "Failed to open '" << entry->blk_device << "'";
return retval;
}
// read verity metadata
if (fec_verity_get_metadata(f, &verity) < 0) {
- PERROR << "Failed to get verity metadata '" << fstab->blk_device << "'";
+ PERROR << "Failed to get verity metadata '" << entry->blk_device << "'";
// Allow verity disabled when the device is unlocked without metadata
if (fs_mgr_is_device_unlocked()) {
retval = FS_MGR_SETUP_VERITY_SKIPPED;
@@ -760,9 +753,9 @@
params.ecc.valid = false;
}
- params.ecc_dev = fstab->blk_device;
+ params.ecc_dev = entry->blk_device.c_str();
- if (load_verity_state(fstab, ¶ms.mode) < 0) {
+ if (load_verity_state(*entry, ¶ms.mode) < 0) {
/* if accessing or updating the state failed, switch to the default
* safe mode. This makes sure the device won't end up in an endless
* restart loop, and no corrupted data will be exposed to userspace
@@ -803,8 +796,8 @@
<< " (mode " << params.mode << ")";
// Update the verity params using the actual block device path
- update_verity_table_blk_device(fstab->blk_device, ¶ms.table,
- fstab->fs_mgr_flags & MF_SLOTSELECT);
+ update_verity_table_blk_device(entry->blk_device, ¶ms.table,
+ entry->fs_mgr_flags.slot_select);
// load the verity mapping table
if (load_verity_table(dm, mount_point, verity.data_size, ¶ms, format_verity_table) == 0) {
@@ -848,31 +841,29 @@
}
// mark the underlying block device as read-only
- fs_mgr_set_blk_ro(fstab->blk_device);
+ fs_mgr_set_blk_ro(entry->blk_device);
// Verify the entire partition in one go
// If there is an error, allow it to mount as a normal verity partition.
- if (fstab->fs_mgr_flags & MF_VERIFYATBOOT) {
- LINFO << "Verifying partition " << fstab->blk_device << " at boot";
+ if (entry->fs_mgr_flags.verify_at_boot) {
+ LINFO << "Verifying partition " << entry->blk_device << " at boot";
int err = read_partition(verity_blk_name.c_str(), verity.data_size);
if (!err) {
- LINFO << "Verified verity partition "
- << fstab->blk_device << " at boot";
+ LINFO << "Verified verity partition " << entry->blk_device << " at boot";
verified_at_boot = true;
}
}
// assign the new verity block device as the block device
if (!verified_at_boot) {
- free(fstab->blk_device);
- fstab->blk_device = strdup(verity_blk_name.c_str());
+ entry->blk_device = verity_blk_name;
} else if (!dm.DeleteDevice(mount_point)) {
LERROR << "Failed to remove verity device " << mount_point.c_str();
goto out;
}
// make sure we've set everything up properly
- if (wait_for_verity_dev && !fs_mgr_wait_for_file(fstab->blk_device, 1s)) {
+ if (wait_for_verity_dev && !fs_mgr_wait_for_file(entry->blk_device, 1s)) {
goto out;
}
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index c1dc731..814ba46 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -59,7 +59,8 @@
#define FS_MGR_MNTALL_DEV_NOT_ENCRYPTED 1
#define FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE 0
#define FS_MGR_MNTALL_FAIL (-1)
-int fs_mgr_mount_all(fstab* fstab, int mount_mode);
+// fs_mgr_mount_all() updates fstab entries that reference device-mapper.
+int fs_mgr_mount_all(Fstab* fstab, int mount_mode);
#define FS_MGR_DOMNT_FAILED (-1)
#define FS_MGR_DOMNT_BUSY (-2)
@@ -68,6 +69,7 @@
int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point);
int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
bool need_cp);
+int fs_mgr_do_mount_one(const FstabEntry& entry);
int fs_mgr_do_mount_one(fstab_rec* rec);
int fs_mgr_do_tmpfs_mount(const char *n_name);
fstab_rec const* fs_mgr_get_crypt_entry(fstab const* fstab);
@@ -76,15 +78,17 @@
bool fs_mgr_update_verity_state(
std::function<void(const std::string& mount_point, int mode)> callback);
bool fs_mgr_swapon_all(const Fstab& fstab);
+bool fs_mgr_update_logical_partition(FstabEntry* entry);
bool fs_mgr_update_logical_partition(struct fstab_rec* rec);
-int fs_mgr_do_format(fstab_rec* fstab, bool reserve_footer);
+int fs_mgr_do_format(const FstabEntry& entry, bool reserve_footer);
+int fs_mgr_do_format(fstab_rec* rec, bool reserve_footer);
#define FS_MGR_SETUP_VERITY_SKIPPED (-3)
#define FS_MGR_SETUP_VERITY_DISABLED (-2)
#define FS_MGR_SETUP_VERITY_FAIL (-1)
#define FS_MGR_SETUP_VERITY_SUCCESS 0
-int fs_mgr_setup_verity(fstab_rec* fstab, bool wait_for_verity_dev);
+int fs_mgr_setup_verity(FstabEntry* fstab, bool wait_for_verity_dev);
// Return the name of the super partition if it exists. If a slot number is
// specified, the super partition for the corresponding metadata slot will be
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index 0dd9121..4bf2238 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -21,10 +21,8 @@
#include <string>
#include <vector>
-bool fs_mgr_overlayfs_mount_all(fstab* fstab);
-bool fs_mgr_overlayfs_mount_all(const std::vector<fstab_rec*>& fstab);
-std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab* fstab);
-std::vector<std::string> fs_mgr_overlayfs_required_devices(const std::vector<fstab_rec*>& fstab);
+bool fs_mgr_overlayfs_mount_all(Fstab* fstab);
+std::vector<std::string> fs_mgr_overlayfs_required_devices(Fstab* fstab);
bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
bool* change = nullptr);
bool fs_mgr_overlayfs_teardown(const char* mount_point = nullptr, bool* change = nullptr);
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 4706028..26a1e5c 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -156,6 +156,7 @@
bool logical : 1;
bool checkpoint_blk : 1;
bool checkpoint_fs : 1;
+ bool first_stage_mount : 1;
};
} fs_mgr_flags;
diff --git a/fs_mgr/libfs_avb/fs_avb.cpp b/fs_mgr/libfs_avb/fs_avb.cpp
index c4accad..89c755e 100644
--- a/fs_mgr/libfs_avb/fs_avb.cpp
+++ b/fs_mgr/libfs_avb/fs_avb.cpp
@@ -265,7 +265,7 @@
return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target));
}
-static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry,
+static bool hashtree_dm_verity_setup(FstabEntry* fstab_entry,
const AvbHashtreeDescriptor& hashtree_desc,
const std::string& salt, const std::string& root_digest,
bool wait_for_verity_dev) {
@@ -278,7 +278,7 @@
}
table.set_readonly(true);
- const std::string mount_point(basename(fstab_entry->mount_point));
+ const std::string mount_point(basename(fstab_entry->mount_point.c_str()));
android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
if (!dm.CreateDevice(mount_point, table)) {
LERROR << "Couldn't create verity device!";
@@ -295,8 +295,7 @@
fs_mgr_set_blk_ro(fstab_entry->blk_device);
// Updates fstab_rec->blk_device to verity device name.
- free(fstab_entry->blk_device);
- fstab_entry->blk_device = strdup(dev_path.c_str());
+ fstab_entry->blk_device = dev_path;
// Makes sure we've set everything up properly.
if (wait_for_verity_dev && !fs_mgr_wait_for_file(dev_path, 1s)) {
@@ -449,8 +448,7 @@
return avb_handle;
}
-AvbHashtreeResult AvbHandle::SetUpAvbHashtree(struct fstab_rec* fstab_entry,
- bool wait_for_verity_dev) {
+AvbHashtreeResult AvbHandle::SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev) {
if (!fstab_entry || status_ == kAvbHandleUninitialized || !avb_slot_data_ ||
avb_slot_data_->num_vbmeta_images < 1) {
return AvbHashtreeResult::kFail;
@@ -464,13 +462,13 @@
// Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor
// to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix.
std::string partition_name;
- if (fstab_entry->fs_mgr_flags & MF_LOGICAL) {
+ if (fstab_entry->fs_mgr_flags.logical) {
partition_name = fstab_entry->logical_partition_name;
} else {
- partition_name = basename(fstab_entry->blk_device);
+ partition_name = basename(fstab_entry->blk_device.c_str());
}
- if (fstab_entry->fs_mgr_flags & MF_SLOTSELECT) {
+ if (fstab_entry->fs_mgr_flags.slot_select) {
auto ab_suffix = partition_name.rfind(fs_mgr_get_slot_suffix());
if (ab_suffix != std::string::npos) {
partition_name.erase(ab_suffix);
diff --git a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
index 9adab3d..08bdbdc 100644
--- a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
+++ b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
@@ -85,7 +85,7 @@
// failed to get the HASHTREE descriptor, runtime error when set up
// device-mapper, etc.
// - kDisabled: hashtree is disabled.
- AvbHashtreeResult SetUpAvbHashtree(fstab_rec* fstab_entry, bool wait_for_verity_dev);
+ AvbHashtreeResult SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev);
const std::string& avb_version() const { return avb_version_; }
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 699b9e7..07f9d66 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -606,14 +606,23 @@
}
uint64_t sectors = std::min(sectors_needed, region.length());
+ if (sectors < region.length()) {
+ const auto& block_device = block_devices_[region.device_index];
+ if (block_device.alignment) {
+ const uint64_t alignment = block_device.alignment / LP_SECTOR_SIZE;
+ sectors = AlignTo(sectors, alignment);
+ sectors = std::min(sectors, region.length());
+ }
+ }
CHECK(sectors % sectors_per_block == 0);
auto extent = std::make_unique<LinearExtent>(sectors, region.device_index, region.start);
new_extents.push_back(std::move(extent));
- sectors_needed -= sectors;
- if (!sectors_needed) {
+ if (sectors >= sectors_needed) {
+ sectors_needed = 0;
break;
}
+ sectors_needed -= sectors;
}
if (sectors_needed) {
LERROR << "Not enough free space to expand partition: " << partition->name();
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index 7833a25..3793964 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -209,8 +209,8 @@
ASSERT_TRUE(builder->ResizePartition(a, a->size() + 4096));
ASSERT_TRUE(builder->ResizePartition(b, b->size() + 4096));
}
- EXPECT_EQ(a->size(), 40960);
- EXPECT_EQ(b->size(), 40960);
+ EXPECT_EQ(a->size(), 7864320);
+ EXPECT_EQ(b->size(), 7864320);
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
@@ -218,7 +218,7 @@
// Check that each starting sector is aligned.
for (const auto& extent : exported->extents) {
ASSERT_EQ(extent.target_type, LP_TARGET_TYPE_LINEAR);
- EXPECT_EQ(extent.num_sectors, 8);
+ EXPECT_EQ(extent.num_sectors, 1536);
uint64_t lba = extent.target_data * LP_SECTOR_SIZE;
uint64_t aligned_lba = AlignTo(lba, device_info.alignment, device_info.alignment_offset);
@@ -645,7 +645,7 @@
EXPECT_EQ(metadata->extents[1].target_type, LP_TARGET_TYPE_LINEAR);
EXPECT_EQ(metadata->extents[1].target_data, 1472);
EXPECT_EQ(metadata->extents[1].target_source, 1);
- EXPECT_EQ(metadata->extents[2].num_sectors, 129088);
+ EXPECT_EQ(metadata->extents[2].num_sectors, 129600);
EXPECT_EQ(metadata->extents[2].target_type, LP_TARGET_TYPE_LINEAR);
EXPECT_EQ(metadata->extents[2].target_data, 1472);
EXPECT_EQ(metadata->extents[2].target_source, 2);
@@ -744,17 +744,41 @@
EXPECT_EQ(system_a->extents().size(), static_cast<size_t>(1));
EXPECT_EQ(system_b->extents().size(), static_cast<size_t>(1));
ASSERT_TRUE(builder->ResizePartition(system_b, 6_GiB));
- EXPECT_EQ(system_b->extents().size(), static_cast<size_t>(3));
+ EXPECT_EQ(system_b->extents().size(), static_cast<size_t>(2));
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
- ASSERT_EQ(exported->extents.size(), static_cast<size_t>(4));
+ ASSERT_EQ(exported->extents.size(), static_cast<size_t>(3));
EXPECT_EQ(exported->extents[0].target_data, 10487808);
- EXPECT_EQ(exported->extents[0].num_sectors, 4194304);
- EXPECT_EQ(exported->extents[1].target_data, 14682624);
- EXPECT_EQ(exported->extents[1].num_sectors, 6288896);
- EXPECT_EQ(exported->extents[2].target_data, 6292992);
- EXPECT_EQ(exported->extents[2].num_sectors, 2099712);
- EXPECT_EQ(exported->extents[3].target_data, 1536);
- EXPECT_EQ(exported->extents[3].num_sectors, 6291456);
+ EXPECT_EQ(exported->extents[0].num_sectors, 10483712);
+ EXPECT_EQ(exported->extents[1].target_data, 6292992);
+ EXPECT_EQ(exported->extents[1].num_sectors, 2099712);
+ EXPECT_EQ(exported->extents[2].target_data, 1536);
+ EXPECT_EQ(exported->extents[2].num_sectors, 6291456);
+}
+
+TEST_F(BuilderTest, PartialExtents) {
+ // super has a minimum extent size of 768KiB.
+ BlockDeviceInfo device_info("super", 1_GiB, 768 * 1024, 0, 4096);
+ auto builder = MetadataBuilder::New(device_info, 65536, 1);
+ ASSERT_NE(builder, nullptr);
+ Partition* system = builder->AddPartition("system", 0);
+ ASSERT_NE(system, nullptr);
+ Partition* vendor = builder->AddPartition("vendor", 0);
+ ASSERT_NE(vendor, nullptr);
+ ASSERT_TRUE(builder->ResizePartition(system, device_info.alignment + 4096));
+ ASSERT_TRUE(builder->ResizePartition(vendor, device_info.alignment));
+ ASSERT_EQ(system->size(), device_info.alignment * 2);
+ ASSERT_EQ(vendor->size(), device_info.alignment);
+
+ ASSERT_TRUE(builder->ResizePartition(system, device_info.alignment * 2));
+ ASSERT_EQ(system->extents().size(), static_cast<size_t>(1));
+
+ unique_ptr<LpMetadata> exported = builder->Export();
+ ASSERT_NE(exported, nullptr);
+ ASSERT_EQ(exported->extents.size(), static_cast<size_t>(2));
+ EXPECT_EQ(exported->extents[0].target_data, 1536);
+ EXPECT_EQ(exported->extents[0].num_sectors, 3072);
+ EXPECT_EQ(exported->extents[1].target_data, 4608);
+ EXPECT_EQ(exported->extents[1].num_sectors, 1536);
}
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index d8195ca..454258b 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -84,7 +84,6 @@
// with potentially invalid metadata, or random partition data with metadata.
static bool ValidateAndSerializeMetadata(const IPartitionOpener& opener, const LpMetadata& metadata,
const std::string& slot_suffix, std::string* blob) {
- const LpMetadataHeader& header = metadata.header;
const LpMetadataGeometry& geometry = metadata.geometry;
*blob = SerializeMetadata(metadata);
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 2bebe76..7fd4e27 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -473,9 +473,10 @@
// Only needed if someone explicitly changes the default log level in their init.rc.
android::base::ScopedLogSeverity info(android::base::INFO);
- struct fstab* fstab = fs_mgr_read_fstab(fstabfile);
- int child_ret = fs_mgr_mount_all(fstab, mount_mode);
- fs_mgr_free_fstab(fstab);
+ Fstab fstab;
+ ReadFstabFromFile(fstabfile, &fstab);
+
+ int child_ret = fs_mgr_mount_all(&fstab, mount_mode);
if (child_ret == -1) {
PLOG(ERROR) << "fs_mgr_mount_all returned an error";
}
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 6ae1123..f5b291e 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -70,7 +70,7 @@
bool InitRequiredDevices();
bool InitMappedDevice(const std::string& verity_device);
bool CreateLogicalPartitions();
- bool MountPartition(fstab_rec* fstab_rec);
+ bool MountPartition(FstabEntry* fstab_entry);
bool MountPartitions();
bool IsDmLinearEnabled();
bool GetDmLinearMetadataDevice();
@@ -80,13 +80,12 @@
// Pure virtual functions.
virtual bool GetDmVerityDevices() = 0;
- virtual bool SetUpDmVerity(fstab_rec* fstab_rec) = 0;
+ virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0;
bool need_dm_verity_;
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab_;
+ Fstab fstab_;
std::string lp_metadata_partition_;
- std::vector<fstab_rec*> mount_fstab_recs_;
std::set<std::string> required_devices_partition_names_;
std::string super_partition_name_;
std::unique_ptr<DeviceHandler> device_handler_;
@@ -100,7 +99,7 @@
protected:
bool GetDmVerityDevices() override;
- bool SetUpDmVerity(fstab_rec* fstab_rec) override;
+ bool SetUpDmVerity(FstabEntry* fstab_entry) override;
};
class FirstStageMountVBootV2 : public FirstStageMount {
@@ -112,7 +111,7 @@
protected:
bool GetDmVerityDevices() override;
- bool SetUpDmVerity(fstab_rec* fstab_rec) override;
+ bool SetUpDmVerity(FstabEntry* fstab_entry) override;
bool InitAvbHandle();
std::string device_tree_vbmeta_parts_;
@@ -131,29 +130,16 @@
// Class Definitions
// -----------------
-FirstStageMount::FirstStageMount()
- : need_dm_verity_(false),
- fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab),
- uevent_listener_(16 * 1024 * 1024) {
- // Stores fstab_->recs[] into mount_fstab_recs_ (vector<fstab_rec*>)
- // for easier manipulation later, e.g., range-base for loop.
- if (fstab_) {
- // DT Fstab predated having a first_stage_mount fs_mgr flag, so if it exists, we use it.
- for (int i = 0; i < fstab_->num_entries; i++) {
- mount_fstab_recs_.push_back(&fstab_->recs[i]);
- }
- } else {
- // Fstab found in first stage ramdisk, which should be a copy of the normal fstab.
- // Mounts intended for first stage are explicitly flagged as such.
- fstab_.reset(fs_mgr_read_fstab_default());
- if (fstab_) {
- for (int i = 0; i < fstab_->num_entries; i++) {
- if (fs_mgr_is_first_stage_mount(&fstab_->recs[i])) {
- mount_fstab_recs_.push_back(&fstab_->recs[i]);
- }
- }
+FirstStageMount::FirstStageMount() : need_dm_verity_(false), uevent_listener_(16 * 1024 * 1024) {
+ if (!ReadFstabFromDt(&fstab_)) {
+ if (ReadDefaultFstab(&fstab_)) {
+ fstab_.erase(std::remove_if(fstab_.begin(), fstab_.end(),
+ [](const auto& entry) {
+ return !entry.fs_mgr_flags.first_stage_mount;
+ }),
+ fstab_.end());
} else {
- LOG(INFO) << "Failed to read fstab from device tree";
+ LOG(INFO) << "Failed to fstab for first stage mount";
}
}
@@ -174,7 +160,7 @@
}
bool FirstStageMount::DoFirstStageMount() {
- if (!IsDmLinearEnabled() && mount_fstab_recs_.empty()) {
+ if (!IsDmLinearEnabled() && fstab_.empty()) {
// Nothing to mount.
LOG(INFO) << "First stage mount skipped (missing/incompatible/empty fstab in device tree)";
return true;
@@ -194,8 +180,8 @@
}
bool FirstStageMount::IsDmLinearEnabled() {
- for (auto fstab_rec : mount_fstab_recs_) {
- if (fs_mgr_is_logical(fstab_rec)) return true;
+ for (const auto& entry : fstab_) {
+ if (entry.fs_mgr_flags.logical) return true;
}
return false;
}
@@ -381,21 +367,21 @@
return true;
}
-bool FirstStageMount::MountPartition(fstab_rec* fstab_rec) {
- if (fs_mgr_is_logical(fstab_rec)) {
- if (!fs_mgr_update_logical_partition(fstab_rec)) {
+bool FirstStageMount::MountPartition(FstabEntry* fstab_entry) {
+ if (fstab_entry->fs_mgr_flags.logical) {
+ if (!fs_mgr_update_logical_partition(fstab_entry)) {
return false;
}
- if (!InitMappedDevice(fstab_rec->blk_device)) {
+ if (!InitMappedDevice(fstab_entry->blk_device)) {
return false;
}
}
- if (!SetUpDmVerity(fstab_rec)) {
- PLOG(ERROR) << "Failed to setup verity for '" << fstab_rec->mount_point << "'";
+ if (!SetUpDmVerity(fstab_entry)) {
+ PLOG(ERROR) << "Failed to setup verity for '" << fstab_entry->mount_point << "'";
return false;
}
- if (fs_mgr_do_mount_one(fstab_rec)) {
- PLOG(ERROR) << "Failed to mount '" << fstab_rec->mount_point << "'";
+ if (fs_mgr_do_mount_one(*fstab_entry)) {
+ PLOG(ERROR) << "Failed to mount '" << fstab_entry->mount_point << "'";
return false;
}
return true;
@@ -405,28 +391,28 @@
// If system is in the fstab then we're not a system-as-root device, and in
// this case, we mount system first then pivot to it. From that point on,
// we are effectively identical to a system-as-root device.
- auto system_partition =
- std::find_if(mount_fstab_recs_.begin(), mount_fstab_recs_.end(),
- [](const auto& rec) { return rec->mount_point == "/system"s; });
+ auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
+ return entry.mount_point == "/system";
+ });
- if (system_partition != mount_fstab_recs_.end()) {
- if (!MountPartition(*system_partition)) {
+ if (system_partition != fstab_.end()) {
+ if (!MountPartition(&(*system_partition))) {
return false;
}
- SwitchRoot((*system_partition)->mount_point);
+ SwitchRoot((*system_partition).mount_point);
- mount_fstab_recs_.erase(system_partition);
+ fstab_.erase(system_partition);
}
- for (auto fstab_rec : mount_fstab_recs_) {
- if (!MountPartition(fstab_rec) && !fs_mgr_is_nofail(fstab_rec)) {
+ for (auto& fstab_entry : fstab_) {
+ if (!MountPartition(&fstab_entry) && !fstab_entry.fs_mgr_flags.no_fail) {
return false;
}
}
// heads up for instantiating required device(s) for overlayfs logic
- const auto devices = fs_mgr_overlayfs_required_devices(mount_fstab_recs_);
+ const auto devices = fs_mgr_overlayfs_required_devices(&fstab_);
for (auto const& device : devices) {
if (android::base::StartsWith(device, "/dev/block/by-name/")) {
required_devices_partition_names_.emplace(basename(device.c_str()));
@@ -438,7 +424,7 @@
}
}
- fs_mgr_overlayfs_mount_all(mount_fstab_recs_);
+ fs_mgr_overlayfs_mount_all(&fstab_);
return true;
}
@@ -447,25 +433,25 @@
std::string verity_loc_device;
need_dm_verity_ = false;
- for (auto fstab_rec : mount_fstab_recs_) {
+ for (const auto& fstab_entry : fstab_) {
// Don't allow verifyatboot in the first stage.
- if (fs_mgr_is_verifyatboot(fstab_rec)) {
+ if (fstab_entry.fs_mgr_flags.verify_at_boot) {
LOG(ERROR) << "Partitions can't be verified at boot";
return false;
}
// Checks for verified partitions.
- if (fs_mgr_is_verified(fstab_rec)) {
+ if (fstab_entry.fs_mgr_flags.verify) {
need_dm_verity_ = true;
}
// Checks if verity metadata is on a separate partition. Note that it is
// not partition specific, so there must be only one additional partition
// that carries verity state.
- if (fstab_rec->verity_loc) {
+ if (!fstab_entry.verity_loc.empty()) {
if (verity_loc_device.empty()) {
- verity_loc_device = fstab_rec->verity_loc;
- } else if (verity_loc_device != fstab_rec->verity_loc) {
+ verity_loc_device = fstab_entry.verity_loc;
+ } else if (verity_loc_device != fstab_entry.verity_loc) {
LOG(ERROR) << "More than one verity_loc found: " << verity_loc_device << ", "
- << fstab_rec->verity_loc;
+ << fstab_entry.verity_loc;
return false;
}
}
@@ -473,9 +459,9 @@
// Includes the partition names of fstab records and verity_loc_device (if any).
// Notes that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used.
- for (auto fstab_rec : mount_fstab_recs_) {
- if (!fs_mgr_is_logical(fstab_rec)) {
- required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
+ for (const auto& fstab_entry : fstab_) {
+ if (!fstab_entry.fs_mgr_flags.logical) {
+ required_devices_partition_names_.emplace(basename(fstab_entry.blk_device.c_str()));
}
}
@@ -486,19 +472,19 @@
return true;
}
-bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) {
- if (fs_mgr_is_verified(fstab_rec)) {
- int ret = fs_mgr_setup_verity(fstab_rec, false /* wait_for_verity_dev */);
+bool FirstStageMountVBootV1::SetUpDmVerity(FstabEntry* fstab_entry) {
+ if (fstab_entry->fs_mgr_flags.verify) {
+ int ret = fs_mgr_setup_verity(fstab_entry, false /* wait_for_verity_dev */);
switch (ret) {
case FS_MGR_SETUP_VERITY_SKIPPED:
case FS_MGR_SETUP_VERITY_DISABLED:
- LOG(INFO) << "Verity disabled/skipped for '" << fstab_rec->mount_point << "'";
+ LOG(INFO) << "Verity disabled/skipped for '" << fstab_entry->mount_point << "'";
return true;
case FS_MGR_SETUP_VERITY_SUCCESS:
// The exact block device name (fstab_rec->blk_device) is changed to
// "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init
// first stage.
- return InitMappedDevice(fstab_rec->blk_device);
+ return InitMappedDevice(fstab_entry->blk_device);
default:
return false;
}
@@ -531,15 +517,15 @@
std::set<std::string> logical_partitions;
// fstab_rec->blk_device has A/B suffix.
- for (auto fstab_rec : mount_fstab_recs_) {
- if (fs_mgr_is_avb(fstab_rec)) {
+ for (const auto& fstab_entry : fstab_) {
+ if (fstab_entry.fs_mgr_flags.avb) {
need_dm_verity_ = true;
}
- if (fs_mgr_is_logical(fstab_rec)) {
+ if (fstab_entry.fs_mgr_flags.logical) {
// Don't try to find logical partitions via uevent regeneration.
- logical_partitions.emplace(basename(fstab_rec->blk_device));
+ logical_partitions.emplace(basename(fstab_entry.blk_device.c_str()));
} else {
- required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
+ required_devices_partition_names_.emplace(basename(fstab_entry.blk_device.c_str()));
}
}
@@ -569,11 +555,11 @@
return true;
}
-bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) {
- if (fs_mgr_is_avb(fstab_rec)) {
+bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) {
+ if (fstab_entry->fs_mgr_flags.avb) {
if (!InitAvbHandle()) return false;
AvbHashtreeResult hashtree_result =
- avb_handle_->SetUpAvbHashtree(fstab_rec, false /* wait_for_verity_dev */);
+ avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */);
switch (hashtree_result) {
case AvbHashtreeResult::kDisabled:
return true; // Returns true to mount the partition.
@@ -581,7 +567,7 @@
// The exact block device name (fstab_rec->blk_device) is changed to
// "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init
// first stage.
- return InitMappedDevice(fstab_rec->blk_device);
+ return InitMappedDevice(fstab_entry->blk_device);
default:
return false;
}
diff --git a/libcutils/include/cutils/partition_utils.h b/libcutils/include/cutils/partition_utils.h
index 7518559..8bc9b48 100644
--- a/libcutils/include/cutils/partition_utils.h
+++ b/libcutils/include/cutils/partition_utils.h
@@ -21,7 +21,7 @@
__BEGIN_DECLS
-int partition_wiped(char *source);
+int partition_wiped(const char* source);
__END_DECLS
diff --git a/libcutils/partition_utils.cpp b/libcutils/partition_utils.cpp
index 2211ff6..b840559 100644
--- a/libcutils/partition_utils.cpp
+++ b/libcutils/partition_utils.cpp
@@ -39,8 +39,7 @@
return ret;
}
-int partition_wiped(char *source)
-{
+int partition_wiped(const char* source) {
uint8_t buf[4096];
int fd, ret;
@@ -67,4 +66,3 @@
return 0;
}
-
diff --git a/libmeminfo/include/meminfo/sysmeminfo.h b/libmeminfo/include/meminfo/sysmeminfo.h
index 885be1d..f18ae08 100644
--- a/libmeminfo/include/meminfo/sysmeminfo.h
+++ b/libmeminfo/include/meminfo/sysmeminfo.h
@@ -18,6 +18,7 @@
#include <sys/types.h>
+#include <functional>
#include <map>
#include <string>
#include <vector>
@@ -51,6 +52,9 @@
bool ReadMemInfo(const std::string& path = "/proc/meminfo");
bool ReadMemInfo(const std::vector<std::string>& tags,
const std::string& path = "/proc/meminfo");
+ bool ReadMemInfo(const std::vector<std::string>& tags, std::vector<uint64_t>* out,
+ const std::string& path = "/proc/meminfo");
+ bool ReadMemInfo(std::vector<uint64_t>* out, const std::string& path = "/proc/meminfo");
// getters
uint64_t mem_total_kb() { return mem_in_kb_[kMemTotal]; }
@@ -59,19 +63,21 @@
uint64_t mem_cached_kb() { return mem_in_kb_[kMemCached]; }
uint64_t mem_shmem_kb() { return mem_in_kb_[kMemShmem]; }
uint64_t mem_slab_kb() { return mem_in_kb_[kMemSlab]; }
- uint64_t mem_slab_reclailmable_kb() { return mem_in_kb_[kMemSReclaim]; }
+ uint64_t mem_slab_reclaimable_kb() { return mem_in_kb_[kMemSReclaim]; }
uint64_t mem_slab_unreclaimable_kb() { return mem_in_kb_[kMemSUnreclaim]; }
uint64_t mem_swap_kb() { return mem_in_kb_[kMemSwapTotal]; }
uint64_t mem_swap_free_kb() { return mem_in_kb_[kMemSwapFree]; }
uint64_t mem_mapped_kb() { return mem_in_kb_[kMemMapped]; }
uint64_t mem_vmalloc_used_kb() { return mem_in_kb_[kMemVmallocUsed]; }
uint64_t mem_page_tables_kb() { return mem_in_kb_[kMemPageTables]; }
- uint64_t mem_kernel_stack_kb() { return mem_in_kb_[kMemPageTables]; }
+ uint64_t mem_kernel_stack_kb() { return mem_in_kb_[kMemKernelStack]; }
uint64_t mem_zram_kb(const std::string& zram_dev = "");
private:
std::map<std::string, uint64_t> mem_in_kb_;
bool MemZramDevice(const std::string& zram_dev, uint64_t* mem_zram_dev);
+ bool ReadMemInfo(const std::vector<std::string>& tags, const std::string& path,
+ std::function<void(const std::string&, uint64_t)> store_val);
};
} // namespace meminfo
diff --git a/libmeminfo/libmeminfo_benchmark.cpp b/libmeminfo/libmeminfo_benchmark.cpp
index 1db0824..2660a4d 100644
--- a/libmeminfo/libmeminfo_benchmark.cpp
+++ b/libmeminfo/libmeminfo_benchmark.cpp
@@ -29,6 +29,8 @@
#include <benchmark/benchmark.h>
+using ::android::meminfo::SysMemInfo;
+
enum {
MEMINFO_TOTAL,
MEMINFO_FREE,
@@ -71,8 +73,7 @@
static const char* const tags[] = {
"MemTotal:", "MemFree:", "Buffers:", "Cached:", "Shmem:", "Slab:",
"SReclaimable:", "SUnreclaim:", "SwapTotal:", "SwapFree:", "ZRam:", "Mapped:",
- "VmallocUsed:", "PageTables:", "KernelStack:", NULL
- };
+ "VmallocUsed:", "PageTables:", "KernelStack:", NULL};
static const int tagsLen[] = {9, 8, 8, 7, 6, 5, 13, 11, 10, 9, 5, 7, 12, 11, 12, 0};
@@ -105,7 +106,7 @@
}
}
-static void BM_ParseSysMemInfo(benchmark::State& state) {
+static void BM_ReadMemInfo_old(benchmark::State& state) {
std::string meminfo = R"meminfo(MemTotal: 3019740 kB
MemFree: 1809728 kB
MemAvailable: 2546560 kB
@@ -159,9 +160,9 @@
get_mem_info(mem, tf.path);
}
}
-BENCHMARK(BM_ParseSysMemInfo);
+BENCHMARK(BM_ReadMemInfo_old);
-static void BM_ReadMemInfo(benchmark::State& state) {
+static void BM_ReadMemInfo_new(benchmark::State& state) {
std::string meminfo = R"meminfo(MemTotal: 3019740 kB
MemFree: 1809728 kB
MemAvailable: 2546560 kB
@@ -211,12 +212,21 @@
android::base::WriteStringToFd(meminfo, tf.fd);
std::string file = std::string(tf.path);
- ::android::meminfo::SysMemInfo mi;
+ std::vector<uint64_t> mem(MEMINFO_COUNT);
+ const std::vector<std::string> tags = {
+ SysMemInfo::kMemTotal, SysMemInfo::kMemFree, SysMemInfo::kMemBuffers,
+ SysMemInfo::kMemCached, SysMemInfo::kMemShmem, SysMemInfo::kMemSlab,
+ SysMemInfo::kMemSReclaim, SysMemInfo::kMemSUnreclaim, SysMemInfo::kMemSwapTotal,
+ SysMemInfo::kMemSwapFree, SysMemInfo::kMemMapped, SysMemInfo::kMemVmallocUsed,
+ SysMemInfo::kMemPageTables, SysMemInfo::kMemKernelStack,
+ };
+
+ SysMemInfo smi;
for (auto _ : state) {
- mi.ReadMemInfo(file);
+ smi.ReadMemInfo(tags, &mem, file);
}
}
-BENCHMARK(BM_ReadMemInfo);
+BENCHMARK(BM_ReadMemInfo_new);
static uint64_t get_zram_mem_used(const std::string& zram_dir) {
FILE* f = fopen((zram_dir + "mm_stat").c_str(), "r");
@@ -246,23 +256,145 @@
return 0;
}
-static void BM_OldReadZramTotal(benchmark::State& state) {
+static void BM_ZramTotal_old(benchmark::State& state) {
std::string exec_dir = ::android::base::GetExecutableDirectory();
std::string zram_mmstat_dir = exec_dir + "/testdata1/";
for (auto _ : state) {
uint64_t zram_total __attribute__((unused)) = get_zram_mem_used(zram_mmstat_dir) / 1024;
}
}
-BENCHMARK(BM_OldReadZramTotal);
+BENCHMARK(BM_ZramTotal_old);
-static void BM_NewReadZramTotal(benchmark::State& state) {
+static void BM_ZramTotal_new(benchmark::State& state) {
std::string exec_dir = ::android::base::GetExecutableDirectory();
std::string zram_mmstat_dir = exec_dir + "/testdata1/";
- ::android::meminfo::SysMemInfo mi;
+ SysMemInfo smi;
for (auto _ : state) {
- uint64_t zram_total __attribute__((unused)) = mi.mem_zram_kb(zram_mmstat_dir);
+ uint64_t zram_total __attribute__((unused)) = smi.mem_zram_kb(zram_mmstat_dir);
}
}
-BENCHMARK(BM_NewReadZramTotal);
+BENCHMARK(BM_ZramTotal_new);
+
+static void BM_MemInfoWithZram_old(benchmark::State& state) {
+ std::string meminfo = R"meminfo(MemTotal: 3019740 kB
+MemFree: 1809728 kB
+MemAvailable: 2546560 kB
+Buffers: 54736 kB
+Cached: 776052 kB
+SwapCached: 0 kB
+Active: 445856 kB
+Inactive: 459092 kB
+Active(anon): 78492 kB
+Inactive(anon): 2240 kB
+Active(file): 367364 kB
+Inactive(file): 456852 kB
+Unevictable: 3096 kB
+Mlocked: 3096 kB
+SwapTotal: 0 kB
+SwapFree: 0 kB
+Dirty: 32 kB
+Writeback: 0 kB
+AnonPages: 74988 kB
+Mapped: 62624 kB
+Shmem: 4020 kB
+Slab: 86464 kB
+SReclaimable: 44432 kB
+SUnreclaim: 42032 kB
+KernelStack: 4880 kB
+PageTables: 2900 kB
+NFS_Unstable: 0 kB
+Bounce: 0 kB
+WritebackTmp: 0 kB
+CommitLimit: 1509868 kB
+Committed_AS: 80296 kB
+VmallocTotal: 263061440 kB
+VmallocUsed: 0 kB
+VmallocChunk: 0 kB
+AnonHugePages: 6144 kB
+ShmemHugePages: 0 kB
+ShmemPmdMapped: 0 kB
+CmaTotal: 131072 kB
+CmaFree: 130380 kB
+HugePages_Total: 0
+HugePages_Free: 0
+HugePages_Rsvd: 0
+HugePages_Surp: 0
+Hugepagesize: 2048 kB)meminfo";
+
+ TemporaryFile tf;
+ ::android::base::WriteStringToFd(meminfo, tf.fd);
+ std::string exec_dir = ::android::base::GetExecutableDirectory();
+ std::string zram_mmstat_dir = exec_dir + "/testdata1/";
+ uint64_t mem[MEMINFO_COUNT];
+ for (auto _ : state) {
+ get_mem_info(mem, tf.path);
+ mem[MEMINFO_ZRAM_TOTAL] = get_zram_mem_used("/sys/block/zram0/") / 1024;
+ CHECK_EQ(mem[MEMINFO_KERNEL_STACK], 4880u);
+ }
+}
+BENCHMARK(BM_MemInfoWithZram_old);
+
+static void BM_MemInfoWithZram_new(benchmark::State& state) {
+ std::string meminfo = R"meminfo(MemTotal: 3019740 kB
+MemFree: 1809728 kB
+MemAvailable: 2546560 kB
+Buffers: 54736 kB
+Cached: 776052 kB
+SwapCached: 0 kB
+Active: 445856 kB
+Inactive: 459092 kB
+Active(anon): 78492 kB
+Inactive(anon): 2240 kB
+Active(file): 367364 kB
+Inactive(file): 456852 kB
+Unevictable: 3096 kB
+Mlocked: 3096 kB
+SwapTotal: 0 kB
+SwapFree: 0 kB
+Dirty: 32 kB
+Writeback: 0 kB
+AnonPages: 74988 kB
+Mapped: 62624 kB
+Shmem: 4020 kB
+Slab: 86464 kB
+SReclaimable: 44432 kB
+SUnreclaim: 42032 kB
+KernelStack: 4880 kB
+PageTables: 2900 kB
+NFS_Unstable: 0 kB
+Bounce: 0 kB
+WritebackTmp: 0 kB
+CommitLimit: 1509868 kB
+Committed_AS: 80296 kB
+VmallocTotal: 263061440 kB
+VmallocUsed: 0 kB
+VmallocChunk: 0 kB
+AnonHugePages: 6144 kB
+ShmemHugePages: 0 kB
+ShmemPmdMapped: 0 kB
+CmaTotal: 131072 kB
+CmaFree: 130380 kB
+HugePages_Total: 0
+HugePages_Free: 0
+HugePages_Rsvd: 0
+HugePages_Surp: 0
+Hugepagesize: 2048 kB)meminfo";
+
+ TemporaryFile tf;
+ android::base::WriteStringToFd(meminfo, tf.fd);
+
+ std::string file = std::string(tf.path);
+ std::vector<uint64_t> mem(MEMINFO_COUNT);
+ std::vector<std::string> tags(SysMemInfo::kDefaultSysMemInfoTags);
+ auto it = tags.begin();
+ tags.insert(it + MEMINFO_ZRAM_TOTAL, "Zram:");
+ SysMemInfo smi;
+
+ for (auto _ : state) {
+ smi.ReadMemInfo(tags, &mem, file);
+ CHECK_EQ(mem[MEMINFO_KERNEL_STACK], 4880u);
+ }
+}
+BENCHMARK(BM_MemInfoWithZram_new);
BENCHMARK_MAIN();
diff --git a/libmeminfo/libmeminfo_test.cpp b/libmeminfo/libmeminfo_test.cpp
index b7a4b6b..2856c2d 100644
--- a/libmeminfo/libmeminfo_test.cpp
+++ b/libmeminfo/libmeminfo_test.cpp
@@ -347,8 +347,8 @@
Inactive(file): 456852 kB
Unevictable: 3096 kB
Mlocked: 3096 kB
-SwapTotal: 0 kB
-SwapFree: 0 kB
+SwapTotal: 32768 kB
+SwapFree: 4096 kB
Dirty: 32 kB
Writeback: 0 kB
AnonPages: 74988 kB
@@ -365,7 +365,7 @@
CommitLimit: 1509868 kB
Committed_AS: 80296 kB
VmallocTotal: 263061440 kB
-VmallocUsed: 0 kB
+VmallocUsed: 65536 kB
VmallocChunk: 0 kB
AnonHugePages: 6144 kB
ShmemHugePages: 0 kB
@@ -385,7 +385,19 @@
SysMemInfo mi;
ASSERT_TRUE(mi.ReadMemInfo(tf.path));
EXPECT_EQ(mi.mem_total_kb(), 3019740);
+ EXPECT_EQ(mi.mem_free_kb(), 1809728);
+ EXPECT_EQ(mi.mem_buffers_kb(), 54736);
+ EXPECT_EQ(mi.mem_cached_kb(), 776052);
+ EXPECT_EQ(mi.mem_shmem_kb(), 4020);
+ EXPECT_EQ(mi.mem_slab_kb(), 86464);
+ EXPECT_EQ(mi.mem_slab_reclaimable_kb(), 44432);
+ EXPECT_EQ(mi.mem_slab_unreclaimable_kb(), 42032);
+ EXPECT_EQ(mi.mem_swap_kb(), 32768);
+ EXPECT_EQ(mi.mem_swap_free_kb(), 4096);
+ EXPECT_EQ(mi.mem_mapped_kb(), 62624);
+ EXPECT_EQ(mi.mem_vmalloc_used_kb(), 65536);
EXPECT_EQ(mi.mem_page_tables_kb(), 2900);
+ EXPECT_EQ(mi.mem_kernel_stack_kb(), 4880);
}
TEST(SysMemInfoParser, TestEmptyFile) {
@@ -399,7 +411,7 @@
EXPECT_EQ(mi.mem_total_kb(), 0);
}
-TEST(SysMemInfoParse, TestZramTotal) {
+TEST(SysMemInfoParser, TestZramTotal) {
std::string exec_dir = ::android::base::GetExecutableDirectory();
SysMemInfo mi;
@@ -410,6 +422,100 @@
EXPECT_EQ(mi.mem_zram_kb(zram_memused_dir), 30504);
}
+enum {
+ MEMINFO_TOTAL,
+ MEMINFO_FREE,
+ MEMINFO_BUFFERS,
+ MEMINFO_CACHED,
+ MEMINFO_SHMEM,
+ MEMINFO_SLAB,
+ MEMINFO_SLAB_RECLAIMABLE,
+ MEMINFO_SLAB_UNRECLAIMABLE,
+ MEMINFO_SWAP_TOTAL,
+ MEMINFO_SWAP_FREE,
+ MEMINFO_ZRAM_TOTAL,
+ MEMINFO_MAPPED,
+ MEMINFO_VMALLOC_USED,
+ MEMINFO_PAGE_TABLES,
+ MEMINFO_KERNEL_STACK,
+ MEMINFO_COUNT
+};
+
+TEST(SysMemInfoParser, TestZramWithTags) {
+ std::string meminfo = R"meminfo(MemTotal: 3019740 kB
+MemFree: 1809728 kB
+MemAvailable: 2546560 kB
+Buffers: 54736 kB
+Cached: 776052 kB
+SwapCached: 0 kB
+Active: 445856 kB
+Inactive: 459092 kB
+Active(anon): 78492 kB
+Inactive(anon): 2240 kB
+Active(file): 367364 kB
+Inactive(file): 456852 kB
+Unevictable: 3096 kB
+Mlocked: 3096 kB
+SwapTotal: 32768 kB
+SwapFree: 4096 kB
+Dirty: 32 kB
+Writeback: 0 kB
+AnonPages: 74988 kB
+Mapped: 62624 kB
+Shmem: 4020 kB
+Slab: 86464 kB
+SReclaimable: 44432 kB
+SUnreclaim: 42032 kB
+KernelStack: 4880 kB
+PageTables: 2900 kB
+NFS_Unstable: 0 kB
+Bounce: 0 kB
+WritebackTmp: 0 kB
+CommitLimit: 1509868 kB
+Committed_AS: 80296 kB
+VmallocTotal: 263061440 kB
+VmallocUsed: 65536 kB
+VmallocChunk: 0 kB
+AnonHugePages: 6144 kB
+ShmemHugePages: 0 kB
+ShmemPmdMapped: 0 kB
+CmaTotal: 131072 kB
+CmaFree: 130380 kB
+HugePages_Total: 0
+HugePages_Free: 0
+HugePages_Rsvd: 0
+HugePages_Surp: 0
+Hugepagesize: 2048 kB)meminfo";
+
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ ASSERT_TRUE(::android::base::WriteStringToFd(meminfo, tf.fd));
+ std::string file = std::string(tf.path);
+ std::vector<uint64_t> mem(MEMINFO_COUNT);
+ std::vector<std::string> tags(SysMemInfo::kDefaultSysMemInfoTags);
+ auto it = tags.begin();
+ tags.insert(it + MEMINFO_ZRAM_TOTAL, "Zram:");
+ SysMemInfo mi;
+
+ // Read system memory info
+ EXPECT_TRUE(mi.ReadMemInfo(tags, &mem, file));
+
+ EXPECT_EQ(mem[MEMINFO_TOTAL], 3019740);
+ EXPECT_EQ(mem[MEMINFO_FREE], 1809728);
+ EXPECT_EQ(mem[MEMINFO_BUFFERS], 54736);
+ EXPECT_EQ(mem[MEMINFO_CACHED], 776052);
+ EXPECT_EQ(mem[MEMINFO_SHMEM], 4020);
+ EXPECT_EQ(mem[MEMINFO_SLAB], 86464);
+ EXPECT_EQ(mem[MEMINFO_SLAB_RECLAIMABLE], 44432);
+ EXPECT_EQ(mem[MEMINFO_SLAB_UNRECLAIMABLE], 42032);
+ EXPECT_EQ(mem[MEMINFO_SWAP_TOTAL], 32768);
+ EXPECT_EQ(mem[MEMINFO_SWAP_FREE], 4096);
+ EXPECT_EQ(mem[MEMINFO_MAPPED], 62624);
+ EXPECT_EQ(mem[MEMINFO_VMALLOC_USED], 65536);
+ EXPECT_EQ(mem[MEMINFO_PAGE_TABLES], 2900);
+ EXPECT_EQ(mem[MEMINFO_KERNEL_STACK], 4880);
+}
+
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
if (argc <= 1) {
diff --git a/libmeminfo/sysmeminfo.cpp b/libmeminfo/sysmeminfo.cpp
index 7e56238..4ec1c99 100644
--- a/libmeminfo/sysmeminfo.cpp
+++ b/libmeminfo/sysmeminfo.cpp
@@ -18,12 +18,15 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
+#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <algorithm>
#include <cctype>
#include <cstdio>
#include <fstream>
+#include <iterator>
#include <string>
#include <utility>
#include <vector>
@@ -49,7 +52,29 @@
};
bool SysMemInfo::ReadMemInfo(const std::string& path) {
- return ReadMemInfo(SysMemInfo::kDefaultSysMemInfoTags, path);
+ return ReadMemInfo(SysMemInfo::kDefaultSysMemInfoTags, path,
+ [&](const std::string& tag, uint64_t val) { mem_in_kb_[tag] = val; });
+}
+
+bool SysMemInfo::ReadMemInfo(std::vector<uint64_t>* out, const std::string& path) {
+ return ReadMemInfo(SysMemInfo::kDefaultSysMemInfoTags, out, path);
+}
+
+bool SysMemInfo::ReadMemInfo(const std::vector<std::string>& tags, std::vector<uint64_t>* out,
+ const std::string& path) {
+ out->clear();
+ out->resize(tags.size());
+
+ return ReadMemInfo(tags, path, [&]([[maybe_unused]] const std::string& tag, uint64_t val) {
+ auto it = std::find(tags.begin(), tags.end(), tag);
+ if (it == tags.end()) {
+ LOG(ERROR) << "Tried to store invalid tag: " << tag;
+ return;
+ }
+ auto index = std::distance(tags.begin(), it);
+ // store the values in the same order as the tags
+ out->at(index) = val;
+ });
}
// TODO: Delete this function if it can't match up with the c-like implementation below.
@@ -88,7 +113,8 @@
}
#else
-bool SysMemInfo::ReadMemInfo(const std::vector<std::string>& tags, const std::string& path) {
+bool SysMemInfo::ReadMemInfo(const std::vector<std::string>& tags, const std::string& path,
+ std::function<void(const std::string&, uint64_t)> store_val) {
char buffer[4096];
int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
if (fd < 0) {
@@ -106,22 +132,34 @@
char* p = buffer;
uint32_t found = 0;
uint32_t lineno = 0;
+ bool zram_tag_found = false;
while (*p && found < tags.size()) {
for (auto& tag : tags) {
+ // Special case for "Zram:" tag that android_os_Debug and friends look
+ // up along with the rest of the numbers from /proc/meminfo
+ if (!zram_tag_found && tag == "Zram:") {
+ store_val(tag, mem_zram_kb());
+ zram_tag_found = true;
+ found++;
+ continue;
+ }
+
if (strncmp(p, tag.c_str(), tag.size()) == 0) {
p += tag.size();
while (*p == ' ') p++;
char* endptr = nullptr;
- mem_in_kb_[tag] = strtoull(p, &endptr, 10);
+ uint64_t val = strtoull(p, &endptr, 10);
if (p == endptr) {
PLOG(ERROR) << "Failed to parse line:" << lineno + 1 << " in file: " << path;
return false;
}
+ store_val(tag, val);
p = endptr;
found++;
break;
}
}
+
while (*p && *p != '\n') {
p++;
}
@@ -163,24 +201,19 @@
}
bool SysMemInfo::MemZramDevice(const std::string& zram_dev, uint64_t* mem_zram_dev) {
- std::string content;
- if (android::base::ReadFileToString(zram_dev + "mm_stat", &content)) {
- std::vector<std::string> values = ::android::base::Split(content, " ");
- if (values.size() < 3) {
- LOG(ERROR) << "Malformed mm_stat file for zram dev: " << zram_dev
- << " content: " << content;
+ std::string mmstat = ::android::base::StringPrintf("%s/%s", zram_dev.c_str(), "mm_stat");
+ auto mmstat_fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(mmstat.c_str(), "re"), fclose};
+ if (mmstat_fp != nullptr) {
+ // only if we do have mmstat, use it. Otherwise, fall through to trying out the old
+ // 'mem_used_total'
+ if (fscanf(mmstat_fp.get(), "%*" SCNu64 " %*" SCNu64 " %" SCNu64, mem_zram_dev) != 1) {
+ PLOG(ERROR) << "Malformed mm_stat file in: " << zram_dev;
return false;
}
-
- if (!::android::base::ParseUint(values[2], mem_zram_dev)) {
- LOG(ERROR) << "Malformed mm_stat file for zram dev: " << zram_dev
- << " value: " << values[2];
- return false;
- }
-
return true;
}
+ std::string content;
if (::android::base::ReadFileToString(zram_dev + "mem_used_total", &content)) {
*mem_zram_dev = strtoull(content.c_str(), NULL, 10);
if (*mem_zram_dev == ULLONG_MAX) {
diff --git a/libmeminfo/testdata1/mm_stat b/libmeminfo/testdata1/mm_stat
index 684f567..32b325f 100644
--- a/libmeminfo/testdata1/mm_stat
+++ b/libmeminfo/testdata1/mm_stat
@@ -1 +1 @@
-145674240 26801454 31236096 0 45772800 3042 1887 517
+ 145674240 26801454 31236096 0 45772800 3042 1887 517
diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp
index 8516640..32691a3 100644
--- a/libpixelflinger/codeflinger/CodeCache.cpp
+++ b/libpixelflinger/codeflinger/CodeCache.cpp
@@ -61,7 +61,11 @@
#define USAGE_ERROR_ACTION(m,p) \
heap_error("ARGUMENT IS INVALID HEAP ADDRESS", __FUNCTION__, p)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wexpansion-to-defined"
+#pragma GCC diagnostic ignored "-Wnull-pointer-arithmetic"
#include "../../../../external/dlmalloc/malloc.c"
+#pragma GCC diagnostic pop
static void heap_error(const char* msg, const char* function, void* p) {
ALOG(LOG_FATAL, LOG_TAG, "@@@ ABORTING: CODE FLINGER: %s IN %s addr=%p",
diff --git a/libsparse/output_file.cpp b/libsparse/output_file.cpp
index fe314b3..5b8179f 100644
--- a/libsparse/output_file.cpp
+++ b/libsparse/output_file.cpp
@@ -508,7 +508,7 @@
out->len = len;
out->block_size = block_size;
- out->cur_out_ptr = 0ll;
+ out->cur_out_ptr = 0LL;
out->chunk_cnt = 0;
out->crc32 = 0;
out->use_crc = crc;
diff --git a/libunwindstack/DwarfCfa.cpp b/libunwindstack/DwarfCfa.cpp
index 0fa1638..4ba8a4b 100644
--- a/libunwindstack/DwarfCfa.cpp
+++ b/libunwindstack/DwarfCfa.cpp
@@ -260,7 +260,7 @@
}
// Log any of the expression data.
- for (const auto line : expression_lines) {
+ for (const auto& line : expression_lines) {
log(indent + 1, "%s", line.c_str());
}
return true;
diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp
index ba8797c..652dbd1 100644
--- a/libunwindstack/tools/unwind_for_offline.cpp
+++ b/libunwindstack/tools/unwind_for_offline.cpp
@@ -229,7 +229,7 @@
sp_map_start = map_info->start;
}
- for (auto frame : unwinder.frames()) {
+ for (const auto& frame : unwinder.frames()) {
map_info = maps.Find(frame.sp);
if (map_info != nullptr && sp_map_start != map_info->start) {
stacks.emplace_back(std::make_pair(frame.sp, map_info->end));
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index 427dace..969f26b 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -610,7 +610,7 @@
std::string llkFormat(const std::unordered_set<std::string>& blacklist) {
std::string ret;
- for (auto entry : blacklist) {
+ for (const auto& entry : blacklist) {
if (ret.size()) {
ret += ",";
}
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 041f6d8..264c612 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -28,7 +28,7 @@
dir.postinstall = /postinstall
[system]
-additional.namespaces = sphal,vndk,rs
+additional.namespaces = runtime,sphal,vndk,rs
###############################################################################
# "default" namespace
@@ -38,8 +38,7 @@
###############################################################################
namespace.default.isolated = true
-namespace.default.search.paths = /apex/com.android.runtime/${LIB}
-namespace.default.search.paths += /system/${LIB}
+namespace.default.search.paths = /system/${LIB}
namespace.default.search.paths += /%PRODUCT%/${LIB}
namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
@@ -76,7 +75,6 @@
namespace.default.permitted.paths += /mnt/expand
namespace.default.asan.search.paths = /data/asan/system/${LIB}
-namespace.default.asan.search.paths += /apex/com.android.runtime/${LIB}
namespace.default.asan.search.paths += /system/${LIB}
namespace.default.asan.search.paths += /data/asan/product/${LIB}
namespace.default.asan.search.paths += /%PRODUCT%/${LIB}
@@ -107,6 +105,28 @@
namespace.default.asan.permitted.paths += /%PRODUCT_SERVICES%/priv-app
namespace.default.asan.permitted.paths += /mnt/expand
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.default.links = runtime
+namespace.default.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+namespace.default.link.runtime.shared_libs += libart.so:libartd.so
+namespace.default.link.runtime.shared_libs += libnativebridge.so
+namespace.default.link.runtime.shared_libs += libnativehelper.so
+namespace.default.link.runtime.shared_libs += libnativeloader.so
+
+###############################################################################
+# "runtime" APEX namespace
+#
+# This namespace exposes externally accessible libraries from the Runtime APEX.
+###############################################################################
+namespace.runtime.isolated = true
+
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.links = default
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
+# when it exists.
+namespace.runtime.link.default.allow_all_shared_libs = true
+
###############################################################################
# "sphal" namespace
#
@@ -141,8 +161,12 @@
# Once in this namespace, access to libraries in /system/lib is restricted. Only
# libs listed here can be used.
-namespace.sphal.links = default,vndk,rs
+namespace.sphal.links = runtime,default,vndk,rs
+namespace.sphal.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+
+# LLNDK_LIBRARIES includes the runtime libs above, but the order here ensures
+# that they are loaded from the runtime namespace.
namespace.sphal.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.sphal.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
@@ -189,9 +213,11 @@
namespace.rs.asan.permitted.paths += /vendor/${LIB}
namespace.rs.asan.permitted.paths += /data
-namespace.rs.links = default,vndk
+namespace.rs.links = runtime,default,vndk
-namespace.rs.link.default.shared_libs = %LLNDK_LIBRARIES%
+namespace.rs.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+
+namespace.rs.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.rs.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
# Private LLNDK libs (e.g. libft2.so) are exceptionally allowed to this
# namespace because RS framework libs are using them.
@@ -237,10 +263,13 @@
namespace.vndk.asan.permitted.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%/hw
namespace.vndk.asan.permitted.paths += /system/${LIB}/vndk-sp%VNDK_VER%/hw
-# The "vndk" namespace links to "default" namespace for LLNDK libs and links to
-# "sphal" namespace for vendor libs. The ordering matters. The "default"
-# namespace has higher priority than the "sphal" namespace.
-namespace.vndk.links = default,sphal
+# The "vndk" namespace links to "runtime" for Bionic libs, "default" namespace
+# for LLNDK libs, and links to "sphal" namespace for vendor libs. The ordering
+# matters. The "default" namespace has higher priority than the "sphal"
+# namespace.
+namespace.vndk.links = runtime,default,sphal
+
+namespace.vndk.link.runtime.shared_libs = libc.so:libdl.so:libm.so
# When these NDK libs are required inside this namespace, then it is redirected
# to the default namespace. This is possible since their ABI is stable across
@@ -251,6 +280,7 @@
# Allow VNDK-SP extensions to use vendor libraries
namespace.vndk.link.sphal.allow_all_shared_libs = true
+
###############################################################################
# Namespace config for vendor processes. In O, no restriction is enforced for
# them. However, in O-MR1, access to /system/${LIB} will not be allowed to
@@ -258,7 +288,7 @@
# (LL-NDK only) access.
###############################################################################
[vendor]
-additional.namespaces = system,vndk
+additional.namespaces = runtime,system,vndk
###############################################################################
# "default" namespace
@@ -289,12 +319,24 @@
namespace.default.asan.permitted.paths += /data/asan/vendor
namespace.default.asan.permitted.paths += /vendor
-namespace.default.links = system,vndk
+namespace.default.links = runtime,system,vndk
+namespace.default.link.runtime.shared_libs = libc.so:libdl.so:libm.so
namespace.default.link.system.shared_libs = %LLNDK_LIBRARIES%
namespace.default.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES%
namespace.default.link.vndk.shared_libs += %VNDK_CORE_LIBRARIES%
###############################################################################
+# "runtime" APEX namespace
+#
+# This namespace pulls in externally accessible libs from the Runtime APEX.
+###############################################################################
+namespace.runtime.isolated = true
+namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.links = default
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies.
+namespace.runtime.link.default.allow_all_shared_libs = true
+
+###############################################################################
# "vndk" namespace
#
# This namespace is where VNDK and VNDK-SP libraries are loaded for
@@ -325,7 +367,10 @@
# When these NDK libs are required inside this namespace, then it is redirected
# to the system namespace. This is possible since their ABI is stable across
# Android releases.
-namespace.vndk.links = system,default
+namespace.vndk.links = runtime,system,default
+
+namespace.vndk.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+
namespace.vndk.link.system.shared_libs = %LLNDK_LIBRARIES%
namespace.vndk.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
@@ -339,30 +384,47 @@
###############################################################################
namespace.system.isolated = false
-namespace.system.search.paths = /apex/com.android.runtime/${LIB}
-namespace.system.search.paths += /system/${LIB}
+namespace.system.search.paths = /system/${LIB}
namespace.system.search.paths += /%PRODUCT%/${LIB}
namespace.system.search.paths += /%PRODUCT_SERVICES%/${LIB}
namespace.system.asan.search.paths = /data/asan/system/${LIB}
-namespace.system.asan.search.paths += /apex/com.android.runtime/${LIB}
namespace.system.asan.search.paths += /system/${LIB}
namespace.system.asan.search.paths += /data/asan/product/${LIB}
namespace.system.asan.search.paths += /%PRODUCT%/${LIB}
namespace.system.asan.search.paths += /data/asan/product_services/${LIB}
namespace.system.asan.search.paths += /%PRODUCT_SERVICES%/${LIB}
+namespace.system.links = runtime
+namespace.system.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+
+
###############################################################################
# Namespace config for binaries under /postinstall.
-# Only one default namespace is defined and it has no directories other than
-# /system/lib in the search paths. This is because linker calls realpath on the
-# search paths and this causes selinux denial if the paths (/vendor, /odm) are
-# not allowed to the poinstall binaries. There is no reason to allow the
-# binaries to access the paths.
+# Only default and runtime namespaces are defined and default has no directories
+# other than /system/lib in the search paths. This is because linker calls
+# realpath on the search paths and this causes selinux denial if the paths
+# (/vendor, /odm) are not allowed to the postinstall binaries. There is no
+# reason to allow the binaries to access the paths.
###############################################################################
[postinstall]
+additional.namespaces = runtime
+
namespace.default.isolated = false
-namespace.default.search.paths = /apex/com.android.runtime/${LIB}
-namespace.default.search.paths += /system/${LIB}
+namespace.default.search.paths = /system/${LIB}
namespace.default.search.paths += /%PRODUCT%/${LIB}
namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
+
+namespace.default.links = runtime
+namespace.default.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+
+###############################################################################
+# "runtime" APEX namespace
+#
+# This namespace pulls in externally accessible libs from the Runtime APEX.
+###############################################################################
+namespace.runtime.isolated = true
+namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.links = default
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies.
+namespace.runtime.link.default.allow_all_shared_libs = true
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 6a53b03..7ca45ff 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -28,7 +28,7 @@
dir.postinstall = /postinstall
[system]
-additional.namespaces = sphal,vndk,rs
+additional.namespaces = runtime,sphal,vndk,rs
###############################################################################
# "default" namespace
@@ -38,15 +38,13 @@
###############################################################################
namespace.default.isolated = false
-namespace.default.search.paths = /apex/com.android.runtime/${LIB}
-namespace.default.search.paths += /system/${LIB}
+namespace.default.search.paths = /system/${LIB}
namespace.default.search.paths += /odm/${LIB}
namespace.default.search.paths += /vendor/${LIB}
namespace.default.search.paths += /%PRODUCT%/${LIB}
namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
namespace.default.asan.search.paths = /data/asan/system/${LIB}
-namespace.default.asan.search.paths += /apex/com.android.runtime/${LIB}
namespace.default.asan.search.paths += /system/${LIB}
namespace.default.asan.search.paths += /data/asan/odm/${LIB}
namespace.default.asan.search.paths += /odm/${LIB}
@@ -57,6 +55,27 @@
namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
namespace.default.asan.search.paths += /%PRODUCT_SERVICES%/${LIB}
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.default.links = runtime
+namespace.default.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+namespace.default.link.runtime.shared_libs += libart.so:libartd.so
+namespace.default.link.runtime.shared_libs += libnativehelper.so
+namespace.default.link.runtime.shared_libs += libnativeloader.so
+
+###############################################################################
+# "runtime" APEX namespace
+#
+# This namespace pulls in externally accessible libs from the Runtime APEX.
+###############################################################################
+namespace.runtime.isolated = true
+
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.links = default
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
+# when it exists.
+namespace.runtime.link.default.allow_all_shared_libs = true
+
###############################################################################
# "sphal" namespace
#
@@ -91,8 +110,12 @@
# Once in this namespace, access to libraries in /system/lib is restricted. Only
# libs listed here can be used.
-namespace.sphal.links = default,vndk,rs
+namespace.sphal.links = runtime,default,vndk,rs
+namespace.sphal.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+
+# LLNDK_LIBRARIES includes the runtime libs above, but the order here ensures
+# that they are loaded from the runtime namespace.
namespace.sphal.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.sphal.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
@@ -139,9 +162,11 @@
namespace.rs.asan.permitted.paths += /vendor/${LIB}
namespace.rs.asan.permitted.paths += /data
-namespace.rs.links = default,vndk
+namespace.rs.links = runtime,default,vndk
-namespace.rs.link.default.shared_libs = %LLNDK_LIBRARIES%
+namespace.rs.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+
+namespace.rs.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.rs.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
# Private LLNDK libs (e.g. libft2.so) are exceptionally allowed to this
# namespace because RS framework libs are using them.
@@ -190,10 +215,14 @@
# When these NDK libs are required inside this namespace, then it is redirected
# to the default namespace. This is possible since their ABI is stable across
# Android releases.
-namespace.vndk.links = default
+namespace.vndk.links = runtime,default
+
+namespace.vndk.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+
namespace.vndk.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+
###############################################################################
# Namespace config for vendor processes. In O, no restriction is enforced for
# them. However, in O-MR1, access to /system/${LIB} will not be allowed to
@@ -201,6 +230,7 @@
# (LL-NDK only) access.
###############################################################################
[vendor]
+additional.namespaces = runtime
namespace.default.isolated = false
namespace.default.search.paths = /odm/${LIB}
@@ -210,10 +240,9 @@
namespace.default.search.paths += /vendor/${LIB}/vndk
namespace.default.search.paths += /vendor/${LIB}/vndk-sp
-# Access to system libraries are allowed
+# Access to system libraries is allowed
namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER%
namespace.default.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.default.search.paths += /apex/com.android.runtime/${LIB}
namespace.default.search.paths += /system/${LIB}
namespace.default.search.paths += /%PRODUCT%/${LIB}
namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
@@ -235,24 +264,53 @@
namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
namespace.default.asan.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
namespace.default.asan.search.paths += /data/asan/system/${LIB}
-namespace.default.asan.search.paths += /apex/com.android.runtime/${LIB}
namespace.default.asan.search.paths += /system/${LIB}
namespace.default.asan.search.paths += /data/asan/product/${LIB}
namespace.default.asan.search.paths += /%PRODUCT%/${LIB}
namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
namespace.default.asan.search.paths += /%PRODUCT_SERVICES%/${LIB}
+namespace.default.links = runtime
+namespace.default.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+
+###############################################################################
+# "runtime" APEX namespace
+#
+# This namespace pulls in externally accessible libs from the Runtime APEX.
+###############################################################################
+namespace.runtime.isolated = true
+namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.links = default
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies.
+namespace.runtime.link.default.allow_all_shared_libs = true
+
+
###############################################################################
# Namespace config for binaries under /postinstall.
-# Only one default namespace is defined and it has no directories other than
-# /system/lib in the search paths. This is because linker calls realpath on the
-# search paths and this causes selinux denial if the paths (/vendor, /odm) are
-# not allowed to the poinstall binaries. There is no reason to allow the
-# binaries to access the paths.
+# Only default and runtime namespaces are defined and default has no directories
+# other than /system/lib in the search paths. This is because linker calls
+# realpath on the search paths and this causes selinux denial if the paths
+# (/vendor, /odm) are not allowed to the postinstall binaries. There is no
+# reason to allow the binaries to access the paths.
###############################################################################
[postinstall]
+additional.namespaces = runtime
+
namespace.default.isolated = false
-namespace.default.search.paths = /apex/com.android.runtime/${LIB}
-namespace.default.search.paths += /system/${LIB}
+namespace.default.search.paths = /system/${LIB}
namespace.default.search.paths += /%PRODUCT%/${LIB}
namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
+
+namespace.default.links = runtime
+namespace.default.link.runtime.shared_libs = libc.so:libdl.so:libm.so
+
+###############################################################################
+# "runtime" APEX namespace
+#
+# This namespace pulls in externally accessible libs from the Runtime APEX.
+###############################################################################
+namespace.runtime.isolated = true
+namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.links = default
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies.
+namespace.runtime.link.default.allow_all_shared_libs = true
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index d90a1ce..a9658a4 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -1,6 +1,9 @@
firmware_directories /etc/firmware/ /odm/firmware/ /vendor/firmware/ /firmware/image/
uevent_socket_rcvbuf_size 16M
+subsystem adf
+ devname uevent_devname
+
subsystem graphics
devname uevent_devpath
dirname /dev/graphics
@@ -9,10 +12,26 @@
devname uevent_devpath
dirname /dev/dri
+subsystem oncrpc
+ devname uevent_devpath
+ dirname /dev/oncrpc
+
+subsystem adsp
+ devname uevent_devpath
+ dirname /dev/adsp
+
+subsystem msm_camera
+ devname uevent_devpath
+ dirname /dev/msm_camera
+
subsystem input
devname uevent_devpath
dirname /dev/input
+subsystem mtd
+ devname uevent_devpath
+ dirname /dev/mtd
+
subsystem sound
devname uevent_devpath
dirname /dev/snd
@@ -40,25 +59,73 @@
/dev/pmsg0 0222 root log
+# the msm hw3d client device node is world writable/readable.
+/dev/msm_hw3dc 0666 root root
+
+# gpu driver for adreno200 is globally accessible
+/dev/kgsl 0666 root root
+
# kms driver for drm based gpu
/dev/dri/* 0666 root graphics
# these should not be world writable
/dev/diag 0660 radio radio
+/dev/diag_arm9 0660 radio radio
/dev/ttyMSM0 0600 bluetooth bluetooth
/dev/uhid 0660 uhid uhid
/dev/uinput 0660 uhid uhid
+/dev/alarm 0664 system radio
/dev/rtc0 0640 system system
/dev/tty0 0660 root system
/dev/graphics/* 0660 root graphics
+/dev/msm_hw3dm 0660 system graphics
/dev/input/* 0660 root input
/dev/v4l-touch* 0660 root input
+/dev/eac 0660 root audio
+/dev/cam 0660 root camera
+/dev/pmem 0660 system graphics
+/dev/pmem_adsp* 0660 system audio
+/dev/pmem_camera* 0660 system camera
+/dev/oncrpc/* 0660 root system
+/dev/adsp/* 0660 system audio
/dev/snd/* 0660 system audio
+/dev/mt9t013 0660 system system
+/dev/msm_camera/* 0660 system system
+/dev/akm8976_daemon 0640 compass system
+/dev/akm8976_aot 0640 compass system
+/dev/akm8973_daemon 0640 compass system
+/dev/akm8973_aot 0640 compass system
+/dev/bma150 0640 compass system
+/dev/cm3602 0640 compass system
+/dev/akm8976_pffd 0640 compass system
+/dev/lightsensor 0640 system system
+/dev/msm_pcm_out* 0660 system audio
+/dev/msm_pcm_in* 0660 system audio
+/dev/msm_pcm_ctl* 0660 system audio
+/dev/msm_snd* 0660 system audio
/dev/msm_mp3* 0660 system audio
+/dev/audience_a1026* 0660 system audio
+/dev/tpa2018d1* 0660 system audio
+/dev/msm_audpre 0660 system audio
+/dev/msm_audio_ctl 0660 system audio
+/dev/htc-acoustic 0660 system audio
+/dev/vdec 0660 system audio
+/dev/q6venc 0660 system audio
+/dev/snd/dsp 0660 system audio
+/dev/snd/dsp1 0660 system audio
+/dev/snd/mixer 0660 system audio
+/dev/smd0 0640 radio radio
+/dev/qmi 0640 radio radio
+/dev/qmi0 0640 radio radio
+/dev/qmi1 0640 radio radio
+/dev/qmi2 0640 radio radio
+/dev/bus/usb/* 0660 root usb
+/dev/mtp_usb 0660 root mtp
/dev/usb_accessory 0660 root usb
/dev/tun 0660 system vpn
# CDMA radio interface MUX
+/dev/ts0710mux* 0640 radio radio
/dev/ppp 0660 radio vpn
# sysfs properties
@@ -68,3 +135,6 @@
/sys/devices/virtual/usb_composite/* enable 0664 root system
/sys/devices/system/cpu/cpu* cpufreq/scaling_max_freq 0664 system system
/sys/devices/system/cpu/cpu* cpufreq/scaling_min_freq 0664 system system
+
+# DVB API device nodes
+/dev/dvb* 0660 root system