Merge "adb: don't close sockets before hitting EOF."
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index c00d955..4cbc45a 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -408,7 +408,8 @@
for (int i = argc - 1; i >= 0; i--) {
const char* file = argv[i];
- if (android::base::EndsWithIgnoreCase(file, ".apk")) {
+ if (android::base::EndsWithIgnoreCase(file, ".apk") ||
+ android::base::EndsWithIgnoreCase(file, ".dm")) {
struct stat sb;
if (stat(file, &sb) != -1) total_size += sb.st_size;
first_apk = i;
@@ -470,9 +471,9 @@
}
std::string cmd =
- android::base::StringPrintf("%s install-write -S %" PRIu64 " %d %d_%s -",
+ android::base::StringPrintf("%s install-write -S %" PRIu64 " %d %s -",
install_cmd.c_str(), static_cast<uint64_t>(sb.st_size),
- session_id, i, android::base::Basename(file).c_str());
+ session_id, android::base::Basename(file).c_str());
int localFd = adb_open(file, O_RDONLY);
if (localFd < 0) {
diff --git a/adb/daemon/file_sync_service.cpp b/adb/daemon/file_sync_service.cpp
index 8c39a20..d55096a 100644
--- a/adb/daemon/file_sync_service.cpp
+++ b/adb/daemon/file_sync_service.cpp
@@ -32,6 +32,10 @@
#include <unistd.h>
#include <utime.h>
+#include <memory>
+#include <string>
+#include <vector>
+
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -47,6 +51,7 @@
#include "security_log_tags.h"
#include "sysdeps/errno.h"
+using android::base::Dirname;
using android::base::StringPrintf;
static bool should_use_fs_config(const std::string& path) {
@@ -219,7 +224,7 @@
}
if (fd < 0 && errno == ENOENT) {
- if (!secure_mkdirs(android::base::Dirname(path))) {
+ if (!secure_mkdirs(Dirname(path))) {
SendSyncFailErrno(s, "secure_mkdirs failed");
goto fail;
}
@@ -327,8 +332,6 @@
#else
static bool handle_send_link(int s, const std::string& path, std::vector<char>& buffer) {
syncmsg msg;
- unsigned int len;
- int ret;
if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
@@ -337,24 +340,28 @@
return false;
}
- len = msg.data.size;
+ unsigned int len = msg.data.size;
if (len > buffer.size()) { // TODO: resize buffer?
SendSyncFail(s, "oversize data message");
return false;
}
if (!ReadFdExactly(s, &buffer[0], len)) return false;
- ret = symlink(&buffer[0], path.c_str());
- if (ret && errno == ENOENT) {
- if (!secure_mkdirs(android::base::Dirname(path))) {
- SendSyncFailErrno(s, "secure_mkdirs failed");
+ std::string buf_link;
+ if (!android::base::Readlink(path, &buf_link) || (buf_link != &buffer[0])) {
+ adb_unlink(path.c_str());
+ auto ret = symlink(&buffer[0], path.c_str());
+ if (ret && errno == ENOENT) {
+ if (!secure_mkdirs(Dirname(path))) {
+ SendSyncFailErrno(s, "secure_mkdirs failed");
+ return false;
+ }
+ ret = symlink(&buffer[0], path.c_str());
+ }
+ if (ret) {
+ SendSyncFailErrno(s, "symlink failed");
return false;
}
- ret = symlink(&buffer[0], path.c_str());
- }
- if (ret) {
- SendSyncFailErrno(s, "symlink failed");
- return false;
}
if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
@@ -391,7 +398,8 @@
// Don't delete files before copying if they are not "regular" or symlinks.
struct stat st;
- bool do_unlink = (lstat(path.c_str(), &st) == -1) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
+ bool do_unlink = (lstat(path.c_str(), &st) == -1) || S_ISREG(st.st_mode) ||
+ (S_ISLNK(st.st_mode) && !S_ISLNK(mode));
if (do_unlink) {
adb_unlink(path.c_str());
}
diff --git a/adb/daemon/jdwp_service.cpp b/adb/daemon/jdwp_service.cpp
index b40faee..fe79acd 100644
--- a/adb/daemon/jdwp_service.cpp
+++ b/adb/daemon/jdwp_service.cpp
@@ -212,6 +212,7 @@
static void jdwp_process_event(int socket, unsigned events, void* _proc) {
JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
+ CHECK_EQ(socket, proc->socket);
if (events & FDE_READ) {
if (proc->pid < 0) {
@@ -225,82 +226,50 @@
D("Adding pid %d to jdwp process list", proc->pid);
jdwp_process_list_updated();
} else {
- /* the pid was read, if we get there it's probably because the connection
- * was closed (e.g. the JDWP process exited or crashed) */
- char buf[32];
-
- while (true) {
- int len = TEMP_FAILURE_RETRY(recv(socket, buf, sizeof(buf), 0));
-
- if (len == 0) {
- D("terminating JDWP %d connection: EOF", proc->pid);
- break;
- } else if (len < 0) {
- if (len < 0 && errno == EAGAIN) {
- return;
- }
-
- D("terminating JDWP %d connection: EOF", proc->pid);
- break;
- } else {
- D("ignoring unexpected JDWP %d control socket activity (%d bytes)", proc->pid,
- len);
- }
- }
-
+ // We already have the PID, if we can read from the socket, we've probably hit EOF.
+ D("terminating JDWP connection %d", proc->pid);
goto CloseProcess;
}
}
if (events & FDE_WRITE) {
D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
- if (!proc->out_fds.empty()) {
- int fd = proc->out_fds.back().get();
- struct cmsghdr* cmsg;
- struct msghdr msg;
- struct iovec iov;
- char dummy = '!';
- char buffer[sizeof(struct cmsghdr) + sizeof(int)];
+ CHECK(!proc->out_fds.empty());
- iov.iov_base = &dummy;
- iov.iov_len = 1;
- msg.msg_name = nullptr;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_flags = 0;
- msg.msg_control = buffer;
- msg.msg_controllen = sizeof(buffer);
+ int fd = proc->out_fds.back().get();
+ struct cmsghdr* cmsg;
+ struct msghdr msg;
+ struct iovec iov;
+ char dummy = '!';
+ char buffer[sizeof(struct cmsghdr) + sizeof(int)];
- cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_len = msg.msg_controllen;
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- ((int*)CMSG_DATA(cmsg))[0] = fd;
+ iov.iov_base = &dummy;
+ iov.iov_len = 1;
+ msg.msg_name = nullptr;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+ msg.msg_control = buffer;
+ msg.msg_controllen = sizeof(buffer);
- if (!set_file_block_mode(proc->socket, true)) {
- VLOG(JDWP) << "failed to set blocking mode for fd " << proc->socket;
- goto CloseProcess;
- }
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = msg.msg_controllen;
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ ((int*)CMSG_DATA(cmsg))[0] = fd;
- int ret = TEMP_FAILURE_RETRY(sendmsg(proc->socket, &msg, 0));
- if (ret < 0) {
- D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
- goto CloseProcess;
- }
+ int ret = TEMP_FAILURE_RETRY(sendmsg(socket, &msg, 0));
+ if (ret < 0) {
+ D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
+ goto CloseProcess;
+ }
- D("sent file descriptor %d to JDWP process %d", fd, proc->pid);
+ D("sent file descriptor %d to JDWP process %d", fd, proc->pid);
- proc->out_fds.pop_back();
-
- if (!set_file_block_mode(proc->socket, false)) {
- VLOG(JDWP) << "failed to set non-blocking mode for fd " << proc->socket;
- goto CloseProcess;
- }
-
- if (proc->out_fds.empty()) {
- fdevent_del(proc->fde, FDE_WRITE);
- }
+ proc->out_fds.pop_back();
+ if (proc->out_fds.empty()) {
+ fdevent_del(proc->fde, FDE_WRITE);
}
}
@@ -406,9 +375,10 @@
return 0;
}
-static void jdwp_control_event(int s, unsigned events, void* _control) {
+static void jdwp_control_event(int fd, unsigned events, void* _control) {
JdwpControl* control = (JdwpControl*)_control;
+ CHECK_EQ(fd, control->listen_socket);
if (events & FDE_READ) {
int s = adb_socket_accept(control->listen_socket, nullptr, nullptr);
if (s < 0) {
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index 2bac486..720ec6a 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -202,6 +202,27 @@
return StartSubprocess(command.c_str(), terminal_type.c_str(), type, protocol);
}
+static void spin_service(unique_fd fd) {
+ if (!__android_log_is_debuggable()) {
+ WriteFdExactly(fd.get(), "refusing to spin on non-debuggable build\n");
+ return;
+ }
+
+ // A service that creates an fdevent that's always pending, and then ignores it.
+ unique_fd pipe_read, pipe_write;
+ if (!Pipe(&pipe_read, &pipe_write)) {
+ WriteFdExactly(fd.get(), "failed to create pipe\n");
+ return;
+ }
+
+ fdevent_run_on_main_thread([fd = pipe_read.release()]() {
+ fdevent* fde = fdevent_create(fd, [](int, unsigned, void*) {}, nullptr);
+ fdevent_add(fde, FDE_READ);
+ });
+
+ WriteFdExactly(fd.get(), "spinning\n");
+}
+
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)};
@@ -254,6 +275,9 @@
} else if (!strcmp(name, "reconnect")) {
return create_service_thread(
"reconnect", std::bind(reconnect_service, std::placeholders::_1, transport));
+ } else if (!strcmp(name, "spin")) {
+ return create_service_thread("spin", spin_service);
}
+
return unique_fd{};
}
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index 98a73eb..e096560 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -35,6 +35,8 @@
#include <unordered_map>
#include <vector>
+#include <android-base/chrono_utils.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/thread_annotations.h>
@@ -44,6 +46,7 @@
#include "adb_trace.h"
#include "adb_unique_fd.h"
#include "adb_utils.h"
+#include "sysdeps/chrono.h"
#define FDE_EVENTMASK 0x00ff
#define FDE_STATEMASK 0xff00
@@ -247,6 +250,7 @@
}
CHECK_GT(pollfds.size(), 0u);
D("poll(), pollfds = %s", dump_pollfds(pollfds).c_str());
+
int ret = adb_poll(&pollfds[0], pollfds.size(), -1);
if (ret == -1) {
PLOG(ERROR) << "poll(), ret = " << ret;
@@ -367,10 +371,66 @@
}
}
+static void fdevent_check_spin(uint64_t cycle) {
+ // Check to see if we're spinning because we forgot about an fdevent
+ // by keeping track of how long fdevents have been continuously pending.
+ struct SpinCheck {
+ fdevent* fde;
+ android::base::boot_clock::time_point timestamp;
+ uint64_t cycle;
+ };
+ static auto& g_continuously_pending = *new std::unordered_map<uint64_t, SpinCheck>();
+ static auto last_cycle = android::base::boot_clock::now();
+
+ auto now = android::base::boot_clock::now();
+ if (now - last_cycle > 10ms) {
+ // We're not spinning.
+ g_continuously_pending.clear();
+ last_cycle = now;
+ return;
+ }
+ last_cycle = now;
+
+ for (auto* fde : g_pending_list) {
+ auto it = g_continuously_pending.find(fde->id);
+ if (it == g_continuously_pending.end()) {
+ g_continuously_pending[fde->id] =
+ SpinCheck{.fde = fde, .timestamp = now, .cycle = cycle};
+ } else {
+ it->second.cycle = cycle;
+ }
+ }
+
+ for (auto it = g_continuously_pending.begin(); it != g_continuously_pending.end();) {
+ if (it->second.cycle != cycle) {
+ it = g_continuously_pending.erase(it);
+ } else {
+ // Use an absurdly long window, since all we really care about is
+ // getting a bugreport eventually.
+ if (now - it->second.timestamp > 300s) {
+ LOG(FATAL_WITHOUT_ABORT)
+ << "detected spin in fdevent: " << dump_fde(it->second.fde);
+#if defined(__linux__)
+ int fd = it->second.fde->fd.get();
+ std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
+ std::string path;
+ if (!android::base::Readlink(fd_path, &path)) {
+ PLOG(FATAL_WITHOUT_ABORT) << "readlink of fd " << fd << " failed";
+ }
+ LOG(FATAL_WITHOUT_ABORT) << "fd " << fd << " = " << path;
+#endif
+ abort();
+ }
+ ++it;
+ }
+ }
+}
+
void fdevent_loop() {
set_main_thread();
fdevent_run_setup();
+ uint64_t cycle = 0;
while (true) {
if (terminate_loop) {
return;
@@ -380,6 +440,8 @@
fdevent_process();
+ fdevent_check_spin(cycle++);
+
while (!g_pending_list.empty()) {
fdevent* fde = g_pending_list.front();
g_pending_list.pop_front();
diff --git a/adb/types.h b/adb/types.h
index a3e5d48..1f7008e 100644
--- a/adb/types.h
+++ b/adb/types.h
@@ -42,14 +42,14 @@
}
Block(const Block& copy) = delete;
- Block(Block&& move) {
+ Block(Block&& move) noexcept {
std::swap(data_, move.data_);
std::swap(capacity_, move.capacity_);
std::swap(size_, move.size_);
}
Block& operator=(const Block& copy) = delete;
- Block& operator=(Block&& move) {
+ Block& operator=(Block&& move) noexcept {
clear();
std::swap(data_, move.data_);
@@ -147,12 +147,10 @@
}
IOVector(const IOVector& copy) = delete;
- IOVector(IOVector&& move) : IOVector() {
- *this = std::move(move);
- }
+ IOVector(IOVector&& move) noexcept : IOVector() { *this = std::move(move); }
IOVector& operator=(const IOVector& copy) = delete;
- IOVector& operator=(IOVector&& move) {
+ IOVector& operator=(IOVector&& move) noexcept {
chain_ = std::move(move.chain_);
chain_length_ = move.chain_length_;
begin_offset_ = move.begin_offset_;
diff --git a/base/include/android-base/parseint.h b/base/include/android-base/parseint.h
index 9444fdd..be8b97b 100644
--- a/base/include/android-base/parseint.h
+++ b/base/include/android-base/parseint.h
@@ -22,6 +22,7 @@
#include <limits>
#include <string>
+#include <type_traits>
namespace android {
namespace base {
@@ -33,6 +34,7 @@
template <typename T>
bool ParseUint(const char* s, T* out, T max = std::numeric_limits<T>::max(),
bool allow_suffixes = false) {
+ static_assert(std::is_unsigned<T>::value, "ParseUint can only be used with unsigned types");
while (isspace(*s)) {
s++;
}
@@ -96,6 +98,7 @@
bool ParseInt(const char* s, T* out,
T min = std::numeric_limits<T>::min(),
T max = std::numeric_limits<T>::max()) {
+ static_assert(std::is_signed<T>::value, "ParseInt can only be used with signed types");
while (isspace(*s)) {
s++;
}
diff --git a/base/include/android-base/scopeguard.h b/base/include/android-base/scopeguard.h
index e6a9d10..5a224d6 100644
--- a/base/include/android-base/scopeguard.h
+++ b/base/include/android-base/scopeguard.h
@@ -28,7 +28,7 @@
public:
ScopeGuard(F&& f) : f_(std::forward<F>(f)), active_(true) {}
- ScopeGuard(ScopeGuard&& that) : f_(std::move(that.f_)), active_(that.active_) {
+ ScopeGuard(ScopeGuard&& that) noexcept : f_(std::move(that.f_)), active_(that.active_) {
that.active_ = false;
}
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index 71025ad..cd2dc04 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -90,8 +90,8 @@
explicit unique_fd_impl(int fd) { reset(fd); }
~unique_fd_impl() { reset(); }
- unique_fd_impl(unique_fd_impl&& other) { reset(other.release()); }
- unique_fd_impl& operator=(unique_fd_impl&& s) {
+ unique_fd_impl(unique_fd_impl&& other) noexcept { reset(other.release()); }
+ unique_fd_impl& operator=(unique_fd_impl&& s) noexcept {
int fd = s.fd_;
s.fd_ = -1;
reset(fd, &s);
diff --git a/fastboot/constants.h b/fastboot/constants.h
index 2eaf006..705da33 100644
--- a/fastboot/constants.h
+++ b/fastboot/constants.h
@@ -63,3 +63,4 @@
#define FB_VAR_VARIANT "variant"
#define FB_VAR_OFF_MODE_CHARGE_STATE "off-mode-charge"
#define FB_VAR_BATTERY_VOLTAGE "battery-voltage"
+#define FB_VAR_BATTERY_SOC_OK "battery-soc-ok"
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index b02d968..d5ea6db 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -27,6 +27,7 @@
#include <android-base/unique_fd.h>
#include <cutils/android_reboot.h>
#include <ext4_utils/wipe.h>
+#include <fs_mgr.h>
#include <liblp/builder.h>
#include <liblp/liblp.h>
#include <uuid/uuid.h>
@@ -97,6 +98,7 @@
{FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}},
{FB_VAR_OFF_MODE_CHARGE_STATE, {GetOffModeChargeState, nullptr}},
{FB_VAR_BATTERY_VOLTAGE, {GetBatteryVoltage, nullptr}},
+ {FB_VAR_BATTERY_SOC_OK, {GetBatterySoCOk, nullptr}},
{FB_VAR_HW_REVISION, {GetHardwareRevision, nullptr}}};
if (args.size() < 2) {
@@ -129,6 +131,11 @@
if (args.size() < 2) {
return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
}
+
+ if (GetDeviceLockStatus()) {
+ return device->WriteStatus(FastbootResult::FAIL, "Erase is not allowed on locked devices");
+ }
+
PartitionHandle handle;
if (!OpenPartition(device, args[1], &handle)) {
return device->WriteStatus(FastbootResult::FAIL, "Partition doesn't exist");
@@ -161,9 +168,15 @@
if (args.size() < 2) {
return device->WriteStatus(FastbootResult::FAIL, "size argument unspecified");
}
+
+ if (GetDeviceLockStatus()) {
+ return device->WriteStatus(FastbootResult::FAIL,
+ "Download is not allowed on locked devices");
+ }
+
// arg[0] is the command name, arg[1] contains size of data to be downloaded
unsigned int size;
- if (!android::base::ParseUint("0x" + args[1], &size, UINT_MAX)) {
+ if (!android::base::ParseUint("0x" + args[1], &size, kMaxDownloadSizeDefault)) {
return device->WriteStatus(FastbootResult::FAIL, "Invalid size");
}
device->download_data().resize(size);
@@ -201,6 +214,11 @@
return device->WriteStatus(FastbootResult::FAIL, "Missing slot argument");
}
+ if (GetDeviceLockStatus()) {
+ return device->WriteStatus(FastbootResult::FAIL,
+ "set_active command is not allowed on locked devices");
+ }
+
// Slot suffix needs to be between 'a' and 'z'.
Slot slot;
if (!GetSlotNumber(args[1], &slot)) {
@@ -310,7 +328,7 @@
};
PartitionBuilder::PartitionBuilder(FastbootDevice* device) {
- auto super_device = FindPhysicalPartition(LP_METADATA_PARTITION_NAME);
+ auto super_device = FindPhysicalPartition(fs_mgr_get_super_partition_name());
if (!super_device) {
return;
}
@@ -353,13 +371,7 @@
return device->WriteFail("Partition already exists");
}
- // Make a random UUID, since they're not currently used.
- uuid_t uuid;
- char uuid_str[37];
- uuid_generate_random(uuid);
- uuid_unparse(uuid, uuid_str);
-
- Partition* partition = builder->AddPartition(partition_name, uuid_str, 0);
+ Partition* partition = builder->AddPartition(partition_name, 0);
if (!partition) {
return device->WriteFail("Failed to add partition");
}
diff --git a/fastboot/device/commands.h b/fastboot/device/commands.h
index 9df43a9..bb1f988 100644
--- a/fastboot/device/commands.h
+++ b/fastboot/device/commands.h
@@ -19,6 +19,8 @@
#include <string>
#include <vector>
+constexpr unsigned int kMaxDownloadSizeDefault = 0x20000000;
+
class FastbootDevice;
enum class FastbootResult {
diff --git a/fastboot/device/flashing.cpp b/fastboot/device/flashing.cpp
index a383c54..4fc3d1d 100644
--- a/fastboot/device/flashing.cpp
+++ b/fastboot/device/flashing.cpp
@@ -146,8 +146,7 @@
if (builder->FindPartition(name)) {
continue;
}
- std::string guid = GetPartitionGuid(partition);
- if (!builder->AddPartition(name, guid, partition.attributes)) {
+ if (!builder->AddPartition(name, partition.attributes)) {
return device->WriteFail("Unable to add partition: " + name);
}
}
diff --git a/fastboot/device/utility.cpp b/fastboot/device/utility.cpp
index 02f6f2c..b844b9f 100644
--- a/fastboot/device/utility.cpp
+++ b/fastboot/device/utility.cpp
@@ -23,6 +23,8 @@
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
#include <liblp/liblp.h>
@@ -44,7 +46,7 @@
static bool OpenLogicalPartition(const std::string& name, const std::string& slot,
PartitionHandle* handle) {
- std::optional<std::string> path = FindPhysicalPartition(LP_METADATA_PARTITION_NAME);
+ std::optional<std::string> path = FindPhysicalPartition(fs_mgr_get_super_partition_name());
if (!path) {
return false;
}
@@ -81,6 +83,10 @@
}
std::optional<std::string> FindPhysicalPartition(const std::string& name) {
+ // Check for an invalid file name
+ if (android::base::StartsWith(name, "../") || name.find("/../") != std::string::npos) {
+ return {};
+ }
std::string path = "/dev/block/by-name/" + name;
if (access(path.c_str(), W_OK) < 0) {
return {};
@@ -100,7 +106,7 @@
bool LogicalPartitionExists(const std::string& name, const std::string& slot_suffix,
bool* is_zero_length) {
- auto path = FindPhysicalPartition(LP_METADATA_PARTITION_NAME);
+ auto path = FindPhysicalPartition(fs_mgr_get_super_partition_name());
if (!path) {
return false;
}
@@ -149,7 +155,7 @@
}
// Next get logical partitions.
- if (auto path = FindPhysicalPartition(LP_METADATA_PARTITION_NAME)) {
+ if (auto path = FindPhysicalPartition(fs_mgr_get_super_partition_name())) {
uint32_t slot_number = SlotNumberForSlotSuffix(device->GetCurrentSlot());
if (auto metadata = ReadMetadata(path->c_str(), slot_number)) {
for (const auto& partition : metadata->partitions) {
@@ -163,6 +169,9 @@
bool GetDeviceLockStatus() {
std::string cmdline;
- android::base::ReadFileToString("/proc/cmdline", &cmdline);
+ // Return lock status true if unable to read kernel command line.
+ if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) {
+ return true;
+ }
return cmdline.find("androidboot.verifiedbootstate=orange") == std::string::npos;
}
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index 01415d7..cbd2856 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -36,7 +36,6 @@
using ::android::hardware::fastboot::V1_0::Result;
using ::android::hardware::fastboot::V1_0::Status;
-constexpr int kMaxDownloadSizeDefault = 0x20000000;
constexpr char kFastbootProtocolVersion[] = "0.4";
bool GetVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
@@ -96,6 +95,56 @@
return true;
}
+bool GetBatteryVoltageHelper(FastbootDevice* device, int32_t* battery_voltage) {
+ using android::hardware::health::V2_0::HealthInfo;
+ using android::hardware::health::V2_0::Result;
+
+ auto health_hal = device->health_hal();
+ if (!health_hal) {
+ return false;
+ }
+
+ Result ret;
+ auto ret_val = health_hal->getHealthInfo([&](Result result, HealthInfo info) {
+ *battery_voltage = info.legacy.batteryVoltage;
+ ret = result;
+ });
+ if (!ret_val.isOk() || (ret != Result::SUCCESS)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool GetBatterySoCOk(FastbootDevice* device, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ int32_t battery_voltage = 0;
+ if (!GetBatteryVoltageHelper(device, &battery_voltage)) {
+ *message = "Unable to read battery voltage";
+ return false;
+ }
+
+ auto fastboot_hal = device->fastboot_hal();
+ if (!fastboot_hal) {
+ *message = "Fastboot HAL not found";
+ return false;
+ }
+
+ Result ret;
+ auto ret_val = fastboot_hal->getBatteryVoltageFlashingThreshold(
+ [&](int32_t voltage_threshold, Result result) {
+ *message = battery_voltage >= voltage_threshold ? "yes" : "no";
+ ret = result;
+ });
+
+ if (!ret_val.isOk() || ret.status != Status::SUCCESS) {
+ *message = "Unable to get battery voltage flashing threshold";
+ return false;
+ }
+
+ return true;
+}
+
bool GetOffModeChargeState(FastbootDevice* device, const std::vector<std::string>& /* args */,
std::string* message) {
auto fastboot_hal = device->fastboot_hal();
@@ -120,26 +169,13 @@
bool GetBatteryVoltage(FastbootDevice* device, const std::vector<std::string>& /* args */,
std::string* message) {
- using android::hardware::health::V2_0::HealthInfo;
- using android::hardware::health::V2_0::Result;
-
- auto health_hal = device->health_hal();
- if (!health_hal) {
- *message = "Health HAL not found";
- return false;
+ int32_t battery_voltage = 0;
+ if (GetBatteryVoltageHelper(device, &battery_voltage)) {
+ *message = std::to_string(battery_voltage);
+ return true;
}
-
- Result ret;
- auto ret_val = health_hal->getHealthInfo([&](Result result, HealthInfo info) {
- *message = std::to_string(info.legacy.batteryVoltage);
- ret = result;
- });
- if (!ret_val.isOk() || (ret != Result::SUCCESS)) {
- *message = "Unable to get battery voltage";
- return false;
- }
-
- return true;
+ *message = "Unable to get battery voltage";
+ return false;
}
bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& /* args */,
@@ -252,7 +288,7 @@
bool is_zero_length;
if (LogicalPartitionExists(args[0], device->GetCurrentSlot(), &is_zero_length) &&
is_zero_length) {
- *message = "0";
+ *message = "0x0";
return true;
}
// Otherwise, open the partition as normal.
@@ -272,7 +308,14 @@
*message = "Missing argument";
return false;
}
+
std::string partition_name = args[0];
+ if (!FindPhysicalPartition(partition_name) &&
+ !LogicalPartitionExists(partition_name, device->GetCurrentSlot())) {
+ *message = "Invalid partition";
+ return false;
+ }
+
auto fastboot_hal = device->fastboot_hal();
if (!fastboot_hal) {
*message = "Fastboot HAL not found";
diff --git a/fastboot/device/variables.h b/fastboot/device/variables.h
index e7c3c7c..59b71e8 100644
--- a/fastboot/device/variables.h
+++ b/fastboot/device/variables.h
@@ -57,6 +57,9 @@
std::string* message);
bool GetBatteryVoltage(FastbootDevice* device, const std::vector<std::string>& args,
std::string* message);
+bool GetBatterySoCOk(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+
// Helpers for getvar all.
std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device);
std::vector<std::vector<std::string>> GetAllPartitionArgsNoSlot(FastbootDevice* device);
diff --git a/fastboot/fuzzy_fastboot/fixtures.cpp b/fastboot/fuzzy_fastboot/fixtures.cpp
index c18af1d..280cfb6 100644
--- a/fastboot/fuzzy_fastboot/fixtures.cpp
+++ b/fastboot/fuzzy_fastboot/fixtures.cpp
@@ -86,6 +86,12 @@
return true;
}
+bool FastBootTest::UserSpaceFastboot() {
+ std::string value;
+ fb->GetVar("is-userspace", &value);
+ return value == "yes";
+}
+
RetCode FastBootTest::DownloadCommand(uint32_t size, std::string* response,
std::vector<std::string>* info) {
return fb->DownloadCommand(size, response, info);
@@ -158,6 +164,12 @@
return;
}
+ // User space fastboot implementations are not allowed to communicate to
+ // secure hardware and hence cannot lock/unlock the device.
+ if (UserSpaceFastboot()) {
+ return;
+ }
+
std::string resp;
std::vector<std::string> info;
// To avoid risk of bricking device, make sure unlock ability is set to 1
diff --git a/fastboot/fuzzy_fastboot/fixtures.h b/fastboot/fuzzy_fastboot/fixtures.h
index e47d0fd..e0f829e 100644
--- a/fastboot/fuzzy_fastboot/fixtures.h
+++ b/fastboot/fuzzy_fastboot/fixtures.h
@@ -47,6 +47,7 @@
static int MatchFastboot(usb_ifc_info* info, const char* local_serial = nullptr);
bool UsbStillAvailible();
+ bool UserSpaceFastboot();
protected:
RetCode DownloadCommand(uint32_t size, std::string* response = nullptr,
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index 90a2e74..c02ab1c 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -43,6 +43,7 @@
#include <thread>
#include <vector>
+#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <gtest/gtest.h>
#include <sparse/sparse.h>
@@ -289,6 +290,12 @@
TEST_F(Conformance, UnlockAbility) {
std::string resp;
std::vector<std::string> info;
+ // Userspace fastboot implementations do not have a way to get this
+ // information.
+ if (UserSpaceFastboot()) {
+ GTEST_LOG_(INFO) << "This test is skipped for userspace fastboot.";
+ return;
+ }
EXPECT_EQ(fb->RawCommand("flashing get_unlock_ability", &resp, &info), SUCCESS)
<< "'flashing get_unlock_ability' failed";
// There are two ways this can be reported, through info or the actual response
@@ -325,8 +332,9 @@
<< cmd + " responded with a string with leading whitespace";
EXPECT_FALSE(resp.compare(0, 2, "0x"))
<< cmd + "responded with a string that does not start with 0x...";
- int64_t size = strtoll(resp.c_str(), nullptr, 16);
- EXPECT_GT(size, 0) << "'" + resp + "' is not a valid response from " + cmd;
+ uint64_t size;
+ ASSERT_TRUE(android::base::ParseUint(resp, &size))
+ << "'" + resp + "' is not a valid response from " + cmd;
}
}
@@ -412,6 +420,10 @@
ASSERT_TRUE(resp == "yes" || resp == "no")
<< "Device did not respond with 'yes' or 'no' for getvar:unlocked";
bool curr = resp == "yes";
+ if (UserSpaceFastboot()) {
+ GTEST_LOG_(INFO) << "This test is skipped for userspace fastboot.";
+ return;
+ }
for (int i = 0; i < 2; i++) {
std::string action = !curr ? "unlock" : "lock";
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 208162e..3226010 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -37,6 +37,7 @@
#include <memory>
#include <string>
#include <thread>
+#include <utility>
#include <vector>
#include <android-base/file.h>
@@ -55,6 +56,7 @@
#include <ext4_utils/wipe.h>
#include <fs_mgr_overlayfs.h>
#include <libdm/dm.h>
+#include <liblp/metadata_format.h>
#include <linux/fs.h>
#include <linux/loop.h>
#include <linux/magic.h>
@@ -849,56 +851,115 @@
return true;
}
-bool fs_mgr_update_checkpoint_partition(struct fstab_rec* rec) {
- if (fs_mgr_is_checkpoint_fs(rec)) {
- if (!strcmp(rec->fs_type, "f2fs")) {
- std::string opts(rec->fs_options);
+class CheckpointManager {
+ public:
+ CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}
- opts += ",checkpoint=disable";
- free(rec->fs_options);
- rec->fs_options = strdup(opts.c_str());
- } else {
- LERROR << rec->fs_type << " does not implement checkpoints.";
+ bool Update(struct fstab_rec* rec) {
+ if (!fs_mgr_is_checkpoint(rec)) {
+ return true;
}
- } else if (fs_mgr_is_checkpoint_blk(rec)) {
- call_vdc({"checkpoint", "restoreCheckpoint", rec->blk_device});
- android::base::unique_fd fd(
- TEMP_FAILURE_RETRY(open(rec->blk_device, O_RDONLY | O_CLOEXEC)));
- if (!fd) {
- PERROR << "Cannot open device " << rec->blk_device;
+ if (fs_mgr_is_checkpoint_blk(rec)) {
+ call_vdc({"checkpoint", "restoreCheckpoint", rec->blk_device});
+ }
+
+ if (needs_checkpoint_ == UNKNOWN &&
+ !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &needs_checkpoint_)) {
+ LERROR << "Failed to find if checkpointing is needed. Assuming no.";
+ needs_checkpoint_ = NO;
+ }
+
+ if (needs_checkpoint_ != YES) {
+ return true;
+ }
+
+ if (!UpdateCheckpointPartition(rec)) {
+ LERROR << "Could not set up checkpoint partition, skipping!";
return false;
}
- uint64_t size = get_block_device_size(fd) / 512;
- if (!size) {
- PERROR << "Cannot get device size";
- return false;
+ return true;
+ }
+
+ bool Revert(struct fstab_rec* rec) {
+ if (!fs_mgr_is_checkpoint(rec)) {
+ return true;
}
- android::dm::DmTable table;
- if (!table.AddTarget(
- std::make_unique<android::dm::DmTargetBow>(0, size, rec->blk_device))) {
- LERROR << "Failed to add Bow target";
- return false;
+ if (device_map_.find(rec->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());
+ device_map_.erase(bow_device);
+
DeviceMapper& dm = DeviceMapper::Instance();
- if (!dm.CreateDevice("bow", table)) {
- PERROR << "Failed to create bow device";
- return false;
+ if (!dm.DeleteDevice("bow")) {
+ PERROR << "Failed to remove bow device";
}
- std::string name;
- if (!dm.GetDmDevicePathByName("bow", &name)) {
- PERROR << "Failed to get bow device name";
- return false;
- }
-
- rec->blk_device = strdup(name.c_str());
+ return true;
}
- return true;
-}
+
+ private:
+ bool UpdateCheckpointPartition(struct fstab_rec* rec) {
+ if (fs_mgr_is_checkpoint_fs(rec)) {
+ if (!strcmp(rec->fs_type, "f2fs")) {
+ std::string opts(rec->fs_options);
+
+ opts += ",checkpoint=disable";
+ free(rec->fs_options);
+ rec->fs_options = strdup(opts.c_str());
+ } else {
+ LERROR << rec->fs_type << " does not implement checkpoints.";
+ }
+ } else if (fs_mgr_is_checkpoint_blk(rec)) {
+ android::base::unique_fd fd(
+ TEMP_FAILURE_RETRY(open(rec->blk_device, O_RDONLY | O_CLOEXEC)));
+ if (!fd) {
+ PERROR << "Cannot open device " << rec->blk_device;
+ return false;
+ }
+
+ uint64_t size = get_block_device_size(fd) / 512;
+ if (!size) {
+ PERROR << "Cannot get device size";
+ return false;
+ }
+
+ android::dm::DmTable table;
+ if (!table.AddTarget(
+ std::make_unique<android::dm::DmTargetBow>(0, size, rec->blk_device))) {
+ LERROR << "Failed to add bow target";
+ return false;
+ }
+
+ DeviceMapper& dm = DeviceMapper::Instance();
+ if (!dm.CreateDevice("bow", table)) {
+ PERROR << "Failed to create bow device";
+ return false;
+ }
+
+ std::string name;
+ if (!dm.GetDmDevicePathByName("bow", &name)) {
+ PERROR << "Failed to get bow device name";
+ return false;
+ }
+
+ device_map_[name] = rec->blk_device;
+ free(rec->blk_device);
+ rec->blk_device = strdup(name.c_str());
+ }
+ return true;
+ }
+
+ enum { UNKNOWN = -1, NO = 0, YES = 1 };
+ int needs_checkpoint_;
+ 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
@@ -912,7 +973,7 @@
int mret = -1;
int mount_errno = 0;
int attempted_idx = -1;
- int need_checkpoint = -1;
+ CheckpointManager checkpoint_manager;
FsManagerAvbUniquePtr avb_handle(nullptr);
if (!fstab) {
@@ -959,16 +1020,8 @@
}
}
- if (fs_mgr_is_checkpoint(&fstab->recs[i])) {
- if (need_checkpoint == -1 &&
- !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &need_checkpoint)) {
- LERROR << "Failed to find if checkpointing is needed. Assuming no.";
- need_checkpoint = 0;
- }
- if (need_checkpoint == 1 && !fs_mgr_update_checkpoint_partition(&fstab->recs[i])) {
- LERROR << "Could not set up checkpoint partition, skipping!";
- continue;
- }
+ if (!checkpoint_manager.Update(&fstab->recs[i])) {
+ continue;
}
if (fstab->recs[i].fs_mgr_flags & MF_WAIT &&
@@ -1051,6 +1104,9 @@
<< " is wiped and " << fstab->recs[top_idx].mount_point
<< " " << fstab->recs[top_idx].fs_type
<< " is formattable. Format it.";
+
+ checkpoint_manager.Revert(&fstab->recs[top_idx]);
+
if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY);
@@ -1171,11 +1227,12 @@
* 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 need_checkpoint) {
+ char* tmp_mount_point, int needs_checkpoint) {
int i = 0;
int mount_errors = 0;
int first_mount_errno = 0;
char* mount_point;
+ CheckpointManager checkpoint_manager(needs_checkpoint);
FsManagerAvbUniquePtr avb_handle(nullptr);
if (!fstab) {
@@ -1204,16 +1261,9 @@
}
}
- if (fs_mgr_is_checkpoint(&fstab->recs[i])) {
- if (need_checkpoint == -1 &&
- !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &need_checkpoint)) {
- LERROR << "Failed to find if checkpointing is needed. Assuming no.";
- need_checkpoint = 0;
- }
- if (need_checkpoint == 1 && !fs_mgr_update_checkpoint_partition(&fstab->recs[i])) {
- LERROR << "Could not set up checkpoint partition, skipping!";
- continue;
- }
+ if (!checkpoint_manager.Update(&fstab->recs[i])) {
+ LERROR << "Could not set up checkpoint partition, skipping!";
+ continue;
}
/* First check the filesystem if requested */
@@ -1290,8 +1340,8 @@
}
int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
- bool needs_cp) {
- return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_cp);
+ bool needs_checkpoint) {
+ return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_checkpoint);
}
/*
@@ -1499,16 +1549,17 @@
bool system_root = android::base::GetProperty("ro.build.system_root_image", "") == "true";
for (int i = 0; i < fstab->num_entries; i++) {
- if (!fs_mgr_is_verified(&fstab->recs[i]) && !fs_mgr_is_avb(&fstab->recs[i])) {
+ auto fsrec = &fstab->recs[i];
+ if (!fs_mgr_is_verified(fsrec) && !fs_mgr_is_avb(fsrec)) {
continue;
}
std::string mount_point;
- if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) {
+ if (system_root && !strcmp(fsrec->mount_point, "/")) {
// In AVB, the dm device name is vroot instead of system.
- mount_point = fs_mgr_is_avb(&fstab->recs[i]) ? "vroot" : "system";
+ mount_point = fs_mgr_is_avb(fsrec) ? "vroot" : "system";
} else {
- mount_point = basename(fstab->recs[i].mount_point);
+ mount_point = basename(fsrec->mount_point);
}
if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
@@ -1516,15 +1567,14 @@
continue;
}
- const char* status = nullptr;
+ const char* status;
std::vector<DeviceMapper::TargetInfo> table;
if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) {
- if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
- status = "V";
- } else {
- PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point.c_str();
+ if (!fs_mgr_is_verifyatboot(fsrec)) {
+ PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point;
continue;
}
+ status = "V";
} else {
status = table[0].data.c_str();
}
@@ -1534,9 +1584,13 @@
// instead of [partition.vroot.verified].
if (mount_point == "vroot") mount_point = "system";
if (*status == 'C' || *status == 'V') {
- callback(&fstab->recs[i], mount_point.c_str(), mode, *status);
+ callback(fsrec, mount_point.c_str(), mode, *status);
}
}
return true;
}
+
+std::string fs_mgr_get_super_partition_name(int /* slot */) {
+ return LP_METADATA_DEFAULT_PARTITION_NAME;
+}
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index ee63d60..a97369a 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -29,6 +29,7 @@
#include <sys/vfs.h>
#include <unistd.h>
+#include <algorithm>
#include <map>
#include <memory>
#include <string>
@@ -42,10 +43,12 @@
#include <ext4_utils/ext4_utils.h>
#include <fs_mgr_overlayfs.h>
#include <fstab/fstab.h>
+#include <libdm/dm.h>
#include "fs_mgr_priv.h"
using namespace std::literals;
+using namespace android::dm;
#if ALLOW_ADBD_DISABLE_VERITY == 0 // If we are a user build, provide stubs
@@ -53,6 +56,10 @@
return false;
}
+std::vector<std::string> fs_mgr_overlayfs_required_devices(const fstab*) {
+ return {};
+}
+
bool fs_mgr_overlayfs_setup(const char*, const char*, bool* change) {
if (change) *change = false;
return false;
@@ -173,9 +180,16 @@
return "/system";
}
+bool fs_mgr_access(const std::string& path) {
+ auto save_errno = errno;
+ auto ret = access(path.c_str(), F_OK) == 0;
+ errno = save_errno;
+ return ret;
+}
+
// return true if system supports overlayfs
bool fs_mgr_wants_overlayfs() {
- // This will return empty on init first_stage_mount, so speculative
+ // Properties will return empty on init first_stage_mount, so speculative
// determination, empty (unset) _or_ "1" is true which differs from the
// official ro.debuggable policy. ALLOW_ADBD_DISABLE_VERITY == 0 should
// protect us from false in any case, so this is insurance.
@@ -183,13 +197,7 @@
if (debuggable != "1") return false;
// Overlayfs available in the kernel, and patched for override_creds?
- static signed char overlayfs_in_kernel = -1; // cache for constant condition
- if (overlayfs_in_kernel == -1) {
- auto save_errno = errno;
- overlayfs_in_kernel = !access("/sys/module/overlay/parameters/override_creds", F_OK);
- errno = save_errno;
- }
- return overlayfs_in_kernel;
+ return fs_mgr_access("/sys/module/overlay/parameters/override_creds");
}
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point) {
@@ -217,13 +225,12 @@
return false;
}
-bool fs_mgr_overlayfs_verity_enabled(const std::string& basename_mount_point) {
- auto found = false;
- fs_mgr_update_verity_state(
- [&basename_mount_point, &found](fstab_rec*, const char* mount_point, int, int) {
- if (mount_point && (basename_mount_point == mount_point)) found = true;
- });
- return found;
+std::vector<std::string> fs_mgr_overlayfs_verity_enabled_list() {
+ std::vector<std::string> ret;
+ fs_mgr_update_verity_state([&ret](fstab_rec*, const char* mount_point, int, int) {
+ ret.emplace_back(mount_point);
+ });
+ return ret;
}
bool fs_mgr_wants_overlayfs(const fstab_rec* fsrec) {
@@ -249,7 +256,7 @@
if (!fs_mgr_overlayfs_enabled(fsrec)) return false;
- return !fs_mgr_overlayfs_verity_enabled(android::base::Basename(fsrec_mount_point));
+ return true;
}
bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr) {
@@ -294,6 +301,28 @@
constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
+bool fs_mgr_overlayfs_setup_dir(const std::string& dir, std::string* overlay, bool* change) {
+ auto ret = true;
+ auto top = dir + kOverlayTopDir;
+ if (setfscreatecon(kOverlayfsFileContext)) {
+ ret = false;
+ PERROR << "setfscreatecon " << kOverlayfsFileContext;
+ }
+ auto save_errno = errno;
+ if (!mkdir(top.c_str(), 0755)) {
+ if (change) *change = true;
+ } else if (errno != EEXIST) {
+ ret = false;
+ PERROR << "mkdir " << top;
+ } else {
+ errno = save_errno;
+ }
+ setfscreatecon(nullptr);
+
+ if (overlay) *overlay = std::move(top);
+ return ret;
+}
+
bool fs_mgr_overlayfs_setup_one(const std::string& overlay, const std::string& mount_point,
bool* change) {
auto ret = true;
@@ -347,15 +376,14 @@
bool fs_mgr_overlayfs_teardown_one(const std::string& overlay, const std::string& mount_point,
bool* change) {
const auto top = overlay + kOverlayTopDir;
- auto save_errno = errno;
- auto missing = access(top.c_str(), F_OK);
- errno = save_errno;
- if (missing) return false;
- const auto oldpath = top + (mount_point.empty() ? "" : ("/"s + mount_point));
+ if (!fs_mgr_access(top)) return false;
+
+ auto cleanup_all = mount_point.empty();
+ const auto oldpath = top + (cleanup_all ? "" : ("/"s + mount_point));
const auto newpath = oldpath + ".teardown";
auto ret = fs_mgr_rm_all(newpath);
- save_errno = errno;
+ auto save_errno = errno;
if (!rename(oldpath.c_str(), newpath.c_str())) {
if (change) *change = true;
} else if (errno != ENOENT) {
@@ -374,7 +402,7 @@
} else {
errno = save_errno;
}
- if (!mount_point.empty()) {
+ if (!cleanup_all) {
save_errno = errno;
if (!rmdir(top.c_str())) {
if (change) *change = true;
@@ -419,11 +447,16 @@
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(fstab, fsrec->mount_point));
if (mount_point && (new_mount_point != mount_point)) continue;
+ if (std::find(verity.begin(), verity.end(), android::base::Basename(new_mount_point)) !=
+ verity.end()) {
+ continue;
+ }
auto duplicate_or_more_specific = false;
for (auto it = mounts.begin(); it != mounts.end();) {
if ((*it == new_mount_point) ||
@@ -439,15 +472,35 @@
}
if (!duplicate_or_more_specific) mounts.emplace_back(new_mount_point);
}
- // if not itemized /system or /, system as root, fake up
- // fs_mgr_wants_overlayfs evaluation of /system as candidate.
- if ((std::find(mounts.begin(), mounts.end(), "/system") == mounts.end()) &&
- !fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), "/") &&
- !fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), "/system") &&
- !fs_mgr_overlayfs_verity_enabled("system")) {
- mounts.emplace_back("/system");
+ // if not itemized /system or /, system as root, fake one up?
+
+ // do we want or need to?
+ if (mount_point && ("/system"s != mount_point)) return mounts;
+ if (std::find(mounts.begin(), mounts.end(), "/system") != mounts.end()) return mounts;
+
+ // fs_mgr_overlayfs_verity_enabled_list says not to?
+ 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")) {
+ return mounts;
+ }
+
+ // Manually check dm state because stunted fstab (w/o system as root) borken
+ auto& dm = DeviceMapper::Instance();
+ auto found = false;
+ for (auto& system : {"system", "vroot"}) {
+ if (dm.GetState(system) == DmDeviceState::INVALID) continue;
+ std::vector<DeviceMapper::TargetInfo> table;
+ found = !dm.GetTableStatus(system, &table) || table.empty() || table[0].data.empty() ||
+ (table[0].data[0] == 'C') || (table[0].data[0] == 'V');
+ if (found) break;
+ }
+ if (!found) mounts.emplace_back("/system");
return mounts;
}
@@ -467,6 +520,10 @@
return ret;
}
+std::vector<std::string> fs_mgr_overlayfs_required_devices(const fstab*) {
+ return {};
+}
+
// 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) {
@@ -489,19 +546,9 @@
auto mounts = fs_mgr_candidate_list(fstab.get(), fs_mgr_mount_point(fstab.get(), mount_point));
if (fstab && mounts.empty()) return ret;
- if (setfscreatecon(kOverlayfsFileContext)) {
- PERROR << "setfscreatecon " << kOverlayfsFileContext;
- }
- auto overlay = kOverlayMountPoint + kOverlayTopDir;
- auto save_errno = errno;
- if (!mkdir(overlay.c_str(), 0755)) {
- if (change) *change = true;
- } else if (errno != EEXIST) {
- PERROR << "mkdir " << overlay;
- } else {
- errno = save_errno;
- }
- setfscreatecon(nullptr);
+ std::string overlay;
+ ret |= fs_mgr_overlayfs_setup_dir(kOverlayMountPoint, &overlay, change);
+
if (!fstab && mount_point && fs_mgr_overlayfs_setup_one(overlay, mount_point, change)) {
ret = true;
}
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index cee069b..a4544b2 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -23,6 +23,7 @@
#include <linux/dm-ioctl.h>
#include <functional>
+#include <string>
#include <fstab/fstab.h>
@@ -89,4 +90,9 @@
#define FS_MGR_SETUP_VERITY_SUCCESS 0
int fs_mgr_setup_verity(struct fstab_rec *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
+// returned. Otherwise, it will use the current slot.
+std::string fs_mgr_get_super_partition_name(int slot = -1);
+
#endif /* __CORE_FS_MGR_H */
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index 251dd9b..3274e0e 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -19,8 +19,10 @@
#include <fstab/fstab.h>
#include <string>
+#include <vector>
bool fs_mgr_overlayfs_mount_all(const fstab* fstab);
+std::vector<std::string> fs_mgr_overlayfs_required_devices(const 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/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index cc61917..70823c6 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -59,7 +59,8 @@
: dm_(DeviceMapper::Instance()), name_(name), valid_(false) {
valid_ = dm_.CreateDevice(name, table);
}
- TempDevice(TempDevice&& other) : dm_(other.dm_), name_(other.name_), valid_(other.valid_) {
+ TempDevice(TempDevice&& other) noexcept
+ : dm_(other.dm_), name_(other.name_), valid_(other.valid_) {
other.valid_ = false;
}
~TempDevice() {
@@ -103,7 +104,7 @@
TempDevice(const TempDevice&) = delete;
TempDevice& operator=(const TempDevice&) = delete;
- TempDevice& operator=(TempDevice&& other) {
+ TempDevice& operator=(TempDevice&& other) noexcept {
name_ = other.name_;
valid_ = other.valid_;
other.valid_ = false;
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index 89282db..69dc065 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -35,7 +35,6 @@
"libcrypto",
"libcrypto_utils",
"libsparse",
- "libext2_uuid",
"libext4_utils",
"libz",
],
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index d9a0e9c..97b15bd 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -25,7 +25,6 @@
#include <algorithm>
#include <android-base/unique_fd.h>
-#include <uuid/uuid.h>
#include "liblp/liblp.h"
#include "reader.h"
@@ -79,9 +78,8 @@
out->extents.push_back(LpMetadataExtent{num_sectors_, LP_TARGET_TYPE_ZERO, 0});
}
-Partition::Partition(const std::string& name, const std::string& group_name,
- const std::string& guid, uint32_t attributes)
- : name_(name), group_name_(group_name), guid_(guid), attributes_(attributes), size_(0) {}
+Partition::Partition(const std::string& name, const std::string& group_name, uint32_t attributes)
+ : name_(name), group_name_(group_name), attributes_(attributes), size_(0) {}
void Partition::AddExtent(std::unique_ptr<Extent>&& extent) {
size_ += extent->num_sectors() * LP_SECTOR_SIZE;
@@ -202,8 +200,8 @@
for (const auto& partition : metadata.partitions) {
std::string group_name = GetPartitionGroupName(metadata.groups[partition.group_index]);
- Partition* builder = AddPartition(GetPartitionName(partition), group_name,
- GetPartitionGuid(partition), partition.attributes);
+ Partition* builder =
+ AddPartition(GetPartitionName(partition), group_name, partition.attributes);
if (!builder) {
return false;
}
@@ -329,13 +327,12 @@
return true;
}
-Partition* MetadataBuilder::AddPartition(const std::string& name, const std::string& guid,
- uint32_t attributes) {
- return AddPartition(name, "default", guid, attributes);
+Partition* MetadataBuilder::AddPartition(const std::string& name, uint32_t attributes) {
+ return AddPartition(name, "default", attributes);
}
Partition* MetadataBuilder::AddPartition(const std::string& name, const std::string& group_name,
- const std::string& guid, uint32_t attributes) {
+ uint32_t attributes) {
if (name.empty()) {
LERROR << "Partition must have a non-empty name.";
return nullptr;
@@ -348,7 +345,7 @@
LERROR << "Could not find partition group: " << group_name;
return nullptr;
}
- partitions_.push_back(std::make_unique<Partition>(name, group_name, guid, attributes));
+ partitions_.push_back(std::make_unique<Partition>(name, group_name, attributes));
return partitions_.back().get();
}
@@ -549,12 +546,6 @@
}
strncpy(part.name, partition->name().c_str(), sizeof(part.name));
- if (uuid_parse(partition->guid().c_str(), part.guid) != 0) {
- LERROR << "Could not parse guid " << partition->guid() << " for partition "
- << partition->name();
- return nullptr;
- }
-
part.first_extent_index = static_cast<uint32_t>(metadata->extents.size());
part.num_extents = static_cast<uint32_t>(partition->extents().size());
part.attributes = partition->attributes();
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index 711cc64..c916b44 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -22,16 +22,12 @@
using namespace std;
using namespace android::fs_mgr;
-static const char* TEST_GUID = "A799D1D6-669F-41D8-A3F0-EBB7572D8302";
-static const char* TEST_GUID2 = "A799D1D6-669F-41D8-A3F0-EBB7572D8303";
-
TEST(liblp, BuildBasic) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
- Partition* partition = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ Partition* partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(partition, nullptr);
EXPECT_EQ(partition->name(), "system");
- EXPECT_EQ(partition->guid(), TEST_GUID);
EXPECT_EQ(partition->attributes(), LP_PARTITION_ATTR_READONLY);
EXPECT_EQ(partition->size(), 0);
EXPECT_EQ(builder->FindPartition("system"), partition);
@@ -43,7 +39,7 @@
TEST(liblp, ResizePartition) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
EXPECT_EQ(builder->ResizePartition(system, 65536), true);
EXPECT_EQ(system->size(), 65536);
@@ -94,7 +90,7 @@
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
// Test that we align up to one sector.
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
EXPECT_EQ(builder->ResizePartition(system, 10000), true);
EXPECT_EQ(system->size(), 12288);
@@ -171,9 +167,9 @@
BlockDeviceInfo device_info(512 * 1024 * 1024, 768 * 1024, 753664, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 32 * 1024, 2);
- Partition* a = builder->AddPartition("a", TEST_GUID, 0);
+ Partition* a = builder->AddPartition("a", 0);
ASSERT_NE(a, nullptr);
- Partition* b = builder->AddPartition("b", TEST_GUID2, 0);
+ Partition* b = builder->AddPartition("b", 0);
ASSERT_NE(b, nullptr);
// Add a bunch of small extents to each, interleaving.
@@ -214,7 +210,7 @@
EXPECT_EQ(builder->AllocatableSpace(), allocatable);
EXPECT_EQ(builder->UsedSpace(), 0);
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
EXPECT_EQ(builder->ResizePartition(system, allocatable), true);
EXPECT_EQ(system->size(), allocatable);
@@ -229,8 +225,8 @@
TEST(liblp, BuildComplex) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
- Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
+ Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
ASSERT_NE(vendor, nullptr);
EXPECT_EQ(builder->ResizePartition(system, 65536), true);
@@ -263,15 +259,15 @@
TEST(liblp, AddInvalidPartition) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
- Partition* partition = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ Partition* partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(partition, nullptr);
// Duplicate name.
- partition = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
EXPECT_EQ(partition, nullptr);
// Empty name.
- partition = builder->AddPartition("", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ partition = builder->AddPartition("", LP_PARTITION_ATTR_READONLY);
EXPECT_EQ(partition, nullptr);
}
@@ -282,8 +278,8 @@
unique_ptr<MetadataBuilder> builder =
MetadataBuilder::New(kDiskSize, kMetadataSize, kMetadataSlots);
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
- Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
+ Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
ASSERT_NE(vendor, nullptr);
EXPECT_EQ(builder->ResizePartition(system, 65536), true);
@@ -322,7 +318,6 @@
for (const auto& partition : exported->partitions) {
Partition* original = builder->FindPartition(GetPartitionName(partition));
ASSERT_NE(original, nullptr);
- EXPECT_EQ(original->guid(), GetPartitionGuid(partition));
for (size_t i = 0; i < partition.num_extents; i++) {
const auto& extent = exported->extents[partition.first_extent_index + i];
LinearExtent* original_extent = original->extents()[i]->AsLinearExtent();
@@ -337,8 +332,8 @@
TEST(liblp, BuilderImport) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
- Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
+ Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
ASSERT_NE(vendor, nullptr);
EXPECT_EQ(builder->ResizePartition(system, 65536), true);
@@ -357,11 +352,9 @@
EXPECT_EQ(system->size(), 98304);
ASSERT_EQ(system->extents().size(), 2);
- EXPECT_EQ(system->guid(), TEST_GUID);
EXPECT_EQ(system->attributes(), LP_PARTITION_ATTR_READONLY);
EXPECT_EQ(vendor->size(), 32768);
ASSERT_EQ(vendor->extents().size(), 1);
- EXPECT_EQ(vendor->guid(), TEST_GUID2);
EXPECT_EQ(vendor->attributes(), LP_PARTITION_ATTR_READONLY);
LinearExtent* system1 = system->extents()[0]->AsLinearExtent();
@@ -378,17 +371,7 @@
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
std::string name = "abcdefghijklmnopqrstuvwxyz0123456789";
- Partition* system = builder->AddPartition(name + name, TEST_GUID, LP_PARTITION_ATTR_READONLY);
- EXPECT_NE(system, nullptr);
-
- unique_ptr<LpMetadata> exported = builder->Export();
- EXPECT_EQ(exported, nullptr);
-}
-
-TEST(liblp, ExportInvalidGuid) {
- unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
-
- Partition* system = builder->AddPartition("system", "bad", LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition(name + name, LP_PARTITION_ATTR_READONLY);
EXPECT_NE(system, nullptr);
unique_ptr<LpMetadata> exported = builder->Export();
@@ -483,7 +466,7 @@
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
ASSERT_NE(builder, nullptr);
- Partition* partition = builder->AddPartition("system", TEST_GUID, 0);
+ Partition* partition = builder->AddPartition("system", 0);
ASSERT_NE(partition, nullptr);
ASSERT_TRUE(builder->ResizePartition(partition, 512));
EXPECT_EQ(partition->size(), 4096);
@@ -511,7 +494,7 @@
ASSERT_TRUE(builder->AddGroup("google", 16384));
- Partition* partition = builder->AddPartition("system", "google", TEST_GUID, 0);
+ Partition* partition = builder->AddPartition("system", "google", 0);
ASSERT_NE(partition, nullptr);
EXPECT_TRUE(builder->ResizePartition(partition, 8192));
EXPECT_EQ(partition->size(), 8192);
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index f1edee7..a6044d0 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -112,8 +112,7 @@
friend class MetadataBuilder;
public:
- Partition(const std::string& name, const std::string& group_name, const std::string& guid,
- uint32_t attributes);
+ Partition(const std::string& name, const std::string& group_name, uint32_t attributes);
// Add a raw extent.
void AddExtent(std::unique_ptr<Extent>&& extent);
@@ -128,7 +127,6 @@
const std::string& name() const { return name_; }
const std::string& group_name() const { return group_name_; }
uint32_t attributes() const { return attributes_; }
- const std::string& guid() const { return guid_; }
const std::vector<std::unique_ptr<Extent>>& extents() const { return extents_; }
uint64_t size() const { return size_; }
@@ -137,7 +135,6 @@
std::string name_;
std::string group_name_;
- std::string guid_;
std::vector<std::unique_ptr<Extent>> extents_;
uint32_t attributes_;
uint64_t size_;
@@ -190,11 +187,11 @@
// Add a partition, returning a handle so it can be sized as needed. If a
// partition with the given name already exists, nullptr is returned.
Partition* AddPartition(const std::string& name, const std::string& group_name,
- const std::string& guid, uint32_t attributes);
+ uint32_t attributes);
// Same as AddPartition above, but uses the default partition group which
// has no size restrictions.
- Partition* AddPartition(const std::string& name, const std::string& guid, uint32_t attributes);
+ Partition* AddPartition(const std::string& name, uint32_t attributes);
// Delete a partition by name if it exists.
void RemovePartition(const std::string& name);
diff --git a/fs_mgr/liblp/include/liblp/liblp.h b/fs_mgr/liblp/include/liblp/liblp.h
index 51d262b..5f95dca 100644
--- a/fs_mgr/liblp/include/liblp/liblp.h
+++ b/fs_mgr/liblp/include/liblp/liblp.h
@@ -68,7 +68,6 @@
// Helper to extract safe C++ strings from partition info.
std::string GetPartitionName(const LpMetadataPartition& partition);
-std::string GetPartitionGuid(const LpMetadataPartition& partition);
std::string GetPartitionGroupName(const LpMetadataPartitionGroup& group);
// Helper to return a slot number for a slot suffix.
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index 79ef2ab..7d1a2a9 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -38,7 +38,7 @@
#define LP_METADATA_HEADER_MAGIC 0x414C5030
/* Current metadata version. */
-#define LP_METADATA_MAJOR_VERSION 2
+#define LP_METADATA_MAJOR_VERSION 3
#define LP_METADATA_MINOR_VERSION 0
/* Attributes for the LpMetadataPartition::attributes field.
@@ -67,7 +67,7 @@
* | Geometry Backup |
* +--------------------+
*/
-#define LP_METADATA_PARTITION_NAME "super"
+#define LP_METADATA_DEFAULT_PARTITION_NAME "super"
/* Size of a sector is always 512 bytes for compatibility with the Linux kernel. */
#define LP_SECTOR_SIZE 512
@@ -232,23 +232,20 @@
*/
char name[36];
- /* 36: Globally unique identifier (GUID) of this partition. */
- uint8_t guid[16];
-
- /* 52: Attributes for the partition (see LP_PARTITION_ATTR_* flags above). */
+ /* 36: Attributes for the partition (see LP_PARTITION_ATTR_* flags above). */
uint32_t attributes;
- /* 56: Index of the first extent owned by this partition. The extent will
+ /* 40: Index of the first extent owned by this partition. The extent will
* start at logical sector 0. Gaps between extents are not allowed.
*/
uint32_t first_extent_index;
- /* 60: Number of extents in the partition. Every partition must have at
+ /* 44: Number of extents in the partition. Every partition must have at
* least one extent.
*/
uint32_t num_extents;
- /* 64: Group this partition belongs to. */
+ /* 48: Group this partition belongs to. */
uint32_t group_index;
} __attribute__((packed)) LpMetadataPartition;
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index f93852b..01de3ac 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -37,8 +37,6 @@
static const size_t kDiskSize = 131072;
static const size_t kMetadataSize = 512;
static const size_t kMetadataSlots = 2;
-static const char* TEST_GUID_BASE = "A799D1D6-669F-41D8-A3F0-EBB7572D830";
-static const char* TEST_GUID = "A799D1D6-669F-41D8-A3F0-EBB7572D8302";
// Helper function for creating an in-memory file descriptor. This lets us
// simulate read/writing logical partition metadata as if we had a block device
@@ -81,7 +79,7 @@
}
static bool AddDefaultPartitions(MetadataBuilder* builder) {
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_NONE);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_NONE);
if (!system) {
return false;
}
@@ -171,7 +169,6 @@
// Check partition tables.
ASSERT_EQ(exported->partitions.size(), imported->partitions.size());
EXPECT_EQ(GetPartitionName(exported->partitions[0]), GetPartitionName(imported->partitions[0]));
- EXPECT_EQ(GetPartitionGuid(exported->partitions[0]), GetPartitionGuid(imported->partitions[0]));
EXPECT_EQ(exported->partitions[0].attributes, imported->partitions[0].attributes);
EXPECT_EQ(exported->partitions[0].first_extent_index,
imported->partitions[0].first_extent_index);
@@ -331,18 +328,18 @@
unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
ASSERT_NE(builder, nullptr);
- // Compute the maximum number of partitions we can fit in 1024 bytes of metadata.
- size_t max_partitions = (kMetadataSize - sizeof(LpMetadataHeader)) / sizeof(LpMetadataPartition);
- EXPECT_LT(max_partitions, 10);
+ // Compute the maximum number of partitions we can fit in 512 bytes of
+ // metadata. By default there is the header, and one partition group.
+ static const size_t kMaxPartitionTableSize =
+ kMetadataSize - sizeof(LpMetadataHeader) - sizeof(LpMetadataPartitionGroup);
+ size_t max_partitions = kMaxPartitionTableSize / sizeof(LpMetadataPartition);
// Add this number of partitions.
Partition* partition = nullptr;
for (size_t i = 0; i < max_partitions; i++) {
- std::string guid = std::string(TEST_GUID) + to_string(i);
- partition = builder->AddPartition(to_string(i), TEST_GUID, LP_PARTITION_ATTR_NONE);
+ partition = builder->AddPartition(to_string(i), LP_PARTITION_ATTR_NONE);
ASSERT_NE(partition, nullptr);
}
- ASSERT_NE(partition, nullptr);
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
@@ -354,7 +351,7 @@
ASSERT_TRUE(FlashPartitionTable(fd, *exported.get()));
// Check that adding one more partition overflows the metadata allotment.
- partition = builder->AddPartition("final", TEST_GUID, LP_PARTITION_ATTR_NONE);
+ partition = builder->AddPartition("final", LP_PARTITION_ATTR_NONE);
EXPECT_NE(partition, nullptr);
exported = builder->Export();
diff --git a/fs_mgr/liblp/utility.cpp b/fs_mgr/liblp/utility.cpp
index a590037..b08f96c 100644
--- a/fs_mgr/liblp/utility.cpp
+++ b/fs_mgr/liblp/utility.cpp
@@ -23,7 +23,6 @@
#include <android-base/file.h>
#include <ext4_utils/ext4_utils.h>
#include <openssl/sha.h>
-#include <uuid/uuid.h>
#include "utility.h"
@@ -80,15 +79,6 @@
SHA256_Final(out, &c);
}
-std::string GetPartitionGuid(const LpMetadataPartition& partition) {
- // 32 hex characters, four hyphens. Unfortunately libext2_uuid provides no
- // macro to assist with buffer sizing.
- static const size_t kGuidLen = 36;
- char buffer[kGuidLen + 1];
- uuid_unparse_upper(partition.guid, buffer);
- return buffer;
-}
-
uint32_t SlotNumberForSlotSuffix(const std::string& suffix) {
if (suffix.empty()) {
return 0;
diff --git a/gatekeeperd/IGateKeeperService.cpp b/gatekeeperd/IGateKeeperService.cpp
index 1c339f4..43d5708 100644
--- a/gatekeeperd/IGateKeeperService.cpp
+++ b/gatekeeperd/IGateKeeperService.cpp
@@ -70,7 +70,7 @@
} else {
reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
}
- return NO_ERROR;
+ return OK;
}
case VERIFY: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
@@ -102,7 +102,7 @@
} else {
reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
}
- return NO_ERROR;
+ return OK;
}
case VERIFY_CHALLENGE: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
@@ -141,7 +141,7 @@
} else {
reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
}
- return NO_ERROR;
+ return OK;
}
case GET_SECURE_USER_ID: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
@@ -149,20 +149,20 @@
uint64_t sid = getSecureUserId(uid);
reply->writeNoException();
reply->writeInt64(sid);
- return NO_ERROR;
+ return OK;
}
case CLEAR_SECURE_USER_ID: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
uint32_t uid = data.readInt32();
clearSecureUserId(uid);
reply->writeNoException();
- return NO_ERROR;
+ return OK;
}
case REPORT_DEVICE_SETUP_COMPLETE: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
reportDeviceSetupComplete();
reply->writeNoException();
- return NO_ERROR;
+ return OK;
}
default:
return BBinder::onTransact(code, data, reply, flags);
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 5f3ce36..f2818f3 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -386,7 +386,7 @@
write(fd, result, strlen(result) + 1);
}
- return NO_ERROR;
+ return OK;
}
private:
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 80c5afe..2a5667c 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -357,7 +357,7 @@
if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryChargeCounterPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -367,7 +367,7 @@
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryCurrentNowPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -377,7 +377,7 @@
if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryCurrentAvgPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -387,7 +387,7 @@
if (!mHealthdConfig->batteryCapacityPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryCapacityPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -403,7 +403,7 @@
case BATTERY_PROP_BATTERY_STATUS:
val->valueInt64 = getChargeStatus();
- ret = NO_ERROR;
+ ret = OK;
break;
default:
diff --git a/init/README.md b/init/README.md
index b45da21..02a65d5 100644
--- a/init/README.md
+++ b/init/README.md
@@ -262,6 +262,13 @@
> Scheduling priority of the service process. This value has to be in range
-20 to 19. Default priority is 0. Priority is set via setpriority().
+`restart_period <seconds>`
+> If a non-oneshot service exits, it will be restarted at its start time plus
+ this period. It defaults to 5s to rate limit crashing services.
+ This can be increased for services that are meant to run periodically. For
+ example, it may be set to 3600 to indicate that the service should run every hour
+ or 86400 to indicate that the service should run every day.
+
`rlimit <resource> <cur> <max>`
> This applies the given rlimit to the service. rlimits are inherited by child
processes, so this effectively applies the given rlimit to the process tree
@@ -298,6 +305,12 @@
seclabel or computed based on the service executable file security context.
For native executables see libcutils android\_get\_control\_socket().
+`timeout_period <seconds>`
+> Provide a timeout after which point the service will be killed. The oneshot keyword is respected
+ here, so oneshot services do not automatically restart, however all other services will.
+ This is particularly useful for creating a periodic service combined with the restart_period
+ option described above.
+
`user <username>`
> Change to 'username' before exec'ing this service.
Currently defaults to root. (??? probably should default to nobody)
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 6f97d19..eb86eb0 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -83,6 +83,7 @@
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_;
UeventListener uevent_listener_;
};
@@ -153,6 +154,8 @@
device_handler_ = std::make_unique<DeviceHandler>(
std::vector<Permissions>{}, std::vector<SysfsPermissions>{}, std::vector<Subsystem>{},
std::move(boot_devices), false);
+
+ super_partition_name_ = fs_mgr_get_super_partition_name();
}
std::unique_ptr<FirstStageMount> FirstStageMount::Create() {
@@ -196,7 +199,7 @@
return true;
}
- required_devices_partition_names_.emplace(LP_METADATA_PARTITION_NAME);
+ required_devices_partition_names_.emplace(super_partition_name_);
return true;
}
@@ -262,7 +265,7 @@
if (lp_metadata_partition_.empty()) {
LOG(ERROR) << "Could not locate logical partition tables in partition "
- << LP_METADATA_PARTITION_NAME;
+ << super_partition_name_;
return false;
}
return android::fs_mgr::CreateLogicalPartitions(lp_metadata_partition_);
@@ -275,7 +278,7 @@
auto iter = required_devices_partition_names_.find(name);
if (iter != required_devices_partition_names_.end()) {
LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << *iter;
- if (IsDmLinearEnabled() && name == LP_METADATA_PARTITION_NAME) {
+ if (IsDmLinearEnabled() && name == super_partition_name_) {
std::vector<std::string> links = device_handler_->GetBlockDeviceSymlinks(uevent);
lp_metadata_partition_ = links[0];
}
@@ -388,6 +391,12 @@
}
}
+ // heads up for instantiating required device(s) for overlayfs logic
+ const auto devices = fs_mgr_overlayfs_required_devices(device_tree_fstab_.get());
+ for (auto const& device : devices) {
+ InitMappedDevice(device);
+ }
+
fs_mgr_overlayfs_mount_all(device_tree_fstab_.get());
return true;
diff --git a/init/init.cpp b/init/init.cpp
index 47cfe32..42ec88c 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -187,23 +187,34 @@
}
}
-static std::optional<boot_clock::time_point> RestartProcesses() {
- std::optional<boot_clock::time_point> next_process_restart_time;
+static std::optional<boot_clock::time_point> HandleProcessActions() {
+ std::optional<boot_clock::time_point> next_process_action_time;
for (const auto& s : ServiceList::GetInstance()) {
+ if ((s->flags() & SVC_RUNNING) && s->timeout_period()) {
+ auto timeout_time = s->time_started() + *s->timeout_period();
+ if (boot_clock::now() > timeout_time) {
+ s->Timeout();
+ } else {
+ if (!next_process_action_time || timeout_time < *next_process_action_time) {
+ next_process_action_time = timeout_time;
+ }
+ }
+ }
+
if (!(s->flags() & SVC_RESTARTING)) continue;
- auto restart_time = s->time_started() + 5s;
+ auto restart_time = s->time_started() + s->restart_period();
if (boot_clock::now() > restart_time) {
if (auto result = s->Start(); !result) {
LOG(ERROR) << "Could not restart process '" << s->name() << "': " << result.error();
}
} else {
- if (!next_process_restart_time || restart_time < *next_process_restart_time) {
- next_process_restart_time = restart_time;
+ if (!next_process_action_time || restart_time < *next_process_action_time) {
+ next_process_action_time = restart_time;
}
}
}
- return next_process_restart_time;
+ return next_process_action_time;
}
static Result<Success> DoControlStart(Service* service) {
@@ -570,23 +581,6 @@
RebootSystem(ANDROID_RB_RESTART2, "bootloader");
}
-static void InitKernelLogging(char* argv[]) {
- // Make stdin/stdout/stderr all point to /dev/null.
- int fd = open("/sys/fs/selinux/null", O_RDWR);
- if (fd == -1) {
- int saved_errno = errno;
- android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
- errno = saved_errno;
- PLOG(FATAL) << "Couldn't open /sys/fs/selinux/null";
- }
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- if (fd > 2) close(fd);
-
- android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
-}
-
static void GlobalSeccomp() {
import_kernel_cmdline(false, [](const std::string& key, const std::string& value,
bool in_qemu) {
@@ -643,7 +637,8 @@
SetupSelinux(argv);
}
- InitKernelLogging(argv);
+ // We need to set up stdin/stdout/stderr again now that we're running in init's context.
+ InitKernelLogging(argv, InitAborter);
LOG(INFO) << "init second stage started!";
// Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
@@ -770,12 +765,12 @@
}
if (!(waiting_for_prop || Service::is_exec_service_running())) {
if (!shutting_down) {
- auto next_process_restart_time = RestartProcesses();
+ auto next_process_action_time = HandleProcessActions();
// If there's a process that needs restarting, wake up in time for that.
- if (next_process_restart_time) {
+ if (next_process_action_time) {
epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>(
- *next_process_restart_time - boot_clock::now());
+ *next_process_action_time - boot_clock::now());
if (*epoll_timeout < 0ms) epoll_timeout = 0ms;
}
}
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index 40706a1..d81ca5c 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -102,9 +102,11 @@
// Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
// talk to the outside world...
- android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) {
- RebootSystem(ANDROID_RB_RESTART2, "bootloader");
- });
+ // We need to set up stdin/stdout/stderr for child processes forked from first
+ // stage init as part of the mount process. This closes /dev/console if the
+ // kernel had previously opened it.
+ auto reboot_bootloader = [](const char*) { RebootSystem(ANDROID_RB_RESTART2, "bootloader"); };
+ InitKernelLogging(argv, reboot_bootloader);
if (!errors.empty()) {
for (const auto& [error_string, error_errno] : errors) {
diff --git a/init/keychords_test.cpp b/init/keychords_test.cpp
index c8c47a8..a3baeb1 100644
--- a/init/keychords_test.cpp
+++ b/init/keychords_test.cpp
@@ -47,9 +47,9 @@
public:
EventHandler();
EventHandler(const EventHandler&) = delete;
- EventHandler(EventHandler&&);
+ EventHandler(EventHandler&&) noexcept;
EventHandler& operator=(const EventHandler&) = delete;
- EventHandler& operator=(EventHandler&&);
+ EventHandler& operator=(EventHandler&&) noexcept;
~EventHandler() noexcept;
bool init();
@@ -64,11 +64,11 @@
EventHandler::EventHandler() : fd_(-1) {}
-EventHandler::EventHandler(EventHandler&& rval) : fd_(rval.fd_) {
+EventHandler::EventHandler(EventHandler&& rval) noexcept : fd_(rval.fd_) {
rval.fd_ = -1;
}
-EventHandler& EventHandler::operator=(EventHandler&& rval) {
+EventHandler& EventHandler::operator=(EventHandler&& rval) noexcept {
fd_ = rval.fd_;
rval.fd_ = -1;
return *this;
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 866f40e..d476336 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -307,15 +307,14 @@
auto shutdown_timeout = 0ms;
if (!SHUTDOWN_ZERO_TIMEOUT) {
- if (is_thermal_shutdown) {
- constexpr unsigned int thermal_shutdown_timeout = 1;
- shutdown_timeout = std::chrono::seconds(thermal_shutdown_timeout);
- } else {
- constexpr unsigned int shutdown_timeout_default = 6;
- auto shutdown_timeout_property = android::base::GetUintProperty(
- "ro.build.shutdown_timeout", shutdown_timeout_default);
- shutdown_timeout = std::chrono::seconds(shutdown_timeout_property);
+ constexpr unsigned int shutdown_timeout_default = 6;
+ constexpr unsigned int max_thermal_shutdown_timeout = 3;
+ auto shutdown_timeout_final = android::base::GetUintProperty("ro.build.shutdown_timeout",
+ shutdown_timeout_default);
+ if (is_thermal_shutdown && shutdown_timeout_final > max_thermal_shutdown_timeout) {
+ shutdown_timeout_final = max_thermal_shutdown_timeout;
}
+ shutdown_timeout = std::chrono::seconds(shutdown_timeout_final);
}
LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " ms";
diff --git a/init/service.cpp b/init/service.cpp
index d20e90a..a3e5953 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -627,6 +627,15 @@
return Success();
}
+Result<Success> Service::ParseRestartPeriod(const std::vector<std::string>& args) {
+ int period;
+ if (!ParseInt(args[1], &period, 5)) {
+ return Error() << "restart_period value must be an integer >= 5";
+ }
+ restart_period_ = std::chrono::seconds(period);
+ return Success();
+}
+
Result<Success> Service::ParseSeclabel(const std::vector<std::string>& args) {
seclabel_ = args[1];
return Success();
@@ -650,6 +659,15 @@
return Error() << "Invalid shutdown option";
}
+Result<Success> Service::ParseTimeoutPeriod(const std::vector<std::string>& args) {
+ int period;
+ if (!ParseInt(args[1], &period, 1)) {
+ return Error() << "timeout_period value must be an integer >= 1";
+ }
+ timeout_period_ = std::chrono::seconds(period);
+ return Success();
+}
+
template <typename T>
Result<Success> Service::AddDescriptor(const std::vector<std::string>& args) {
int perm = args.size() > 3 ? std::strtoul(args[3].c_str(), 0, 8) : -1;
@@ -757,12 +775,16 @@
{1, 1, &Service::ParseOomScoreAdjust}},
{"override", {0, 0, &Service::ParseOverride}},
{"priority", {1, 1, &Service::ParsePriority}},
+ {"restart_period",
+ {1, 1, &Service::ParseRestartPeriod}},
{"rlimit", {3, 3, &Service::ParseProcessRlimit}},
{"seclabel", {1, 1, &Service::ParseSeclabel}},
{"setenv", {2, 2, &Service::ParseSetenv}},
{"shutdown", {1, 1, &Service::ParseShutdown}},
{"sigstop", {0, 0, &Service::ParseSigstop}},
{"socket", {3, 6, &Service::ParseSocket}},
+ {"timeout_period",
+ {1, 1, &Service::ParseTimeoutPeriod}},
{"user", {1, 1, &Service::ParseUser}},
{"writepid", {1, kMax, &Service::ParseWritepid}},
};
@@ -1022,6 +1044,18 @@
}
}
+void Service::Timeout() {
+ // All process state flags will be taken care of in Reap(), we really just want to kill the
+ // process here when it times out. Oneshot processes will transition to be disabled, and
+ // all other processes will transition to be restarting.
+ LOG(INFO) << "Service '" << name_ << "' expired its timeout of " << timeout_period_->count()
+ << " seconds and will now be killed";
+ if (pid_) {
+ KillProcessGroup(SIGKILL);
+ NotifyStateChange("stopping");
+ }
+}
+
void Service::Restart() {
if (flags_ & SVC_RUNNING) {
/* Stop, wait, then start the service. */
diff --git a/init/service.h b/init/service.h
index ea79a07..e8d5ead 100644
--- a/init/service.h
+++ b/init/service.h
@@ -21,7 +21,9 @@
#include <sys/resource.h>
#include <sys/types.h>
+#include <chrono>
#include <memory>
+#include <optional>
#include <set>
#include <string>
#include <vector>
@@ -81,6 +83,7 @@
void Reset();
void Stop();
void Terminate();
+ void Timeout();
void Restart();
void Reap(const siginfo_t& siginfo);
void DumpState() const;
@@ -117,6 +120,8 @@
bool process_cgroup_empty() const { return process_cgroup_empty_; }
unsigned long start_order() const { return start_order_; }
void set_sigstop(bool value) { sigstop_ = value; }
+ std::chrono::seconds restart_period() const { return restart_period_; }
+ std::optional<std::chrono::seconds> timeout_period() const { return timeout_period_; }
const std::vector<std::string>& args() const { return args_; }
private:
@@ -153,11 +158,13 @@
Result<Success> ParseMemcgSwappiness(const std::vector<std::string>& args);
Result<Success> ParseNamespace(const std::vector<std::string>& args);
Result<Success> ParseProcessRlimit(const std::vector<std::string>& args);
+ Result<Success> ParseRestartPeriod(const std::vector<std::string>& args);
Result<Success> ParseSeclabel(const std::vector<std::string>& args);
Result<Success> ParseSetenv(const std::vector<std::string>& args);
Result<Success> ParseShutdown(const std::vector<std::string>& args);
Result<Success> ParseSigstop(const std::vector<std::string>& args);
Result<Success> ParseSocket(const std::vector<std::string>& args);
+ Result<Success> ParseTimeoutPeriod(const std::vector<std::string>& args);
Result<Success> ParseFile(const std::vector<std::string>& args);
Result<Success> ParseUser(const std::vector<std::string>& args);
Result<Success> ParseWritepid(const std::vector<std::string>& args);
@@ -220,6 +227,9 @@
bool sigstop_ = false;
+ std::chrono::seconds restart_period_ = 5s;
+ std::optional<std::chrono::seconds> timeout_period_;
+
std::vector<std::string> args_;
std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
diff --git a/init/util.cpp b/init/util.cpp
index 105ac87..3781141 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -436,5 +436,21 @@
return true;
}
+void InitKernelLogging(char** argv, std::function<void(const char*)> abort_function) {
+ // Make stdin/stdout/stderr all point to /dev/null.
+ int fd = open("/dev/null", O_RDWR);
+ if (fd == -1) {
+ int saved_errno = errno;
+ android::base::InitLogging(argv, &android::base::KernelLogger, std::move(abort_function));
+ errno = saved_errno;
+ PLOG(FATAL) << "Couldn't open /dev/null";
+ }
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+ if (fd > 2) close(fd);
+ android::base::InitLogging(argv, &android::base::KernelLogger, std::move(abort_function));
+}
+
} // namespace init
} // namespace android
diff --git a/init/util.h b/init/util.h
index 07e4864..53f4547 100644
--- a/init/util.h
+++ b/init/util.h
@@ -64,6 +64,8 @@
bool IsLegalPropertyName(const std::string& name);
+void InitKernelLogging(char** argv, std::function<void(const char*)> abort_function);
+
} // namespace init
} // namespace android
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 43bcd98..7f9a18a 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -116,10 +116,6 @@
target: {
linux_glibc: {
- // The host uses rosegment, which isn't supported yet.
- ldflags: [
- "-Wl,--no-rosegment",
- ],
// This forces the creation of eh_frame with unwind information
// for host.
cflags: [
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 3be8ad0..845c586 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -131,6 +131,7 @@
#define AID_SECURE_ELEMENT 1068 /* secure element subsystem */
#define AID_LMKD 1069 /* low memory killer daemon */
#define AID_LLKD 1070 /* live lock daemon */
+#define AID_IORAPD 1071 /* input/output readahead and pin daemon */
/* Changes to this file must be made in AOSP, *not* in internal branches. */
#define AID_SHELL 2000 /* adb and debug shell user */
diff --git a/libcutils/partition_utils.cpp b/libcutils/partition_utils.cpp
index 6735d6c..2211ff6 100644
--- a/libcutils/partition_utils.cpp
+++ b/libcutils/partition_utils.cpp
@@ -25,7 +25,7 @@
#include <cutils/properties.h>
-static int only_one_char(char *buf, int len, char c)
+static int only_one_char(uint8_t *buf, int len, uint8_t c)
{
int i, ret;
@@ -41,7 +41,7 @@
int partition_wiped(char *source)
{
- char buf[4096];
+ uint8_t buf[4096];
int fd, ret;
if ((fd = open(source, O_RDONLY)) < 0) {
diff --git a/liblog/event_tag_map.cpp b/liblog/event_tag_map.cpp
index 2e2bf87..574a386 100644
--- a/liblog/event_tag_map.cpp
+++ b/liblog/event_tag_map.cpp
@@ -72,7 +72,7 @@
explicit MapString(const std::string& str)
: alloc(new std::string(str)), str(alloc->data(), alloc->length()) {
}
- MapString(MapString&& rval)
+ MapString(MapString&& rval) noexcept
: alloc(rval.alloc), str(rval.data(), rval.length()) {
rval.alloc = NULL;
}
diff --git a/libmemunreachable/ScopedPipe.h b/libmemunreachable/ScopedPipe.h
index adabfd8..b9dead5 100644
--- a/libmemunreachable/ScopedPipe.h
+++ b/libmemunreachable/ScopedPipe.h
@@ -33,12 +33,12 @@
}
~ScopedPipe() { Close(); }
- ScopedPipe(ScopedPipe&& other) {
+ ScopedPipe(ScopedPipe&& other) noexcept {
SetReceiver(other.ReleaseReceiver());
SetSender(other.ReleaseSender());
}
- ScopedPipe& operator=(ScopedPipe&& other) {
+ ScopedPipe& operator=(ScopedPipe&& other) noexcept {
SetReceiver(other.ReleaseReceiver());
SetSender(other.ReleaseSender());
return *this;
diff --git a/libmemunreachable/Tarjan.h b/libmemunreachable/Tarjan.h
index 355679f..f3ab652 100644
--- a/libmemunreachable/Tarjan.h
+++ b/libmemunreachable/Tarjan.h
@@ -38,7 +38,7 @@
Node(T* ptr, Allocator<Node> allocator)
: references_in(allocator), references_out(allocator), ptr(ptr){};
- Node(Node&& rhs) = default;
+ Node(Node&& rhs) noexcept = default;
void Edge(Node<T>* ref) {
references_out.emplace(ref);
ref->references_in.emplace(this);
diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp
index ac009a9..f47b6e4 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.cpp
+++ b/libpixelflinger/codeflinger/ARMAssembler.cpp
@@ -171,7 +171,7 @@
}
mAssembly->resize( int(pc()-base())*4 );
-
+
// the instruction cache is flushed by CodeCache
const int64_t duration = ggl_system_time() - mDuration;
const char * const format = "generated %s (%d ins) at [%p:%p] in %lld ns\n";
@@ -183,8 +183,8 @@
printf(format, name, int(pc()-base()), base(), pc(), duration);
disassemble(name);
}
-
- return NO_ERROR;
+
+ return OK;
}
uint32_t* ARMAssembler::pcForLabel(const char* label)
@@ -213,14 +213,14 @@
// multiply...
void ARMAssembler::MLA(int cc, int s,
int Rd, int Rm, int Rs, int Rn) {
- if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
+ if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
LOG_FATAL_IF(Rd==Rm, "MLA(r%u,r%u,r%u,r%u)", Rd,Rm,Rs,Rn);
*mPC++ = (cc<<28) | (1<<21) | (s<<20) |
(Rd<<16) | (Rn<<12) | (Rs<<8) | 0x90 | Rm;
}
void ARMAssembler::MUL(int cc, int s,
int Rd, int Rm, int Rs) {
- if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
+ if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
LOG_FATAL_IF(Rd==Rm, "MUL(r%u,r%u,r%u)", Rd,Rm,Rs);
*mPC++ = (cc<<28) | (s<<20) | (Rd<<16) | (Rs<<8) | 0x90 | Rm;
}
@@ -577,4 +577,3 @@
}
}; // namespace android
-
diff --git a/libpixelflinger/codeflinger/Arm64Assembler.cpp b/libpixelflinger/codeflinger/Arm64Assembler.cpp
index aebc129..8926776 100644
--- a/libpixelflinger/codeflinger/Arm64Assembler.cpp
+++ b/libpixelflinger/codeflinger/Arm64Assembler.cpp
@@ -325,7 +325,7 @@
printf(format, name, int(pc()-base()), base(), pc(), duration);
disassemble(name);
}
- return NO_ERROR;
+ return OK;
}
uint32_t* ArmToArm64Assembler::pcForLabel(const char* label)
@@ -1238,4 +1238,3 @@
}
}; // namespace android
-
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.cpp b/libpixelflinger/codeflinger/MIPSAssembler.cpp
index 039a725..7de8cc1 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.cpp
+++ b/libpixelflinger/codeflinger/MIPSAssembler.cpp
@@ -1421,7 +1421,7 @@
disassemble(name);
}
- return NO_ERROR;
+ return OK;
}
uint32_t* MIPSAssembler::pcForLabel(const char* label)
@@ -1953,5 +1953,3 @@
}; // namespace android:
-
-
diff --git a/libstats/include/stats_event_list.h b/libstats/include/stats_event_list.h
index 5d174ae..a9832db 100644
--- a/libstats/include/stats_event_list.h
+++ b/libstats/include/stats_event_list.h
@@ -24,6 +24,8 @@
#endif
void reset_log_context(android_log_context ctx);
int write_to_logger(android_log_context context, log_id_t id);
+void note_log_drop();
+void stats_log_close();
#ifdef __cplusplus
}
diff --git a/libstats/stats_event_list.c b/libstats/stats_event_list.c
index 3d746db..735088a 100644
--- a/libstats/stats_event_list.c
+++ b/libstats/stats_event_list.c
@@ -119,6 +119,18 @@
return retValue;
}
+void note_log_drop() {
+ statsdLoggerWrite.noteDrop();
+}
+
+void stats_log_close() {
+ statsd_writer_init_lock();
+ if (statsdLoggerWrite.close) {
+ (*statsdLoggerWrite.close)();
+ }
+ statsd_writer_init_unlock();
+}
+
/* log_init_lock assumed */
static int __write_to_statsd_initialize_locked() {
if (!statsdLoggerWrite.open || ((*statsdLoggerWrite.open)() < 0)) {
diff --git a/libstats/statsd_writer.c b/libstats/statsd_writer.c
index 9953bba..afe401f 100644
--- a/libstats/statsd_writer.c
+++ b/libstats/statsd_writer.c
@@ -38,6 +38,7 @@
#define min(x, y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static atomic_int dropped = 0;
void statsd_writer_init_lock() {
/*
@@ -59,14 +60,16 @@
static int statsdOpen();
static void statsdClose();
static int statsdWrite(struct timespec* ts, struct iovec* vec, size_t nr);
+static void statsdNoteDrop();
struct android_log_transport_write statsdLoggerWrite = {
- .name = "statsd",
- .sock = -EBADF,
- .available = statsdAvailable,
- .open = statsdOpen,
- .close = statsdClose,
- .write = statsdWrite,
+ .name = "statsd",
+ .sock = -EBADF,
+ .available = statsdAvailable,
+ .open = statsdOpen,
+ .close = statsdClose,
+ .write = statsdWrite,
+ .noteDrop = statsdNoteDrop,
};
/* log_init_lock assumed */
@@ -131,6 +134,10 @@
return 1;
}
+static void statsdNoteDrop() {
+ atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
+}
+
static int statsdWrite(struct timespec* ts, struct iovec* vec, size_t nr) {
ssize_t ret;
int sock;
@@ -138,7 +145,6 @@
struct iovec newVec[nr + headerLength];
android_log_header_t header;
size_t i, payloadSize;
- static atomic_int dropped;
sock = atomic_load(&statsdLoggerWrite.sock);
if (sock < 0) switch (sock) {
@@ -252,8 +258,6 @@
if (ret > (ssize_t)sizeof(header)) {
ret -= sizeof(header);
- } else if (ret == -EAGAIN) {
- atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
}
return ret;
diff --git a/libstats/statsd_writer.h b/libstats/statsd_writer.h
index 82e14e0..7289441 100644
--- a/libstats/statsd_writer.h
+++ b/libstats/statsd_writer.h
@@ -38,6 +38,8 @@
void (*close)(); /* free up resources */
/* write log to transport, returns number of bytes propagated, or -errno */
int (*write)(struct timespec* ts, struct iovec* vec, size_t nr);
+ /* note one log drop */
+ void (*noteDrop)();
};
#endif // ANDROID_STATS_LOG_STATS_WRITER_H
diff --git a/libsystem/include/system/camera.h b/libsystem/include/system/camera.h
index 7d79673..2ca90c3 100644
--- a/libsystem/include/system/camera.h
+++ b/libsystem/include/system/camera.h
@@ -158,8 +158,8 @@
*
* When any camera method returns error, the client can use ping command
* to see if the camera has been taken away by other clients. If the result
- * is NO_ERROR, it means the camera hardware is not released. If the result
- * is not NO_ERROR, the camera has been released and the existing client
+ * is OK, it means the camera hardware is not released. If the result
+ * is not OK, the camera has been released and the existing client
* can silently finish itself or show a dialog.
*/
CAMERA_CMD_PING = 9,
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index be2145d..970e05c 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -178,6 +178,7 @@
"tests/JitDebugTest.cpp",
"tests/LocalUnwinderTest.cpp",
"tests/LogFake.cpp",
+ "tests/MapInfoCreateMemoryTest.cpp",
"tests/MapInfoGetElfTest.cpp",
"tests/MapInfoGetLoadBiasTest.cpp",
"tests/MapsTest.cpp",
@@ -188,6 +189,7 @@
"tests/MemoryOfflineBufferTest.cpp",
"tests/MemoryOfflineTest.cpp",
"tests/MemoryRangeTest.cpp",
+ "tests/MemoryRangesTest.cpp",
"tests/MemoryRemoteTest.cpp",
"tests/MemoryTest.cpp",
"tests/RegsInfoTest.cpp",
diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp
index 430f6c5..17e2526 100644
--- a/libunwindstack/DexFiles.cpp
+++ b/libunwindstack/DexFiles.cpp
@@ -126,7 +126,7 @@
const std::string dex_debug_name("__dex_debug_descriptor");
for (MapInfo* info : *maps) {
- if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) {
+ if (!(info->flags & PROT_READ) || info->offset != 0) {
continue;
}
diff --git a/libunwindstack/JitDebug.cpp b/libunwindstack/JitDebug.cpp
index 0c319ec..821aacf 100644
--- a/libunwindstack/JitDebug.cpp
+++ b/libunwindstack/JitDebug.cpp
@@ -174,7 +174,7 @@
const std::string descriptor_name("__jit_debug_descriptor");
for (MapInfo* info : *maps) {
- if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) {
+ if (!(info->flags & PROT_READ) || info->offset != 0) {
continue;
}
@@ -194,10 +194,9 @@
Elf* elf = info->GetElf(memory_, true);
uint64_t descriptor_addr;
- if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr)) {
- // Search for the first non-zero entry.
- descriptor_addr += info->start;
- entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr);
+ // Find first non-empty entry (libart might be loaded multiple times).
+ if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr) && descriptor_addr != 0) {
+ entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr + info->start);
if (entry_addr_ != 0) {
break;
}
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 39378a3..64005ae 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -102,7 +102,54 @@
if (!(flags & PROT_READ)) {
return nullptr;
}
- return new MemoryRange(process_memory, start, end - start, 0);
+
+ // Need to verify that this elf is valid. It's possible that
+ // only part of the elf file to be mapped into memory is in the executable
+ // map. In this case, there will be another read-only map that includes the
+ // first part of the elf file. This is done if the linker rosegment
+ // option is used.
+ std::unique_ptr<MemoryRange> memory(new MemoryRange(process_memory, start, end - start, 0));
+ bool valid;
+ uint64_t max_size;
+ Elf::GetInfo(memory.get(), &valid, &max_size);
+ if (valid) {
+ // Valid elf, we are done.
+ return memory.release();
+ }
+
+ if (name.empty() || maps_ == nullptr) {
+ return nullptr;
+ }
+
+ // Find the read-only map that has the same name and has an offset closest
+ // to the current offset but less than the offset of the current map.
+ // For shared libraries, there should be a r-x map that has a non-zero
+ // offset and then a r-- map that has a zero offset.
+ // For shared libraries loaded from an apk, there should be a r-x map that
+ // has a non-zero offset and then a r-- map that has a non-zero offset less
+ // than the offset from the r-x map.
+ uint64_t closest_offset = 0;
+ MapInfo* ro_map_info = nullptr;
+ for (auto map_info : *maps_) {
+ if (map_info->flags == PROT_READ && map_info->name == name && map_info->offset < offset &&
+ map_info->offset >= closest_offset) {
+ ro_map_info = map_info;
+ closest_offset = ro_map_info->offset;
+ }
+ }
+
+ if (ro_map_info != nullptr) {
+ // Make sure that relative pc values are corrected properly.
+ elf_offset = offset - closest_offset;
+
+ MemoryRanges* ranges = new MemoryRanges;
+ ranges->Insert(new MemoryRange(process_memory, ro_map_info->start,
+ ro_map_info->end - ro_map_info->start, 0));
+ ranges->Insert(new MemoryRange(process_memory, start, end - start, elf_offset));
+
+ return ranges;
+ }
+ return nullptr;
}
Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata) {
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
index e676a5a..8729871 100644
--- a/libunwindstack/Maps.cpp
+++ b/libunwindstack/Maps.cpp
@@ -66,13 +66,13 @@
if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
}
- maps_.push_back(new MapInfo(start, end, pgoff, flags, name));
+ maps_.push_back(new MapInfo(this, start, end, pgoff, flags, name));
});
}
void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
const std::string& name, uint64_t load_bias) {
- MapInfo* map_info = new MapInfo(start, end, offset, flags, name);
+ MapInfo* map_info = new MapInfo(this, start, end, offset, flags, name);
map_info->load_bias = load_bias;
maps_.push_back(map_info);
}
@@ -97,7 +97,7 @@
if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
}
- maps_.push_back(new MapInfo(start, end, pgoff, flags, name));
+ maps_.push_back(new MapInfo(this, start, end, pgoff, flags, name));
});
}
diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp
index beb2aad..cfa8c6d 100644
--- a/libunwindstack/Memory.cpp
+++ b/libunwindstack/Memory.cpp
@@ -316,6 +316,18 @@
return memory_->Read(read_addr, dst, read_length);
}
+void MemoryRanges::Insert(MemoryRange* memory) {
+ maps_.emplace(memory->offset() + memory->length(), memory);
+}
+
+size_t MemoryRanges::Read(uint64_t addr, void* dst, size_t size) {
+ auto entry = maps_.upper_bound(addr);
+ if (entry != maps_.end()) {
+ return entry->second->Read(addr, dst, size);
+ }
+ return 0;
+}
+
bool MemoryOffline::Init(const std::string& file, uint64_t offset) {
auto memory_file = std::make_shared<MemoryFileAtOffset>();
if (!memory_file->Init(file, offset)) {
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h
index ac0df41..9755c48 100644
--- a/libunwindstack/include/unwindstack/MapInfo.h
+++ b/libunwindstack/include/unwindstack/MapInfo.h
@@ -29,20 +29,25 @@
namespace unwindstack {
// Forward declarations.
+class Maps;
class Memory;
struct MapInfo {
- MapInfo() = default;
- MapInfo(uint64_t start, uint64_t end) : start(start), end(end) {}
- MapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const char* name)
- : start(start),
+ MapInfo(Maps* maps) : maps_(maps) {}
+ MapInfo(Maps* maps, uint64_t start, uint64_t end) : maps_(maps), start(start), end(end) {}
+ MapInfo(Maps* maps, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
+ const char* name)
+ : maps_(maps),
+ start(start),
end(end),
offset(offset),
flags(flags),
name(name),
load_bias(static_cast<uint64_t>(-1)) {}
- MapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const std::string& name)
- : start(start),
+ MapInfo(Maps* maps, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
+ const std::string& name)
+ : maps_(maps),
+ start(start),
end(end),
offset(offset),
flags(flags),
@@ -50,6 +55,8 @@
load_bias(static_cast<uint64_t>(-1)) {}
~MapInfo() = default;
+ Maps* maps_ = nullptr;
+
uint64_t start = 0;
uint64_t end = 0;
uint64_t offset = 0;
@@ -69,14 +76,14 @@
uint64_t GetLoadBias(const std::shared_ptr<Memory>& process_memory);
+ Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);
+
private:
MapInfo(const MapInfo&) = delete;
void operator=(const MapInfo&) = delete;
Memory* GetFileMemory();
- Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);
-
// Protect the creation of the elf object.
std::mutex mutex_;
};
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index dee5e98..9c425cb 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -22,6 +22,7 @@
#include <unistd.h>
#include <atomic>
+#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -119,6 +120,9 @@
size_t Read(uint64_t addr, void* dst, size_t size) override;
+ uint64_t offset() { return offset_; }
+ uint64_t length() { return length_; }
+
private:
std::shared_ptr<Memory> memory_;
uint64_t begin_;
@@ -126,6 +130,19 @@
uint64_t offset_;
};
+class MemoryRanges : public Memory {
+ public:
+ MemoryRanges() = default;
+ virtual ~MemoryRanges() = default;
+
+ void Insert(MemoryRange* memory);
+
+ size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+ private:
+ std::map<uint64_t, std::unique_ptr<MemoryRange>> maps_;
+};
+
class MemoryOffline : public Memory {
public:
MemoryOffline() = default;
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
index 4dd8cb0..40f9f8e 100644
--- a/libunwindstack/tests/DexFileTest.cpp
+++ b/libunwindstack/tests/DexFileTest.cpp
@@ -120,7 +120,7 @@
static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
MemoryFake memory;
- MapInfo info(0, 0x10000, 0, 0x5, tf.path);
+ MapInfo info(nullptr, 0, 0x10000, 0, 0x5, tf.path);
std::unique_ptr<DexFile> dex_file(DexFile::Create(0x500, &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
}
@@ -134,7 +134,7 @@
static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
MemoryFake memory;
- MapInfo info(0x100, 0x10000, 0, 0x5, tf.path);
+ MapInfo info(nullptr, 0x100, 0x10000, 0, 0x5, tf.path);
std::unique_ptr<DexFile> dex_file(DexFile::Create(0x600, &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
}
@@ -148,7 +148,7 @@
static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
MemoryFake memory;
- MapInfo info(0x100, 0x10000, 0x200, 0x5, tf.path);
+ MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, tf.path);
std::unique_ptr<DexFile> dex_file(DexFile::Create(0x400, &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
}
@@ -156,7 +156,7 @@
TEST(DexFileTest, create_using_memory_empty_file) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
+ MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
}
@@ -164,7 +164,7 @@
TEST(DexFileTest, create_using_memory_file_does_not_exist) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
+ MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
}
@@ -178,7 +178,7 @@
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
+ MapInfo info(nullptr, 0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
@@ -200,7 +200,7 @@
TEST(DexFileTest, get_method) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
+ MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
@@ -227,7 +227,7 @@
TEST(DexFileTest, get_method_empty) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
+ MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
index d029bb0..c6d7f33 100644
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ b/libunwindstack/tests/DexFilesTest.cpp
@@ -46,17 +46,17 @@
maps_.reset(
new BufferMaps("1000-4000 ---s 00000000 00:00 0\n"
"4000-6000 r--s 00000000 00:00 0\n"
- "6000-8000 -w-s 00000000 00:00 0\n"
- "a000-c000 r-xp 00000000 00:00 0\n"
- "c000-f000 rwxp 00000000 00:00 0\n"
- "f000-11000 r-xp 00000000 00:00 0\n"
+ "6000-8000 -wxs 00000000 00:00 0\n"
+ "a000-c000 r--p 00000000 00:00 0\n"
+ "c000-f000 rw-p 00000000 00:00 0\n"
+ "f000-11000 r--p 00000000 00:00 0\n"
"100000-110000 rw-p 0000000 00:00 0\n"
"200000-210000 rw-p 0000000 00:00 0\n"
"300000-400000 rw-p 0000000 00:00 0\n"));
ASSERT_TRUE(maps_->Parse());
- // Global variable in a section that is not readable/executable.
- MapInfo* map_info = maps_->Get(kMapGlobalNonReadableExectable);
+ // Global variable in a section that is not readable.
+ MapInfo* map_info = maps_->Get(kMapGlobalNonReadable);
ASSERT_TRUE(map_info != nullptr);
MemoryFake* memory = new MemoryFake;
ElfFake* elf = new ElfFake(memory);
@@ -95,7 +95,7 @@
void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file);
void WriteDex(uint64_t dex_file);
- static constexpr size_t kMapGlobalNonReadableExectable = 3;
+ static constexpr size_t kMapGlobalNonReadable = 2;
static constexpr size_t kMapGlobalSetToZero = 4;
static constexpr size_t kMapGlobal = 5;
static constexpr size_t kMapDexFileEntries = 7;
diff --git a/libunwindstack/tests/ElfCacheTest.cpp b/libunwindstack/tests/ElfCacheTest.cpp
index 89331ea..1afd4ef 100644
--- a/libunwindstack/tests/ElfCacheTest.cpp
+++ b/libunwindstack/tests/ElfCacheTest.cpp
@@ -79,8 +79,8 @@
uint64_t start = 0x1000;
uint64_t end = 0x20000;
- MapInfo info1(start, end, 0, 0x5, tf.path);
- MapInfo info2(start, end, 0, 0x5, tf.path);
+ MapInfo info1(nullptr, start, end, 0, 0x5, tf.path);
+ MapInfo info2(nullptr, start, end, 0, 0x5, tf.path);
Elf* elf1 = info1.GetElf(memory_, true);
ASSERT_TRUE(elf1->valid());
@@ -120,17 +120,17 @@
uint64_t start = 0x1000;
uint64_t end = 0x20000;
// Will have an elf at offset 0 in file.
- MapInfo info0_1(start, end, 0, 0x5, tf.path);
- MapInfo info0_2(start, end, 0, 0x5, tf.path);
+ MapInfo info0_1(nullptr, start, end, 0, 0x5, tf.path);
+ MapInfo info0_2(nullptr, start, end, 0, 0x5, tf.path);
// Will have an elf at offset 0x100 in file.
- MapInfo info100_1(start, end, 0x100, 0x5, tf.path);
- MapInfo info100_2(start, end, 0x100, 0x5, tf.path);
+ MapInfo info100_1(nullptr, start, end, 0x100, 0x5, tf.path);
+ MapInfo info100_2(nullptr, start, end, 0x100, 0x5, tf.path);
// Will have an elf at offset 0x200 in file.
- MapInfo info200_1(start, end, 0x200, 0x5, tf.path);
- MapInfo info200_2(start, end, 0x200, 0x5, tf.path);
+ MapInfo info200_1(nullptr, start, end, 0x200, 0x5, tf.path);
+ MapInfo info200_2(nullptr, start, end, 0x200, 0x5, tf.path);
// Will have an elf at offset 0 in file.
- MapInfo info300_1(start, end, 0x300, 0x5, tf.path);
- MapInfo info300_2(start, end, 0x300, 0x5, tf.path);
+ MapInfo info300_1(nullptr, start, end, 0x300, 0x5, tf.path);
+ MapInfo info300_2(nullptr, start, end, 0x300, 0x5, tf.path);
Elf* elf0_1 = info0_1.GetElf(memory_, true);
ASSERT_TRUE(elf0_1->valid());
@@ -217,10 +217,10 @@
uint64_t start = 0x1000;
uint64_t end = 0x20000;
// Multiple info sections at different offsets will have non-zero elf offsets.
- MapInfo info300_1(start, end, 0x300, 0x5, tf.path);
- MapInfo info300_2(start, end, 0x300, 0x5, tf.path);
- MapInfo info400_1(start, end, 0x400, 0x5, tf.path);
- MapInfo info400_2(start, end, 0x400, 0x5, tf.path);
+ MapInfo info300_1(nullptr, start, end, 0x300, 0x5, tf.path);
+ MapInfo info300_2(nullptr, start, end, 0x300, 0x5, tf.path);
+ MapInfo info400_1(nullptr, start, end, 0x400, 0x5, tf.path);
+ MapInfo info400_2(nullptr, start, end, 0x400, 0x5, tf.path);
Elf* elf300_1 = info300_1.GetElf(memory_, true);
ASSERT_TRUE(elf300_1->valid());
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 55fe16f..9a117b2 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -297,7 +297,7 @@
elf.FakeSetInterface(interface);
elf.FakeSetValid(true);
- MapInfo map_info(0x1000, 0x2000);
+ MapInfo map_info(nullptr, 0x1000, 0x2000);
ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
diff --git a/libunwindstack/tests/JitDebugTest.cpp b/libunwindstack/tests/JitDebugTest.cpp
index c1c45f8..66f0859 100644
--- a/libunwindstack/tests/JitDebugTest.cpp
+++ b/libunwindstack/tests/JitDebugTest.cpp
@@ -45,11 +45,11 @@
maps_.reset(
new BufferMaps("1000-4000 ---s 00000000 00:00 0\n"
"4000-6000 r--s 00000000 00:00 0\n"
- "6000-8000 -w-s 00000000 00:00 0\n"
+ "6000-8000 -wxs 00000000 00:00 0\n"
"a000-c000 --xp 00000000 00:00 0\n"
- "c000-f000 rwxp 00000000 00:00 0\n"
- "f000-11000 r-xp 00000000 00:00 0\n"
- "12000-14000 r-xp 00000000 00:00 0\n"
+ "c000-f000 rw-p 00000000 00:00 0\n"
+ "f000-11000 r--p 00000000 00:00 0\n"
+ "12000-14000 r--p 00000000 00:00 0\n"
"100000-110000 rw-p 0000000 00:00 0\n"
"200000-210000 rw-p 0000000 00:00 0\n"));
ASSERT_TRUE(maps_->Parse());
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
index 866b5b4..2a73c7e 100644
--- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
+++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
@@ -32,8 +32,10 @@
#include <unwindstack/Elf.h>
#include <unwindstack/MapInfo.h>
+#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
+#include "ElfTestUtils.h"
#include "MemoryFake.h"
namespace unwindstack {
@@ -94,7 +96,7 @@
TemporaryFile MapInfoCreateMemoryTest::elf64_at_map_;
TEST_F(MapInfoCreateMemoryTest, end_le_start) {
- MapInfo info(0x100, 0x100, 0, 0, elf_.path);
+ MapInfo info(nullptr, 0x100, 0x100, 0, 0, elf_.path);
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() == nullptr);
@@ -112,7 +114,7 @@
// Verify that if the offset is non-zero but there is no elf at the offset,
// that the full file is used.
TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
- MapInfo info(0x100, 0x200, 0x100, 0, elf_.path);
+ MapInfo info(nullptr, 0x100, 0x200, 0x100, 0, elf_.path);
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
@@ -133,7 +135,7 @@
// Verify that if the offset is non-zero and there is an elf at that
// offset, that only part of the file is used.
TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
- MapInfo info(0x100, 0x200, 0x100, 0, elf_at_100_.path);
+ MapInfo info(nullptr, 0x100, 0x200, 0x100, 0, elf_at_100_.path);
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
@@ -156,7 +158,7 @@
// embedded elf is bigger than the initial map, the new object is larger
// than the original map size. Do this for a 32 bit elf and a 64 bit elf.
TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
- MapInfo info(0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path);
+ MapInfo info(nullptr, 0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path);
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
@@ -172,7 +174,7 @@
}
TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
- MapInfo info(0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path);
+ MapInfo info(nullptr, 0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path);
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
@@ -192,27 +194,24 @@
// Set up some memory so that a valid local memory object would
// be returned if the file mapping fails, but the device check is incorrect.
std::vector<uint8_t> buffer(1024);
- MapInfo info;
- info.start = reinterpret_cast<uint64_t>(buffer.data());
- info.end = info.start + buffer.size();
- info.offset = 0;
+ uint64_t start = reinterpret_cast<uint64_t>(buffer.data());
+ MapInfo info(nullptr, start, start + buffer.size(), 0, 0x8000, "/dev/something");
- info.flags = 0x8000;
- info.name = "/dev/something";
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() == nullptr);
}
TEST_F(MapInfoCreateMemoryTest, process_memory) {
- MapInfo info;
- info.start = 0x2000;
- info.end = 0x3000;
- info.offset = 0;
+ MapInfo info(nullptr, 0x2000, 0x3000, 0, PROT_READ, "");
+
+ Elf32_Ehdr ehdr = {};
+ TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
+ std::vector<uint8_t> buffer(1024);
+ memcpy(buffer.data(), &ehdr, sizeof(ehdr));
// Verify that the the process_memory object is used, so seed it
// with memory.
- std::vector<uint8_t> buffer(1024);
- for (size_t i = 0; i < buffer.size(); i++) {
+ for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
buffer[i] = i % 256;
}
memory_->SetMemory(info.start, buffer.data(), buffer.size());
@@ -222,7 +221,8 @@
memset(buffer.data(), 0, buffer.size());
ASSERT_TRUE(memory->ReadFully(0, buffer.data(), buffer.size()));
- for (size_t i = 0; i < buffer.size(); i++) {
+ ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
+ for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
ASSERT_EQ(i % 256, buffer[i]) << "Failed at byte " << i;
}
@@ -230,4 +230,87 @@
ASSERT_FALSE(memory->ReadFully(buffer.size(), buffer.data(), 1));
}
+TEST_F(MapInfoCreateMemoryTest, valid_rosegment_zero_offset) {
+ Maps maps;
+ maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
+ maps.Add(0x1000, 0x2600, 0, PROT_READ, "/only/in/memory.so", 0);
+ maps.Add(0x3000, 0x5000, 0x4000, PROT_READ | PROT_EXEC, "/only/in/memory.so", 0);
+
+ Elf32_Ehdr ehdr = {};
+ TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
+ memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
+ memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x1600 - sizeof(ehdr), 0xab);
+
+ // Set the memory in the r-x map.
+ memory_->SetMemoryBlock(0x3000, 0x2000, 0x5d);
+
+ MapInfo* map_info = maps.Find(0x3000);
+ ASSERT_TRUE(map_info != nullptr);
+
+ std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
+ ASSERT_TRUE(mem.get() != nullptr);
+ EXPECT_EQ(0x4000UL, map_info->elf_offset);
+ EXPECT_EQ(0x4000UL, map_info->offset);
+
+ // Verify that reading values from this memory works properly.
+ std::vector<uint8_t> buffer(0x4000);
+ size_t bytes = mem->Read(0, buffer.data(), buffer.size());
+ ASSERT_EQ(0x1600UL, bytes);
+ ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
+ for (size_t i = sizeof(ehdr); i < bytes; i++) {
+ ASSERT_EQ(0xab, buffer[i]) << "Failed at byte " << i;
+ }
+
+ bytes = mem->Read(0x4000, buffer.data(), buffer.size());
+ ASSERT_EQ(0x2000UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x5d, buffer[i]) << "Failed at byte " << i;
+ }
+}
+
+TEST_F(MapInfoCreateMemoryTest, valid_rosegment_non_zero_offset) {
+ Maps maps;
+ maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
+ maps.Add(0x1000, 0x2000, 0, PROT_READ, "/only/in/memory.apk", 0);
+ maps.Add(0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
+ maps.Add(0x3000, 0x4000, 0xa000, PROT_READ, "/only/in/memory.apk", 0);
+ maps.Add(0x4000, 0x5000, 0xb000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
+
+ Elf32_Ehdr ehdr = {};
+ TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
+
+ // Setup an elf at offset 0x1000 in memory.
+ memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
+ memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x2000 - sizeof(ehdr), 0x12);
+ memory_->SetMemoryBlock(0x2000, 0x1000, 0x23);
+
+ // Setup an elf at offset 0x3000 in memory..
+ memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
+ memory_->SetMemoryBlock(0x3000 + sizeof(ehdr), 0x4000 - sizeof(ehdr), 0x34);
+ memory_->SetMemoryBlock(0x4000, 0x1000, 0x43);
+
+ MapInfo* map_info = maps.Find(0x4000);
+ ASSERT_TRUE(map_info != nullptr);
+
+ std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
+ ASSERT_TRUE(mem.get() != nullptr);
+ EXPECT_EQ(0x1000UL, map_info->elf_offset);
+ EXPECT_EQ(0xb000UL, map_info->offset);
+
+ // Verify that reading values from this memory works properly.
+ std::vector<uint8_t> buffer(0x4000);
+ size_t bytes = mem->Read(0, buffer.data(), buffer.size());
+ ASSERT_EQ(0x1000UL, bytes);
+ ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
+ for (size_t i = sizeof(ehdr); i < bytes; i++) {
+ ASSERT_EQ(0x34, buffer[i]) << "Failed at byte " << i;
+ }
+
+ bytes = mem->Read(0x1000, buffer.data(), buffer.size());
+ ASSERT_EQ(0x1000UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x43, buffer[i]) << "Failed at byte " << i;
+ }
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp
index 861b82f..918c028 100644
--- a/libunwindstack/tests/MapInfoGetElfTest.cpp
+++ b/libunwindstack/tests/MapInfoGetElfTest.cpp
@@ -69,7 +69,7 @@
};
TEST_F(MapInfoGetElfTest, invalid) {
- MapInfo info(0x1000, 0x2000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
// The map is empty, but this should still create an invalid elf object.
Elf* elf = info.GetElf(process_memory_, false);
@@ -78,7 +78,7 @@
}
TEST_F(MapInfoGetElfTest, valid32) {
- MapInfo info(0x3000, 0x4000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x3000, 0x4000, 0, PROT_READ, "");
Elf32_Ehdr ehdr;
TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
@@ -92,7 +92,7 @@
}
TEST_F(MapInfoGetElfTest, valid64) {
- MapInfo info(0x8000, 0x9000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x8000, 0x9000, 0, PROT_READ, "");
Elf64_Ehdr ehdr;
TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
@@ -106,7 +106,7 @@
}
TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) {
- MapInfo info(0x4000, 0x8000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x4000, 0x8000, 0, PROT_READ, "");
TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
[&](uint64_t offset, const void* ptr, size_t size) {
@@ -122,7 +122,7 @@
}
TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) {
- MapInfo info(0x6000, 0x8000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x6000, 0x8000, 0, PROT_READ, "");
TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
[&](uint64_t offset, const void* ptr, size_t size) {
@@ -138,7 +138,7 @@
}
TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
- MapInfo info(0x2000, 0x3000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x2000, 0x3000, 0, PROT_READ, "");
TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
[&](uint64_t offset, const void* ptr, size_t size) {
@@ -154,7 +154,7 @@
}
TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
- MapInfo info(0x5000, 0x8000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x5000, 0x8000, 0, PROT_READ, "");
TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
[&](uint64_t offset, const void* ptr, size_t size) {
@@ -170,7 +170,7 @@
}
TEST_F(MapInfoGetElfTest, end_le_start) {
- MapInfo info(0x1000, 0x1000, 0, PROT_READ, elf_.path);
+ MapInfo info(nullptr, 0x1000, 0x1000, 0, PROT_READ, elf_.path);
Elf32_Ehdr ehdr;
TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
@@ -197,7 +197,7 @@
// Verify that if the offset is non-zero but there is no elf at the offset,
// that the full file is used.
TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
- MapInfo info(0x1000, 0x2000, 0x100, PROT_READ, elf_.path);
+ MapInfo info(nullptr, 0x1000, 0x2000, 0x100, PROT_READ, elf_.path);
std::vector<uint8_t> buffer(0x1000);
memset(buffer.data(), 0, buffer.size());
@@ -226,7 +226,7 @@
// Verify that if the offset is non-zero and there is an elf at that
// offset, that only part of the file is used.
TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
- MapInfo info(0x1000, 0x2000, 0x2000, PROT_READ, elf_.path);
+ MapInfo info(nullptr, 0x1000, 0x2000, 0x2000, PROT_READ, elf_.path);
std::vector<uint8_t> buffer(0x4000);
memset(buffer.data(), 0, buffer.size());
@@ -256,7 +256,7 @@
// embedded elf is bigger than the initial map, the new object is larger
// than the original map size. Do this for a 32 bit elf and a 64 bit elf.
TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
- MapInfo info(0x5000, 0x6000, 0x1000, PROT_READ, elf_.path);
+ MapInfo info(nullptr, 0x5000, 0x6000, 0x1000, PROT_READ, elf_.path);
std::vector<uint8_t> buffer(0x4000);
memset(buffer.data(), 0, buffer.size());
@@ -284,7 +284,7 @@
}
TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
- MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ, elf_.path);
+ MapInfo info(nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, elf_.path);
std::vector<uint8_t> buffer(0x4000);
memset(buffer.data(), 0, buffer.size());
@@ -312,7 +312,7 @@
}
TEST_F(MapInfoGetElfTest, process_memory_not_read_only) {
- MapInfo info(0x9000, 0xa000, 0x1000, 0, "");
+ MapInfo info(nullptr, 0x9000, 0xa000, 0x1000, 0, "");
// Create valid elf data in process memory only.
Elf64_Ehdr ehdr;
@@ -333,7 +333,8 @@
}
TEST_F(MapInfoGetElfTest, check_device_maps) {
- MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP, "/dev/something");
+ MapInfo info(nullptr, 0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP,
+ "/dev/something");
// Create valid elf data in process memory for this to verify that only
// the name is causing invalid elf data.
@@ -378,7 +379,7 @@
wait = true;
// Create all of the threads and have them do the GetElf at the same time
// to make it likely that a race will occur.
- MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ, "");
+ MapInfo info(nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, "");
for (size_t i = 0; i < kNumConcurrentThreads; i++) {
std::thread* thread = new std::thread([i, this, &wait, &info, &elf_in_threads]() {
while (wait)
diff --git a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
index 7e64a8a..f5ac6cb 100644
--- a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
+++ b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
@@ -50,7 +50,7 @@
process_memory_.reset(memory_);
elf_ = new ElfFake(new MemoryFake);
elf_container_.reset(elf_);
- map_info_.reset(new MapInfo(0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, ""));
+ map_info_.reset(new MapInfo(nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, ""));
}
void MultipleThreadTest(uint64_t expected_load_bias);
@@ -63,7 +63,7 @@
};
TEST_F(MapInfoGetLoadBiasTest, no_elf_and_no_valid_elf_in_memory) {
- MapInfo info(0x1000, 0x2000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
EXPECT_EQ(0U, info.GetLoadBias(process_memory_));
}
diff --git a/libunwindstack/tests/MapsTest.cpp b/libunwindstack/tests/MapsTest.cpp
index 9622ba5..6bdd0b2 100644
--- a/libunwindstack/tests/MapsTest.cpp
+++ b/libunwindstack/tests/MapsTest.cpp
@@ -63,7 +63,7 @@
}
TEST(MapsTest, verify_parse_line) {
- MapInfo info;
+ MapInfo info(nullptr);
VerifyLine("01-02 rwxp 03 04:05 06\n", &info);
EXPECT_EQ(1U, info.start);
@@ -136,7 +136,7 @@
}
TEST(MapsTest, verify_large_values) {
- MapInfo info;
+ MapInfo info(nullptr);
#if defined(__LP64__)
VerifyLine("fabcdef012345678-f12345678abcdef8 rwxp f0b0d0f010305070 00:00 0\n", &info);
EXPECT_EQ(0xfabcdef012345678UL, info.start);
diff --git a/libunwindstack/tests/MemoryFake.cpp b/libunwindstack/tests/MemoryFake.cpp
index 60936cd..5695dfc 100644
--- a/libunwindstack/tests/MemoryFake.cpp
+++ b/libunwindstack/tests/MemoryFake.cpp
@@ -23,6 +23,17 @@
namespace unwindstack {
+void MemoryFake::SetMemoryBlock(uint64_t addr, size_t length, uint8_t value) {
+ for (size_t i = 0; i < length; i++, addr++) {
+ auto entry = data_.find(addr);
+ if (entry != data_.end()) {
+ entry->second = value;
+ } else {
+ data_.insert({addr, value});
+ }
+ }
+}
+
void MemoryFake::SetMemory(uint64_t addr, const void* memory, size_t length) {
const uint8_t* src = reinterpret_cast<const uint8_t*>(memory);
for (size_t i = 0; i < length; i++, addr++) {
diff --git a/libunwindstack/tests/MemoryFake.h b/libunwindstack/tests/MemoryFake.h
index 764a6c3..20610a5 100644
--- a/libunwindstack/tests/MemoryFake.h
+++ b/libunwindstack/tests/MemoryFake.h
@@ -36,6 +36,8 @@
void SetMemory(uint64_t addr, const void* memory, size_t length);
+ void SetMemoryBlock(uint64_t addr, size_t length, uint8_t value);
+
void SetData8(uint64_t addr, uint8_t value) {
SetMemory(addr, &value, sizeof(value));
}
diff --git a/libunwindstack/tests/MemoryRangeTest.cpp b/libunwindstack/tests/MemoryRangeTest.cpp
index cb1a0c9..2bac95b 100644
--- a/libunwindstack/tests/MemoryRangeTest.cpp
+++ b/libunwindstack/tests/MemoryRangeTest.cpp
@@ -15,7 +15,6 @@
*/
#include <stdint.h>
-#include <string.h>
#include <memory>
#include <vector>
@@ -28,30 +27,34 @@
namespace unwindstack {
-TEST(MemoryRangeTest, read) {
- std::vector<uint8_t> src(1024);
- memset(src.data(), 0x4c, 1024);
- MemoryFake* memory_fake = new MemoryFake;
- std::shared_ptr<Memory> process_memory(memory_fake);
- memory_fake->SetMemory(9001, src);
+class MemoryRangeTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ process_memory_.reset();
+ memory_fake_ = new MemoryFake;
+ process_memory_.reset(memory_fake_);
+ }
- MemoryRange range(process_memory, 9001, src.size(), 0);
+ std::shared_ptr<Memory> process_memory_;
+ MemoryFake* memory_fake_ = nullptr;
+};
+
+TEST_F(MemoryRangeTest, read_fully) {
+ memory_fake_->SetMemoryBlock(9000, 2048, 0x4c);
+
+ MemoryRange range(process_memory_, 9001, 1024, 0);
std::vector<uint8_t> dst(1024);
- ASSERT_TRUE(range.ReadFully(0, dst.data(), src.size()));
- for (size_t i = 0; i < 1024; i++) {
+ ASSERT_TRUE(range.ReadFully(0, dst.data(), dst.size()));
+ for (size_t i = 0; i < dst.size(); i++) {
ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
}
}
-TEST(MemoryRangeTest, read_near_limit) {
- std::vector<uint8_t> src(4096);
- memset(src.data(), 0x4c, 4096);
- MemoryFake* memory_fake = new MemoryFake;
- std::shared_ptr<Memory> process_memory(memory_fake);
- memory_fake->SetMemory(1000, src);
+TEST_F(MemoryRangeTest, read_fully_near_limit) {
+ memory_fake_->SetMemoryBlock(0, 8192, 0x4c);
- MemoryRange range(process_memory, 1000, 1024, 0);
+ MemoryRange range(process_memory_, 1000, 1024, 0);
std::vector<uint8_t> dst(1024);
ASSERT_TRUE(range.ReadFully(1020, dst.data(), 4));
@@ -68,7 +71,7 @@
ASSERT_TRUE(range.ReadFully(1020, dst.data(), 4));
}
-TEST(MemoryRangeTest, read_overflow) {
+TEST_F(MemoryRangeTest, read_fully_overflow) {
std::vector<uint8_t> buffer(100);
std::shared_ptr<Memory> process_memory(new MemoryFakeAlwaysReadZero);
@@ -76,19 +79,28 @@
ASSERT_FALSE(overflow->ReadFully(UINT64_MAX - 10, buffer.data(), 100));
}
-TEST(MemoryRangeTest, Read) {
- std::vector<uint8_t> src(4096);
- memset(src.data(), 0x4c, 4096);
- MemoryFake* memory_fake = new MemoryFake;
- std::shared_ptr<Memory> process_memory(memory_fake);
- memory_fake->SetMemory(1000, src);
+TEST_F(MemoryRangeTest, read) {
+ memory_fake_->SetMemoryBlock(0, 4096, 0x4c);
- MemoryRange range(process_memory, 1000, 1024, 0);
+ MemoryRange range(process_memory_, 1000, 1024, 0);
+
std::vector<uint8_t> dst(1024);
- ASSERT_EQ(4U, range.Read(1020, dst.data(), 1024));
+ ASSERT_EQ(4U, range.Read(1020, dst.data(), dst.size()));
for (size_t i = 0; i < 4; i++) {
ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
}
}
+TEST_F(MemoryRangeTest, read_non_zero_offset) {
+ memory_fake_->SetMemoryBlock(1000, 1024, 0x12);
+
+ MemoryRange range(process_memory_, 1000, 1024, 400);
+
+ std::vector<uint8_t> dst(1024);
+ ASSERT_EQ(1024U, range.Read(400, dst.data(), dst.size()));
+ for (size_t i = 0; i < dst.size(); i++) {
+ ASSERT_EQ(0x12U, dst[i]) << "Failed at byte " << i;
+ }
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryRangesTest.cpp b/libunwindstack/tests/MemoryRangesTest.cpp
new file mode 100644
index 0000000..d24fcd2
--- /dev/null
+++ b/libunwindstack/tests/MemoryRangesTest.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/Memory.h>
+
+#include "MemoryFake.h"
+
+namespace unwindstack {
+
+class MemoryRangesTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ MemoryFake* memory = new MemoryFake;
+ process_memory_.reset(memory);
+ memory->SetMemoryBlock(1000, 5000, 0x15);
+ memory->SetMemoryBlock(6000, 12000, 0x26);
+ memory->SetMemoryBlock(14000, 20000, 0x37);
+ memory->SetMemoryBlock(20000, 22000, 0x48);
+
+ ranges_.reset(new MemoryRanges);
+ ranges_->Insert(new MemoryRange(process_memory_, 15000, 100, 4000));
+ ranges_->Insert(new MemoryRange(process_memory_, 10000, 2000, 2000));
+ ranges_->Insert(new MemoryRange(process_memory_, 3000, 1000, 0));
+ ranges_->Insert(new MemoryRange(process_memory_, 19000, 1000, 6000));
+ ranges_->Insert(new MemoryRange(process_memory_, 20000, 1000, 7000));
+ }
+
+ std::shared_ptr<Memory> process_memory_;
+ std::unique_ptr<MemoryRanges> ranges_;
+};
+
+TEST_F(MemoryRangesTest, read) {
+ std::vector<uint8_t> dst(2000);
+ size_t bytes = ranges_->Read(0, dst.data(), dst.size());
+ ASSERT_EQ(1000UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x15U, dst[i]) << "Failed at byte " << i;
+ }
+
+ bytes = ranges_->Read(2000, dst.data(), dst.size());
+ ASSERT_EQ(2000UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x26U, dst[i]) << "Failed at byte " << i;
+ }
+
+ bytes = ranges_->Read(4000, dst.data(), dst.size());
+ ASSERT_EQ(100UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x37U, dst[i]) << "Failed at byte " << i;
+ }
+}
+
+TEST_F(MemoryRangesTest, read_fail) {
+ std::vector<uint8_t> dst(4096);
+ ASSERT_EQ(0UL, ranges_->Read(1000, dst.data(), dst.size()));
+ ASSERT_EQ(0UL, ranges_->Read(5000, dst.data(), dst.size()));
+ ASSERT_EQ(0UL, ranges_->Read(8000, dst.data(), dst.size()));
+}
+
+TEST_F(MemoryRangesTest, read_across_ranges) {
+ // The MemoryRanges object does not support reading across a range,
+ // so this will only read in the first range.
+ std::vector<uint8_t> dst(4096);
+ size_t bytes = ranges_->Read(6000, dst.data(), dst.size());
+ ASSERT_EQ(1000UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x37U, dst[i]) << "Failed at byte " << i;
+ }
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 90c3fe6..00264c2 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -182,7 +182,7 @@
RegsX86_64 regs_x86_64;
RegsMips regs_mips;
RegsMips64 regs_mips64;
- MapInfo map_info(0x1000, 0x2000);
+ MapInfo map_info(nullptr, 0x1000, 0x2000);
Elf* invalid_elf = new Elf(nullptr);
map_info.elf.reset(invalid_elf);
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 2428f68..4369030 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -58,51 +58,54 @@
protected:
static void SetUpTestCase() {
maps_.FakeClear();
- MapInfo* info = new MapInfo(0x1000, 0x8000, 0, PROT_READ | PROT_WRITE, "/system/fake/libc.so");
+ MapInfo* info =
+ new MapInfo(&maps_, 0x1000, 0x8000, 0, PROT_READ | PROT_WRITE, "/system/fake/libc.so");
ElfFake* elf = new ElfFake(new MemoryFake);
info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
maps_.FakeAddMapInfo(info);
- info = new MapInfo(0x10000, 0x12000, 0, PROT_READ | PROT_WRITE, "[stack]");
+ info = new MapInfo(&maps_, 0x10000, 0x12000, 0, PROT_READ | PROT_WRITE, "[stack]");
maps_.FakeAddMapInfo(info);
- info = new MapInfo(0x13000, 0x15000, 0, PROT_READ | PROT_WRITE | MAPS_FLAGS_DEVICE_MAP,
+ info = new MapInfo(&maps_, 0x13000, 0x15000, 0, PROT_READ | PROT_WRITE | MAPS_FLAGS_DEVICE_MAP,
"/dev/fake_device");
maps_.FakeAddMapInfo(info);
- info = new MapInfo(0x20000, 0x22000, 0, PROT_READ | PROT_WRITE, "/system/fake/libunwind.so");
+ info = new MapInfo(&maps_, 0x20000, 0x22000, 0, PROT_READ | PROT_WRITE,
+ "/system/fake/libunwind.so");
elf = new ElfFake(new MemoryFake);
info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
maps_.FakeAddMapInfo(info);
- info = new MapInfo(0x23000, 0x24000, 0, PROT_READ | PROT_WRITE, "/fake/libanother.so");
+ info = new MapInfo(&maps_, 0x23000, 0x24000, 0, PROT_READ | PROT_WRITE, "/fake/libanother.so");
elf = new ElfFake(new MemoryFake);
info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
maps_.FakeAddMapInfo(info);
- info = new MapInfo(0x33000, 0x34000, 0, PROT_READ | PROT_WRITE, "/fake/compressed.so");
+ info = new MapInfo(&maps_, 0x33000, 0x34000, 0, PROT_READ | PROT_WRITE, "/fake/compressed.so");
elf = new ElfFake(new MemoryFake);
info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
maps_.FakeAddMapInfo(info);
- info = new MapInfo(0x43000, 0x44000, 0x1d000, PROT_READ | PROT_WRITE, "/fake/fake.apk");
+ info = new MapInfo(&maps_, 0x43000, 0x44000, 0x1d000, PROT_READ | PROT_WRITE, "/fake/fake.apk");
elf = new ElfFake(new MemoryFake);
info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
maps_.FakeAddMapInfo(info);
- info = new MapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
+ info = new MapInfo(&maps_, 0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
maps_.FakeAddMapInfo(info);
- info = new MapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex");
+ info = new MapInfo(&maps_, 0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
+ "/fake/fake.vdex");
info->load_bias = 0;
maps_.FakeAddMapInfo(info);
- info = new MapInfo(0xa5000, 0xa6000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
+ info = new MapInfo(&maps_, 0xa5000, 0xa6000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
"/fake/fake_load_bias.so");
elf = new ElfFake(new MemoryFake);
info->elf.reset(elf);
@@ -110,7 +113,7 @@
elf->FakeSetLoadBias(0x5000);
maps_.FakeAddMapInfo(info);
- info = new MapInfo(0xa7000, 0xa8000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
+ info = new MapInfo(&maps_, 0xa7000, 0xa8000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
"/fake/fake_offset.oat");
elf = new ElfFake(new MemoryFake);
info->elf.reset(elf);
diff --git a/libutils/FileMap.cpp b/libutils/FileMap.cpp
index 583c6b9..5feb2aa 100644
--- a/libutils/FileMap.cpp
+++ b/libutils/FileMap.cpp
@@ -62,11 +62,17 @@
}
// Move Constructor.
-FileMap::FileMap(FileMap&& other)
- : mFileName(other.mFileName), mBasePtr(other.mBasePtr), mBaseLength(other.mBaseLength),
- mDataOffset(other.mDataOffset), mDataPtr(other.mDataPtr), mDataLength(other.mDataLength)
+FileMap::FileMap(FileMap&& other) noexcept
+ : mFileName(other.mFileName),
+ mBasePtr(other.mBasePtr),
+ mBaseLength(other.mBaseLength),
+ mDataOffset(other.mDataOffset),
+ mDataPtr(other.mDataPtr),
+ mDataLength(other.mDataLength)
#if defined(__MINGW32__)
- , mFileHandle(other.mFileHandle), mFileMapping(other.mFileMapping)
+ ,
+ mFileHandle(other.mFileHandle),
+ mFileMapping(other.mFileMapping)
#endif
{
other.mFileName = nullptr;
@@ -79,7 +85,7 @@
}
// Move assign operator.
-FileMap& FileMap::operator=(FileMap&& other) {
+FileMap& FileMap::operator=(FileMap&& other) noexcept {
mFileName = other.mFileName;
mBasePtr = other.mBasePtr;
mBaseLength = other.mBaseLength;
diff --git a/libutils/PropertyMap.cpp b/libutils/PropertyMap.cpp
index b8c065d..f00272a 100644
--- a/libutils/PropertyMap.cpp
+++ b/libutils/PropertyMap.cpp
@@ -208,7 +208,7 @@
mTokenizer->nextLine();
}
- return NO_ERROR;
+ return OK;
}
} // namespace android
diff --git a/libutils/String16.cpp b/libutils/String16.cpp
index 5c0b406..818b171 100644
--- a/libutils/String16.cpp
+++ b/libutils/String16.cpp
@@ -157,12 +157,12 @@
if (begin >= N) {
SharedBuffer::bufferFromData(mString)->release();
mString = getEmptyString();
- return NO_ERROR;
+ return OK;
}
if ((begin+len) > N) len = N-begin;
if (begin == 0 && len == N) {
setTo(other);
- return NO_ERROR;
+ return OK;
}
if (&other == this) {
@@ -191,7 +191,7 @@
memmove(str, other, len*sizeof(char16_t));
str[len] = 0;
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -202,9 +202,9 @@
const size_t otherLen = other.size();
if (myLen == 0) {
setTo(other);
- return NO_ERROR;
+ return OK;
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
if (myLen >= SIZE_MAX / sizeof(char16_t) - otherLen) {
@@ -218,7 +218,7 @@
char16_t* str = (char16_t*)buf->data();
memcpy(str+myLen, other, (otherLen+1)*sizeof(char16_t));
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -228,9 +228,9 @@
const size_t myLen = size();
if (myLen == 0) {
setTo(chrs, otherLen);
- return NO_ERROR;
+ return OK;
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
if (myLen >= SIZE_MAX / sizeof(char16_t) - otherLen) {
@@ -245,7 +245,7 @@
memcpy(str+myLen, chrs, otherLen*sizeof(char16_t));
str[myLen+otherLen] = 0;
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -260,9 +260,9 @@
const size_t myLen = size();
if (myLen == 0) {
return setTo(chrs, len);
- return NO_ERROR;
+ return OK;
} else if (len == 0) {
- return NO_ERROR;
+ return OK;
}
if (pos > myLen) pos = myLen;
@@ -286,7 +286,7 @@
#if 0
printf("Result (%d chrs): %s\n", size(), String8(*this).string());
#endif
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -357,7 +357,7 @@
edit[i] = tolower((char)v);
}
}
- return NO_ERROR;
+ return OK;
}
status_t String16::replaceAll(char16_t replaceThis, char16_t withThis)
@@ -378,7 +378,7 @@
edit[i] = withThis;
}
}
- return NO_ERROR;
+ return OK;
}
status_t String16::remove(size_t len, size_t begin)
@@ -387,11 +387,11 @@
if (begin >= N) {
SharedBuffer::bufferFromData(mString)->release();
mString = getEmptyString();
- return NO_ERROR;
+ return OK;
}
if ((begin+len) > N) len = N-begin;
if (begin == 0 && len == N) {
- return NO_ERROR;
+ return OK;
}
if (begin > 0) {
@@ -410,7 +410,7 @@
char16_t* str = (char16_t*)buf->data();
str[len] = 0;
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index 8d318f7..0025c56 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -230,7 +230,7 @@
const char *newString = allocFromUTF8(other, strlen(other));
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -241,7 +241,7 @@
const char *newString = allocFromUTF8(other, len);
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -252,7 +252,7 @@
const char *newString = allocFromUTF16(other, len);
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -263,7 +263,7 @@
const char *newString = allocFromUTF32(other, len);
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -274,9 +274,9 @@
const size_t otherLen = other.bytes();
if (bytes() == 0) {
setTo(other);
- return NO_ERROR;
+ return OK;
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
return real_append(other.string(), otherLen);
@@ -292,7 +292,7 @@
if (bytes() == 0) {
return setTo(other, otherLen);
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
return real_append(other, otherLen);
@@ -311,7 +311,7 @@
status_t String8::appendFormatV(const char* fmt, va_list args)
{
- int n, result = NO_ERROR;
+ int n, result = OK;
va_list tmp_args;
/* args is undefined after vsnprintf.
@@ -346,7 +346,7 @@
str += myLen;
memcpy(str, other, otherLen);
str[otherLen] = '\0';
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -382,7 +382,7 @@
mString = str;
}
- return NO_ERROR;
+ return OK;
}
ssize_t String8::find(const char* other, size_t start) const
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
index 43ec6c1..64bc402 100644
--- a/libutils/Threads.cpp
+++ b/libutils/Threads.cpp
@@ -379,7 +379,7 @@
{
DWORD dwWaitResult;
dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE);
- return dwWaitResult != WAIT_OBJECT_0 ? -1 : NO_ERROR;
+ return dwWaitResult != WAIT_OBJECT_0 ? -1 : OK;
}
void Mutex::unlock()
@@ -506,7 +506,7 @@
ReleaseMutex(condState->internalMutex);
WaitForSingleObject(hMutex, INFINITE);
- return res == WAIT_OBJECT_0 ? NO_ERROR : -1;
+ return res == WAIT_OBJECT_0 ? OK : -1;
}
} WinCondition;
@@ -639,13 +639,15 @@
*/
Thread::Thread(bool canCallJava)
- : mCanCallJava(canCallJava),
- mThread(thread_id_t(-1)),
- mLock("Thread::mLock"),
- mStatus(NO_ERROR),
- mExitPending(false), mRunning(false)
+ : mCanCallJava(canCallJava),
+ mThread(thread_id_t(-1)),
+ mLock("Thread::mLock"),
+ mStatus(OK),
+ mExitPending(false),
+ mRunning(false)
#if defined(__ANDROID__)
- , mTid(-1)
+ ,
+ mTid(-1)
#endif
{
}
@@ -656,7 +658,7 @@
status_t Thread::readyToRun()
{
- return NO_ERROR;
+ return OK;
}
status_t Thread::run(const char* name, int32_t priority, size_t stack)
@@ -672,7 +674,7 @@
// reset status and exitPending to their default value, so we can
// try again after an error happened (either below, or in readyToRun())
- mStatus = NO_ERROR;
+ mStatus = OK;
mExitPending = false;
mThread = thread_id_t(-1);
@@ -700,10 +702,10 @@
}
// Do not refer to mStatus here: The thread is already running (may, in fact
- // already have exited with a valid mStatus result). The NO_ERROR indication
+ // already have exited with a valid mStatus result). The OK indication
// here merely indicates successfully starting the thread and does not
// imply successful termination/execution.
- return NO_ERROR;
+ return OK;
// Exiting scope of mLock is a memory barrier and allows new thread to run
}
@@ -728,7 +730,7 @@
if (first) {
first = false;
self->mStatus = self->readyToRun();
- result = (self->mStatus == NO_ERROR);
+ result = (self->mStatus == OK);
if (result && !self->exitPending()) {
// Binder threads (and maybe others) rely on threadLoop
diff --git a/libutils/Tokenizer.cpp b/libutils/Tokenizer.cpp
index f73d699..98dd2fd 100644
--- a/libutils/Tokenizer.cpp
+++ b/libutils/Tokenizer.cpp
@@ -48,7 +48,7 @@
status_t Tokenizer::open(const String8& filename, Tokenizer** outTokenizer) {
*outTokenizer = nullptr;
- int result = NO_ERROR;
+ int result = OK;
int fd = ::open(filename.string(), O_RDONLY);
if (fd < 0) {
result = -errno;
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
index e16f88d..c97a19b 100644
--- a/libutils/VectorImpl.cpp
+++ b/libutils/VectorImpl.cpp
@@ -61,7 +61,7 @@
"[%p] subclasses of VectorImpl must call finish_vector()"
" in their destructor. Leaking %d bytes.",
this, (int)(mCount*mItemSize));
- // We can't call _do_destroy() here because the vtable is already gone.
+ // We can't call _do_destroy() here because the vtable is already gone.
}
VectorImpl& VectorImpl::operator = (const VectorImpl& rhs)
@@ -197,7 +197,7 @@
_do_copy(temp, item, 1);
ssize_t j = i-1;
- void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
+ void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
do {
_do_destroy(next, 1);
_do_copy(next, curr, 1);
@@ -214,13 +214,13 @@
}
i++;
}
-
+
if (temp) {
_do_destroy(temp, 1);
free(temp);
}
}
- return NO_ERROR;
+ return OK;
}
void VectorImpl::pop()
@@ -354,7 +354,7 @@
}
ssize_t VectorImpl::resize(size_t size) {
- ssize_t result = NO_ERROR;
+ ssize_t result = OK;
if (size > mCount) {
result = insertAt(mCount, size - mCount);
} else if (size < mCount) {
@@ -370,7 +370,7 @@
if (sb->release(SharedBuffer::eKeepStorage) == 1) {
_do_destroy(mStorage, mCount);
SharedBuffer::dealloc(sb);
- }
+ }
}
}
@@ -644,13 +644,13 @@
}
}
}
- return NO_ERROR;
+ return OK;
}
ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector)
{
// we've merging a sorted vector... nice!
- ssize_t err = NO_ERROR;
+ ssize_t err = OK;
if (!vector.isEmpty()) {
// first take care of the case where the vectors are sorted together
if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) {
@@ -677,4 +677,3 @@
/*****************************************************************************/
}; // namespace android
-
diff --git a/libutils/include/utils/Errors.h b/libutils/include/utils/Errors.h
index 7093a20..7aafe42 100644
--- a/libutils/include/utils/Errors.h
+++ b/libutils/include/utils/Errors.h
@@ -43,8 +43,8 @@
#endif
enum {
- OK = 0, // Everything's swell.
- NO_ERROR = 0, // No errors.
+ OK = 0, // Preferred constant for checking success.
+ NO_ERROR = OK, // Deprecated synonym for `OK`. Prefer `OK` because it doesn't conflict with Windows.
UNKNOWN_ERROR = (-2147483647-1), // INT32_MIN value
diff --git a/libutils/include/utils/FileMap.h b/libutils/include/utils/FileMap.h
index 8d402a3..f9f8f3c 100644
--- a/libutils/include/utils/FileMap.h
+++ b/libutils/include/utils/FileMap.h
@@ -52,8 +52,8 @@
public:
FileMap(void);
- FileMap(FileMap&& f);
- FileMap& operator=(FileMap&& f);
+ FileMap(FileMap&& f) noexcept;
+ FileMap& operator=(FileMap&& f) noexcept;
/*
* Create a new mapping on an open file.
diff --git a/libutils/include/utils/Flattenable.h b/libutils/include/utils/Flattenable.h
index 0a19019..9d00602 100644
--- a/libutils/include/utils/Flattenable.h
+++ b/libutils/include/utils/Flattenable.h
@@ -190,11 +190,11 @@
inline status_t flatten(void* buffer, size_t size) const {
if (size < sizeof(T)) return NO_MEMORY;
memcpy(buffer, static_cast<T const*>(this), sizeof(T));
- return NO_ERROR;
+ return OK;
}
inline status_t unflatten(void const* buffer, size_t) {
memcpy(static_cast<T*>(this), buffer, sizeof(T));
- return NO_ERROR;
+ return OK;
}
};
diff --git a/libutils/include/utils/Functor.h b/libutils/include/utils/Functor.h
index c0c8d57..c458699 100644
--- a/libutils/include/utils/Functor.h
+++ b/libutils/include/utils/Functor.h
@@ -29,7 +29,7 @@
public:
Functor() {}
virtual ~Functor() {}
- virtual status_t operator ()(int /*what*/, void* /*data*/) { return NO_ERROR; }
+ virtual status_t operator()(int /*what*/, void* /*data*/) { return OK; }
};
} // namespace android
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 3abce17..1571129 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -56,7 +56,7 @@
sp(T* other); // NOLINT(implicit)
sp(const sp<T>& other);
- sp(sp<T>&& other);
+ sp(sp<T>&& other) noexcept;
template<typename U> sp(U* other); // NOLINT(implicit)
template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
@@ -67,7 +67,7 @@
sp& operator = (T* other);
sp& operator = (const sp<T>& other);
- sp& operator = (sp<T>&& other);
+ sp& operator=(sp<T>&& other) noexcept;
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (sp<U>&& other);
@@ -125,9 +125,8 @@
m_ptr->incStrong(this);
}
-template<typename T>
-sp<T>::sp(sp<T>&& other)
- : m_ptr(other.m_ptr) {
+template <typename T>
+sp<T>::sp(sp<T>&& other) noexcept : m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
@@ -169,8 +168,8 @@
return *this;
}
-template<typename T>
-sp<T>& sp<T>::operator =(sp<T>&& other) {
+template <typename T>
+sp<T>& sp<T>::operator=(sp<T>&& other) noexcept {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
diff --git a/libutils/include/utils/Tokenizer.h b/libutils/include/utils/Tokenizer.h
index bb25f37..61c5ff7 100644
--- a/libutils/include/utils/Tokenizer.h
+++ b/libutils/include/utils/Tokenizer.h
@@ -37,7 +37,7 @@
/**
* Opens a file and maps it into memory.
*
- * Returns NO_ERROR and a tokenizer for the file, if successful.
+ * Returns OK and a tokenizer for the file, if successful.
* Otherwise returns an error and sets outTokenizer to NULL.
*/
static status_t open(const String8& filename, Tokenizer** outTokenizer);
@@ -45,7 +45,7 @@
/**
* Prepares to tokenize the contents of a string.
*
- * Returns NO_ERROR and a tokenizer for the string, if successful.
+ * Returns OK and a tokenizer for the string, if successful.
* Otherwise returns an error and sets outTokenizer to NULL.
*/
static status_t fromContents(const String8& filename,
diff --git a/libziparchive/include/ziparchive/zip_writer.h b/libziparchive/include/ziparchive/zip_writer.h
index c350a27..0e0caf1 100644
--- a/libziparchive/include/ziparchive/zip_writer.h
+++ b/libziparchive/include/ziparchive/zip_writer.h
@@ -91,10 +91,10 @@
explicit ZipWriter(FILE* f);
// Move constructor.
- ZipWriter(ZipWriter&& zipWriter);
+ ZipWriter(ZipWriter&& zipWriter) noexcept;
// Move assignment.
- ZipWriter& operator=(ZipWriter&& zipWriter);
+ ZipWriter& operator=(ZipWriter&& zipWriter) noexcept;
/**
* Starts a new zip entry with the given path and flags.
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index f8d1356..6a3db6b 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -903,7 +903,7 @@
return FileWriter(fd, declared_length);
}
- FileWriter(FileWriter&& other)
+ FileWriter(FileWriter&& other) noexcept
: fd_(other.fd_),
declared_length_(other.declared_length_),
total_bytes_written_(other.total_bytes_written_) {
diff --git a/libziparchive/zip_writer.cc b/libziparchive/zip_writer.cc
index 6ad3366..ed1d135 100644
--- a/libziparchive/zip_writer.cc
+++ b/libziparchive/zip_writer.cc
@@ -97,7 +97,7 @@
}
}
-ZipWriter::ZipWriter(ZipWriter&& writer)
+ZipWriter::ZipWriter(ZipWriter&& writer) noexcept
: file_(writer.file_),
seekable_(writer.seekable_),
current_offset_(writer.current_offset_),
@@ -109,7 +109,7 @@
writer.state_ = State::kError;
}
-ZipWriter& ZipWriter::operator=(ZipWriter&& writer) {
+ZipWriter& ZipWriter::operator=(ZipWriter&& writer) noexcept {
file_ = writer.file_;
seekable_ = writer.seekable_;
current_offset_ = writer.current_offset_;
diff --git a/llkd/README.md b/llkd/README.md
index 1f69718..e5be850 100644
--- a/llkd/README.md
+++ b/llkd/README.md
@@ -127,7 +127,7 @@
default 2 minutes samples of threads for D or Z.
#### ro.llk.stack
-default *empty* or false, comma separated list of kernel symbols.
+default cma_alloc,__get_user_pages, comma separated list of kernel symbols.
The string "*false*" is the equivalent to an *empty* list.
Look for kernel stack symbols that if ever persistently present can
indicate a subsystem is locked up.
diff --git a/llkd/include/llkd.h b/llkd/include/llkd.h
index d0188ec..1e2df2f 100644
--- a/llkd/include/llkd.h
+++ b/llkd/include/llkd.h
@@ -48,7 +48,7 @@
/* LLK_CHECK_MS_DEFAULT = actual timeout_ms / LLK_CHECKS_PER_TIMEOUT_DEFAULT */
#define LLK_CHECKS_PER_TIMEOUT_DEFAULT 5
#define LLK_CHECK_STACK_PROPERTY "ro.llk.stack"
-#define LLK_CHECK_STACK_DEFAULT ""
+#define LLK_CHECK_STACK_DEFAULT "cma_alloc,__get_user_pages"
#define LLK_BLACKLIST_PROCESS_PROPERTY "ro.llk.blacklist.process"
#define LLK_BLACKLIST_PROCESS_DEFAULT \
"0,1,2,init,[kthreadd],[khungtaskd],lmkd,lmkd.llkd,llkd,watchdogd,[watchdogd],[watchdogd/0]"
@@ -57,7 +57,7 @@
#define LLK_BLACKLIST_UID_PROPERTY "ro.llk.blacklist.uid"
#define LLK_BLACKLIST_UID_DEFAULT ""
#define LLK_BLACKLIST_STACK_PROPERTY "ro.llk.blacklist.process.stack"
-#define LLK_BLACKLIST_STACK_DEFAULT "init,lmkd.llkd,llkd,keystore,/system/bin/keystore"
+#define LLK_BLACKLIST_STACK_DEFAULT "init,lmkd.llkd,llkd,keystore,/system/bin/keystore,ueventd"
/* clang-format on */
__END_DECLS
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index 58c2ba8..6840ed0 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -265,7 +265,7 @@
}
content.erase(pos);
uid_t ret;
- if (!android::base::ParseInt(content, &ret, uid_t(0))) {
+ if (!android::base::ParseUint(content, &ret, uid_t(0))) {
return -1;
}
return ret;
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index d6b8ab3..469f6dc 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -531,7 +531,7 @@
name = std::string_view(alloc->c_str(), alloc->size());
}
- explicit TagNameKey(TagNameKey&& rval)
+ explicit TagNameKey(TagNameKey&& rval) noexcept
: alloc(rval.alloc), name(rval.name.data(), rval.name.length()) {
rval.alloc = nullptr;
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 6a6a8f9..9aaad8f 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -398,6 +398,10 @@
class_start early_hal
on post-fs-data
+ # Start checkpoint before we touch data
+ start vold
+ exec - system system -- /system/bin/vdc checkpoint prepareCheckpoint
+
# We chown/chmod /data again so because mount is run as root + defaults
chown system system /data
chmod 0771 /data
@@ -405,8 +409,6 @@
restorecon /data
# Make sure we have the device encryption key.
- start vold
- exec - system system -- /system/bin/vdc checkpoint prepareDriveForCheckpoint /data
installkey /data
# Start bootcharting as soon as possible after the data partition is
diff --git a/storaged/storaged_service.cpp b/storaged/storaged_service.cpp
index 17ea25b..45f1d4d 100644
--- a/storaged/storaged_service.cpp
+++ b/storaged/storaged_service.cpp
@@ -161,7 +161,7 @@
storaged_sp->update_uid_io_interval(time_window);
}
- return NO_ERROR;
+ return OK;
}
binder::Status StoragedService::onUserStarted(int32_t userId) {
diff --git a/storaged/uid_info.cpp b/storaged/uid_info.cpp
index 58e3fd2..0f718de 100644
--- a/storaged/uid_info.cpp
+++ b/storaged/uid_info.cpp
@@ -32,7 +32,7 @@
parcel->writeCString(task_it.second.comm.c_str());
parcel->write(&task_it.second.io, sizeof(task_it.second.io));
}
- return NO_ERROR;
+ return OK;
}
status_t UidInfo::readFromParcel(const Parcel* parcel) {
@@ -48,5 +48,5 @@
parcel->read(&task.io, sizeof(task.io));
tasks[task.pid] = task;
}
- return NO_ERROR;
+ return OK;
}
diff --git a/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp b/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp
index 0849ee9..98cbcc3 100644
--- a/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp
+++ b/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp
@@ -112,7 +112,8 @@
}
}
}
- KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
+ KmParamSet(KmParamSet&& other) noexcept
+ : keymaster_key_param_set_t{other.params, other.length} {
other.length = 0;
other.params = nullptr;
}