Merge "BSD grep: sync with upstream."
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 6960345..9791769 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -312,7 +312,7 @@
std::string android_dir = user_dir + OS_PATH_SEPARATOR + ".android";
struct stat buf;
if (stat(android_dir.c_str(), &buf) == -1) {
- if (adb_mkdir(android_dir.c_str(), 0750) == -1) {
+ if (adb_mkdir(android_dir, 0750) == -1) {
PLOG(FATAL) << "Cannot mkdir '" << android_dir << "'";
}
}
diff --git a/adb/bugreport_test.cpp b/adb/bugreport_test.cpp
index 72ca59a..a6be203 100644
--- a/adb/bugreport_test.cpp
+++ b/adb/bugreport_test.cpp
@@ -136,7 +136,7 @@
void ExpectBugreportzVersion(const std::string& version) {
EXPECT_CALL(br_, SendShellCommand("bugreportz -v", false, _))
- .WillOnce(DoAll(WithArg<2>(WriteOnStderr(version.c_str())),
+ .WillOnce(DoAll(WithArg<2>(WriteOnStderr(version)),
WithArg<2>(ReturnCallbackDone(0))));
}
diff --git a/adb/client/auth.cpp b/adb/client/auth.cpp
index bcb829b..3eee426 100644
--- a/adb/client/auth.cpp
+++ b/adb/client/auth.cpp
@@ -416,7 +416,7 @@
#endif
for (const std::string& path : key_paths) {
- load_keys(path.c_str());
+ load_keys(path);
}
}
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index 7e470e1..5d10238 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -1012,7 +1012,7 @@
dst_dir.append(android::base::Basename(src_path));
}
- success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(), sync, false);
+ success &= copy_local_dir_remote(sc, src_path, dst_dir, sync, false);
continue;
} else if (!should_push_file(st.st_mode)) {
sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
@@ -1128,7 +1128,7 @@
// Recursively build the list of files to copy.
sc.Printf("pull: building file list...");
std::vector<copyinfo> file_list;
- if (!remote_build_list(sc, &file_list, rpath.c_str(), lpath.c_str())) {
+ if (!remote_build_list(sc, &file_list, rpath, lpath)) {
return false;
}
@@ -1240,7 +1240,7 @@
dst_dir.append(android::base::Basename(src_path));
}
- success &= copy_remote_dir_local(sc, src_path, dst_dir.c_str(), copy_attrs);
+ success &= copy_remote_dir_local(sc, src_path, dst_dir, copy_attrs);
continue;
} else if (!should_pull_file(src_st.st_mode)) {
sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_st.st_mode);
diff --git a/adb/daemon/file_sync_service.cpp b/adb/daemon/file_sync_service.cpp
index 29bd798..e82a51f 100644
--- a/adb/daemon/file_sync_service.cpp
+++ b/adb/daemon/file_sync_service.cpp
@@ -422,7 +422,7 @@
bool result;
uint32_t timestamp;
if (S_ISLNK(mode)) {
- result = handle_send_link(s, path.c_str(), ×tamp, buffer);
+ result = handle_send_link(s, path, ×tamp, buffer);
} else {
// Copy user permission bits to "group" and "other" permissions.
mode &= 0777;
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index b42236e..14cdb69 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -168,7 +168,8 @@
struct UsbFfsConnection : public Connection {
UsbFfsConnection(unique_fd control, unique_fd read, unique_fd write,
std::promise<void> destruction_notifier)
- : stopped_(false),
+ : worker_started_(false),
+ stopped_(false),
destruction_notifier_(std::move(destruction_notifier)),
control_fd_(std::move(control)),
read_fd_(std::move(read)),
@@ -194,6 +195,7 @@
// We need to explicitly close our file descriptors before we notify our destruction,
// because the thread listening on the future will immediately try to reopen the endpoint.
+ aio_context_.reset();
control_fd_.reset();
read_fd_.reset();
write_fd_.reset();
@@ -267,18 +269,23 @@
adb_thread_setname("UsbFfs-monitor");
bool bound = false;
- bool started = false;
+ bool enabled = false;
bool running = true;
while (running) {
adb_pollfd pfd[2] = {
{ .fd = control_fd_.get(), .events = POLLIN, .revents = 0 },
{ .fd = monitor_event_fd_.get(), .events = POLLIN, .revents = 0 },
};
- int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, -1));
+
+ // If we don't see our first bind within a second, try again.
+ int timeout_ms = bound ? -1 : 1000;
+
+ int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, timeout_ms));
if (rc == -1) {
PLOG(FATAL) << "poll on USB control fd failed";
} else if (rc == 0) {
- LOG(FATAL) << "poll on USB control fd returned 0";
+ LOG(WARNING) << "timed out while waiting for FUNCTIONFS_BIND, trying again";
+ break;
}
if (pfd[1].revents) {
@@ -298,29 +305,45 @@
switch (event.type) {
case FUNCTIONFS_BIND:
CHECK(!bound) << "received FUNCTIONFS_BIND while already bound?";
+ CHECK(!enabled) << "received FUNCTIONFS_BIND while already enabled?";
bound = true;
+
break;
case FUNCTIONFS_ENABLE:
- CHECK(!started) << "received FUNCTIONFS_ENABLE while already running?";
- started = true;
+ CHECK(bound) << "received FUNCTIONFS_ENABLE while not bound?";
+ CHECK(!enabled) << "received FUNCTIONFS_ENABLE while already enabled?";
+ enabled = true;
+
StartWorker();
break;
case FUNCTIONFS_DISABLE:
+ CHECK(bound) << "received FUNCTIONFS_DISABLE while not bound?";
+ CHECK(enabled) << "received FUNCTIONFS_DISABLE while not enabled?";
+ enabled = false;
+
+ running = false;
+ break;
+
+ case FUNCTIONFS_UNBIND:
+ CHECK(!enabled) << "received FUNCTIONFS_UNBIND while still enabled?";
+ CHECK(bound) << "received FUNCTIONFS_UNBIND when not bound?";
+ bound = false;
+
running = false;
break;
}
}
StopWorker();
- aio_context_.reset();
- read_fd_.reset();
- write_fd_.reset();
+ HandleError("monitor thread finished");
});
}
void StartWorker() {
+ CHECK(!worker_started_);
+ worker_started_ = true;
worker_thread_ = std::thread([this]() {
adb_thread_setname("UsbFfs-worker");
for (size_t i = 0; i < kUsbReadQueueDepth; ++i) {
@@ -339,12 +362,16 @@
LOG(FATAL) << "hit EOF on eventfd";
}
- WaitForEvents();
+ ReadEvents();
}
});
}
void StopWorker() {
+ if (!worker_started_) {
+ return;
+ }
+
pthread_t worker_thread_handle = worker_thread_.native_handle();
while (true) {
int rc = pthread_kill(worker_thread_handle, kInterruptionSignal);
@@ -389,7 +416,7 @@
return block;
}
- void WaitForEvents() {
+ void ReadEvents() {
static constexpr size_t kMaxEvents = kUsbReadQueueDepth + kUsbWriteQueueDepth;
struct io_event events[kMaxEvents];
struct timespec timeout = {.tv_sec = 0, .tv_nsec = 0};
@@ -552,6 +579,8 @@
LOG(VERBOSE) << "submitting write_request " << static_cast<void*>(iocbs[i]);
}
+ writes_submitted_ += writes_to_submit;
+
int rc = io_submit(aio_context_.get(), writes_to_submit, iocbs);
if (rc == -1) {
HandleError(StringPrintf("failed to submit write requests: %s", strerror(errno)));
@@ -560,8 +589,6 @@
LOG(FATAL) << "failed to submit all writes: wanted to submit " << writes_to_submit
<< ", actually submitted " << rc;
}
-
- writes_submitted_ += rc;
}
void HandleError(const std::string& error) {
@@ -574,6 +601,8 @@
}
std::thread monitor_thread_;
+
+ bool worker_started_;
std::thread worker_thread_;
std::atomic<bool> stopped_;
diff --git a/adb/services.cpp b/adb/services.cpp
index 80f9f79..cf346ba 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -188,7 +188,7 @@
if (!strncmp(host.c_str(), "emu:", 4)) {
connect_emulator(host.c_str() + 4, &response);
} else {
- connect_device(host.c_str(), &response);
+ connect_device(host, &response);
}
// Send response for emulator and device
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index 83213e9..3fa3bea 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -105,6 +105,9 @@
int get() const { return fd_; }
operator int() const { return get(); } // NOLINT
+ // Catch bogus error checks (i.e.: "!fd" instead of "fd != -1").
+ bool operator!() const = delete;
+
int release() __attribute__((warn_unused_result)) {
tag(fd_, this, nullptr);
int ret = fd_;
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index 753ebcb..94fcfb2 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -74,6 +74,7 @@
return;
}
+ unwinder->SetDisplayBuildID(true);
for (size_t i = 0; i < unwinder->NumFrames(); i++) {
_LOG(&log, logtype::BACKTRACE, " %s\n", unwinder->FormatFrame(i).c_str());
}
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index c08afda..47a7a8f 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -371,6 +371,7 @@
}
void dump_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* prefix) {
+ unwinder->SetDisplayBuildID(true);
for (size_t i = 0; i < unwinder->NumFrames(); i++) {
_LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, unwinder->FormatFrame(i).c_str());
}
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 4cdd8bc..827db96 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -1805,7 +1805,7 @@
auto format = [&](const std::string& partition) {
fb_perform_format(partition, 0, type_override, size_override, "");
};
- do_for_partitions(partition.c_str(), slot_override, format, true);
+ do_for_partitions(partition, slot_override, format, true);
} else if (command == "signature") {
std::string filename = next_arg(&args);
std::vector<char> data;
@@ -1876,7 +1876,7 @@
}
do_flash(partition.c_str(), fname.c_str());
};
- do_for_partitions(pname.c_str(), slot_override, flash, true);
+ do_for_partitions(pname, slot_override, flash, true);
} else if (command == "flash:raw") {
std::string partition = next_arg(&args);
std::string kernel = next_arg(&args);
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index d26f2d5..ba6b9eb 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1602,6 +1602,14 @@
return true;
}
+std::string fs_mgr_get_verity_device_name(const FstabEntry& entry) {
+ if (entry.mount_point == "/") {
+ // In AVB, the dm device name is vroot instead of system.
+ return entry.fs_mgr_flags.avb ? "vroot" : "system";
+ }
+ return Basename(entry.mount_point);
+}
+
bool fs_mgr_is_verity_enabled(const FstabEntry& entry) {
if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
return false;
@@ -1609,14 +1617,7 @@
DeviceMapper& dm = DeviceMapper::Instance();
- std::string mount_point;
- if (entry.mount_point == "/") {
- // In AVB, the dm device name is vroot instead of system.
- mount_point = entry.fs_mgr_flags.avb ? "vroot" : "system";
- } else {
- mount_point = Basename(entry.mount_point);
- }
-
+ std::string mount_point = fs_mgr_get_verity_device_name(entry);
if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
return false;
}
@@ -1639,6 +1640,27 @@
return false;
}
+bool fs_mgr_verity_is_check_at_most_once(const android::fs_mgr::FstabEntry& entry) {
+ if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
+ return false;
+ }
+
+ DeviceMapper& dm = DeviceMapper::Instance();
+ std::string device = fs_mgr_get_verity_device_name(entry);
+
+ std::vector<DeviceMapper::TargetInfo> table;
+ if (dm.GetState(device) == DmDeviceState::INVALID || !dm.GetTableInfo(device, &table)) {
+ return false;
+ }
+ for (const auto& target : table) {
+ if (strcmp(target.spec.target_type, "verity") == 0 &&
+ target.data.find("check_at_most_once") != std::string::npos) {
+ return true;
+ }
+ }
+ return false;
+}
+
std::string fs_mgr_get_super_partition_name(int slot) {
// Devices upgrading to dynamic partitions are allowed to specify a super
// partition name, assumed to be A/B (non-A/B retrofit is not supported).
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index a3bb852..8abe609 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -77,6 +77,10 @@
bool fs_mgr_swapon_all(const android::fs_mgr::Fstab& fstab);
bool fs_mgr_update_logical_partition(android::fs_mgr::FstabEntry* entry);
+// Returns true if the given fstab entry has verity enabled, *and* the verity
+// device is in "check_at_most_once" mode.
+bool fs_mgr_verity_is_check_at_most_once(const android::fs_mgr::FstabEntry& entry);
+
int fs_mgr_do_format(const android::fs_mgr::FstabEntry& entry, bool reserve_footer);
#define FS_MGR_SETUP_VERITY_SKIPPED (-3)
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 63661f0..9309aad 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -316,7 +316,7 @@
DeviceMapper& dm = DeviceMapper::Instance();
std::vector<DeviceMapper::TargetInfo> table;
- if (!dm.GetTableStatus(argv[0], &table)) {
+ if (!dm.GetTableInfo(argv[0], &table)) {
std::cerr << "Could not query table status of device \"" << argv[0] << "\"." << std::endl;
return -EINVAL;
}
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 5fe58ac..bde5fbe 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -36,6 +36,7 @@
#include <linux/netlink.h>
#include <sys/socket.h>
+#include <cutils/android_get_control_file.h>
#include <cutils/klog.h>
#include <cutils/misc.h>
#include <cutils/properties.h>
@@ -206,10 +207,9 @@
#define MAX_KLOG_WRITE_BUF_SZ 256
static void dump_last_kmsg(void) {
- char* buf;
+ std::string buf;
char* ptr;
- unsigned sz = 0;
- int len;
+ size_t len;
LOGW("\n");
LOGW("*************** LAST KMSG ***************\n");
@@ -221,21 +221,25 @@
"/proc/last_kmsg",
// clang-format on
};
- for (size_t i = 0; i < arraysize(kmsg); ++i) {
- buf = (char*)load_file(kmsg[i], &sz);
- if (buf && sz) break;
+ for (size_t i = 0; i < arraysize(kmsg) && buf.empty(); ++i) {
+ auto fd = android_get_control_file(kmsg[i]);
+ if (fd >= 0) {
+ android::base::ReadFdToString(fd, &buf);
+ } else {
+ android::base::ReadFileToString(kmsg[i], &buf);
+ }
}
- if (!buf || !sz) {
+ if (buf.empty()) {
LOGW("last_kmsg not found. Cold reset?\n");
goto out;
}
- len = min(sz, LAST_KMSG_MAX_SZ);
- ptr = buf + (sz - len);
+ len = min(buf.size(), LAST_KMSG_MAX_SZ);
+ ptr = &buf[buf.size() - len];
while (len > 0) {
- int cnt = min(len, MAX_KLOG_WRITE_BUF_SZ);
+ size_t cnt = min(len, MAX_KLOG_WRITE_BUF_SZ);
char yoink;
char* nl;
@@ -251,8 +255,6 @@
ptr += cnt;
}
- free(buf);
-
out:
LOGW("\n");
LOGW("************* END LAST KMSG *************\n");
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 4b0f05d..d458924 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -78,6 +78,7 @@
ListenerAction HandleBlockDevice(const std::string& name, const Uevent&);
bool InitRequiredDevices();
bool InitMappedDevice(const std::string& verity_device);
+ bool InitDeviceMapper();
bool CreateLogicalPartitions();
bool MountPartition(const Fstab::iterator& begin, bool erase_used_fstab_entry,
Fstab::iterator* end = nullptr);
@@ -97,6 +98,7 @@
virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0;
bool need_dm_verity_;
+ bool gsi_not_on_userdata_ = false;
Fstab fstab_;
std::string lp_metadata_partition_;
@@ -267,8 +269,6 @@
}
required_devices_partition_names_.emplace(super_partition_name_);
- // When booting from live GSI images, userdata is the super device.
- required_devices_partition_names_.emplace("userdata");
return true;
}
@@ -281,25 +281,7 @@
}
if (IsDmLinearEnabled() || need_dm_verity_) {
- const std::string dm_path = "/devices/virtual/misc/device-mapper";
- bool found = false;
- auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
- if (uevent.path == dm_path) {
- device_handler_->HandleUevent(uevent);
- found = true;
- return ListenerAction::kStop;
- }
- return ListenerAction::kContinue;
- };
- uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback);
- if (!found) {
- LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent";
- Timer t;
- uevent_listener_.Poll(dm_callback, 10s);
- LOG(INFO) << "Wait for device-mapper returned after " << t;
- }
- if (!found) {
- LOG(ERROR) << "device-mapper device not found after polling timeout";
+ if (!InitDeviceMapper()) {
return false;
}
}
@@ -327,11 +309,36 @@
return true;
}
+bool FirstStageMount::InitDeviceMapper() {
+ const std::string dm_path = "/devices/virtual/misc/device-mapper";
+ bool found = false;
+ auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
+ if (uevent.path == dm_path) {
+ device_handler_->HandleUevent(uevent);
+ found = true;
+ return ListenerAction::kStop;
+ }
+ return ListenerAction::kContinue;
+ };
+ uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback);
+ if (!found) {
+ LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent";
+ Timer t;
+ uevent_listener_.Poll(dm_callback, 10s);
+ LOG(INFO) << "Wait for device-mapper returned after " << t;
+ }
+ if (!found) {
+ LOG(ERROR) << "device-mapper device not found after polling timeout";
+ return false;
+ }
+ return true;
+}
+
bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) {
auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata);
for (const auto& partition_name : partition_names) {
- const auto super_device = android::fs_mgr::GetMetadataSuperBlockDevice(metadata);
- if (partition_name == android::fs_mgr::GetBlockDevicePartitionName(*super_device)) {
+ // The super partition was found in the earlier pass.
+ if (partition_name == super_partition_name_) {
continue;
}
required_devices_partition_names_.emplace(partition_name);
@@ -499,6 +506,10 @@
if (system_partition == fstab_.end()) return true;
if (MountPartition(system_partition, false)) {
+ if (gsi_not_on_userdata_ && fs_mgr_verity_is_check_at_most_once(*system_partition)) {
+ LOG(ERROR) << "check_most_at_once forbidden on external media";
+ return false;
+ }
SwitchRoot("/system");
} else {
PLOG(ERROR) << "Failed to mount /system";
@@ -612,7 +623,29 @@
return;
}
- if (!android::fs_mgr::CreateLogicalPartitions(*metadata.get(), "/dev/block/by-name/userdata")) {
+ if (!InitDmLinearBackingDevices(*metadata.get())) {
+ return;
+ }
+
+ // Device-mapper might not be ready if the device doesn't use DAP or verity
+ // (for example, hikey).
+ if (access("/dev/device-mapper", F_OK) && !InitDeviceMapper()) {
+ return;
+ }
+
+ // Find the name of the super partition for the GSI. It will either be
+ // "userdata", or a block device such as an sdcard. There are no by-name
+ // partitions other than userdata that we support installing GSIs to.
+ auto super = GetMetadataSuperBlockDevice(*metadata.get());
+ std::string super_name = android::fs_mgr::GetBlockDevicePartitionName(*super);
+ std::string super_path;
+ if (super_name == "userdata") {
+ super_path = "/dev/block/by-name/" + super_name;
+ } else {
+ super_path = "/dev/block/" + super_name;
+ }
+
+ if (!android::fs_mgr::CreateLogicalPartitions(*metadata.get(), super_path)) {
LOG(ERROR) << "GSI partition layout could not be instantiated";
return;
}
@@ -630,6 +663,7 @@
fstab_.erase(system_partition);
}
fstab_.emplace_back(BuildGsiSystemFstabEntry());
+ gsi_not_on_userdata_ = (super_name != "userdata");
}
bool FirstStageMountVBootV1::GetDmVerityDevices() {
diff --git a/init/init.cpp b/init/init.cpp
index a5f4549..cdec41c 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -357,7 +357,7 @@
static Result<Success> SetupCgroupsAction(const BuiltinArguments&) {
// Have to create <CGROUPS_RC_DIR> using make_dir function
// for appropriate sepolicy to be set for it
- make_dir(CGROUPS_RC_DIR, 0711);
+ make_dir(android::base::Dirname(CGROUPS_RC_PATH), 0711);
if (!CgroupSetupCgroups()) {
return ErrnoError() << "Failed to setup cgroups";
}
diff --git a/init/mount_handler.cpp b/init/mount_handler.cpp
index 12dfc6d..c8f0e76 100644
--- a/init/mount_handler.cpp
+++ b/init/mount_handler.cpp
@@ -27,6 +27,7 @@
#include <algorithm>
#include <string>
#include <utility>
+#include <vector>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -34,6 +35,7 @@
#include <android-base/strings.h>
#include <fs_mgr.h>
#include <fstab/fstab.h>
+#include <libdm/dm.h>
#include "epoll.h"
#include "property_service.h"
@@ -47,8 +49,13 @@
auto fields = android::base::Split(line, " ");
while (fields.size() < 3) fields.emplace_back("");
if (fields[0] == "/dev/root") {
- if (android::fs_mgr::Fstab fstab; android::fs_mgr::ReadDefaultFstab(&fstab)) {
- if (auto entry = GetEntryForMountPoint(&fstab, "/")) {
+ auto& dm = dm::DeviceMapper::Instance();
+ std::string path;
+ if (dm.GetDmDevicePathByName("system", &path) || dm.GetDmDevicePathByName("vroot", &path)) {
+ fields[0] = path;
+ } else if (android::fs_mgr::Fstab fstab; android::fs_mgr::ReadDefaultFstab(&fstab)) {
+ auto entry = GetEntryForMountPoint(&fstab, "/");
+ if (entry || (entry = GetEntryForMountPoint(&fstab, "/system"))) {
fields[0] = entry->blk_device;
}
}
@@ -77,14 +84,19 @@
struct stat sb;
if (stat(queue.c_str(), &sb) || !S_ISDIR(sb.st_mode)) value = "";
if (stat(entry.mount_point.c_str(), &sb) || !S_ISDIR(sb.st_mode)) value = "";
- // Skip the noise associated with APEX until there is a need
+ // Clear the noise associated with loopback and APEX.
if (android::base::StartsWith(value, "loop")) value = "";
+ if (android::base::StartsWith(entry.mount_point, "/apex/")) value = "";
}
- std::string property =
- "dev.mnt.blk" + ((entry.mount_point == "/") ? "/root" : entry.mount_point);
- std::replace(property.begin(), property.end(), '/', '.');
- if (value.empty() && android::base::GetProperty(property, "").empty()) return;
- property_set(property, value);
+ auto mount_prop = entry.mount_point;
+ if (mount_prop == "/") mount_prop = "/root";
+ std::replace(mount_prop.begin(), mount_prop.end(), '/', '.');
+ mount_prop = "dev.mnt.blk" + mount_prop;
+ // Set property even if its value does not change to trigger 'on property:'
+ // handling, except for clearing non-existent or already clear property.
+ // Goal is reduction of empty properties and associated triggers.
+ if (value.empty() && android::base::GetProperty(mount_prop, "").empty()) return;
+ property_set(mount_prop, value);
}
} // namespace
@@ -114,25 +126,27 @@
void MountHandler::MountHandlerFunction() {
rewind(fp_.get());
+ std::vector<MountHandlerEntry> touched;
+ auto untouched = mounts_;
char* buf = nullptr;
size_t len = 0;
- auto untouched = mounts_;
while (getline(&buf, &len, fp_.get()) != -1) {
- auto entry = ParseMount(std::string(buf, len));
+ auto entry = ParseMount(std::string(buf));
auto match = untouched.find(entry);
if (match == untouched.end()) {
- SetMountProperty(entry, true);
- mounts_.emplace(std::move(entry));
+ touched.emplace_back(std::move(entry));
} else {
untouched.erase(match);
}
}
free(buf);
for (auto entry : untouched) {
- auto match = mounts_.find(entry);
- if (match == mounts_.end()) continue;
- mounts_.erase(match);
SetMountProperty(entry, false);
+ mounts_.erase(entry);
+ }
+ for (auto entry : touched) {
+ SetMountProperty(entry, true);
+ mounts_.emplace(std::move(entry));
}
}
diff --git a/init/service.cpp b/init/service.cpp
index 6d08cb1..f5c13b9 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -177,7 +177,7 @@
Result<Success> Service::EnterNamespaces() const {
for (const auto& [nstype, path] : namespaces_to_enter_) {
auto fd = unique_fd{open(path.c_str(), O_RDONLY | O_CLOEXEC)};
- if (!fd) {
+ if (fd == -1) {
return ErrnoError() << "Could not open namespace at " << path;
}
if (setns(fd, nstype) == -1) {
diff --git a/libkeyutils/mini_keyctl.cpp b/libkeyutils/mini_keyctl.cpp
index e09c864..fe89e62 100644
--- a/libkeyutils/mini_keyctl.cpp
+++ b/libkeyutils/mini_keyctl.cpp
@@ -30,7 +30,6 @@
fprintf(stderr, "usage: mini-keyctl <action> [args,]\n");
fprintf(stderr, " mini-keyctl add <type> <desc> <data> <keyring>\n");
fprintf(stderr, " mini-keyctl padd <type> <desc> <keyring>\n");
- fprintf(stderr, " mini-keyctl dadd <type> <desc_prefix> <cert_dir> <keyring>\n");
fprintf(stderr, " mini-keyctl unlink <key> <keyring>\n");
fprintf(stderr, " mini-keyctl restrict_keyring <keyring>\n");
fprintf(stderr, " mini-keyctl security <key>\n");
@@ -56,14 +55,6 @@
std::string data = argv[4];
std::string keyring = argv[5];
return Add(type, desc, data, keyring);
- } else if (action == "dadd") {
- if (argc != 6) Usage(1);
- std::string type = argv[2];
- // The key description contains desc_prefix and an index.
- std::string desc_prefix = argv[3];
- std::string cert_dir = argv[4];
- std::string keyring = argv[5];
- return AddCertsFromDir(type, desc_prefix, cert_dir, keyring);
} else if (action == "padd") {
if (argc != 5) Usage(1);
std::string type = argv[2];
diff --git a/libkeyutils/mini_keyctl_utils.cpp b/libkeyutils/mini_keyctl_utils.cpp
index 9fe2dfe..56afea4 100644
--- a/libkeyutils/mini_keyctl_utils.cpp
+++ b/libkeyutils/mini_keyctl_utils.cpp
@@ -86,53 +86,6 @@
return false;
}
-int AddCertsFromDir(const std::string& type, const std::string& desc_prefix,
- const std::string& cert_dir, const std::string& keyring) {
- key_serial_t keyring_id;
- if (!GetKeyringId(keyring, &keyring_id)) {
- LOG(ERROR) << "Can not find keyring id";
- return 1;
- }
-
- std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(cert_dir.c_str()), closedir);
- if (!dir) {
- PLOG(WARNING) << "Failed to open directory " << cert_dir;
- return 1;
- }
- int keys_added = 0;
- struct dirent* dp;
- while ((dp = readdir(dir.get())) != NULL) {
- if (dp->d_type != DT_REG) {
- continue;
- }
- std::string cert_path = cert_dir + "/" + dp->d_name;
- std::string cert_buf;
- if (!android::base::ReadFileToString(cert_path, &cert_buf, false /* follow_symlinks */)) {
- LOG(ERROR) << "Failed to read " << cert_path;
- continue;
- }
-
- if (cert_buf.size() > kMaxCertSize) {
- LOG(ERROR) << "Certficate size too large: " << cert_path;
- continue;
- }
-
- // Add key to keyring.
- int key_desc_index = keys_added;
- std::string key_desc = desc_prefix + std::to_string(key_desc_index);
- key_serial_t key =
- add_key(type.c_str(), key_desc.c_str(), &cert_buf[0], cert_buf.size(), keyring_id);
- if (key < 0) {
- PLOG(ERROR) << "Failed to add key to keyring: " << cert_path;
- continue;
- }
- LOG(INFO) << "Key " << cert_path << " added to " << keyring << " with key id 0x" << std::hex
- << key;
- keys_added++;
- }
- return 0;
-}
-
int Unlink(key_serial_t key, const std::string& keyring) {
key_serial_t keyring_id;
if (!GetKeyringId(keyring, &keyring_id)) {
diff --git a/libkeyutils/mini_keyctl_utils.h b/libkeyutils/mini_keyctl_utils.h
index 804a357..3616831 100644
--- a/libkeyutils/mini_keyctl_utils.h
+++ b/libkeyutils/mini_keyctl_utils.h
@@ -18,11 +18,6 @@
#include <string>
-// Add all files in a directory as certificates to a keyring. |keyring| could be the keyring
-// description or keyring id in hex.
-int AddCertsFromDir(const std::string& type, const std::string& desc_prefix,
- const std::string& cert_dir, const std::string& keyring);
-
// Add key to a keyring. Returns non-zero if error happens.
int Add(const std::string& type, const std::string& desc, const std::string& data,
const std::string& keyring);
diff --git a/liblog/logger_name.cpp b/liblog/logger_name.cpp
index 3aa6841..ece0550 100644
--- a/liblog/logger_name.cpp
+++ b/liblog/logger_name.cpp
@@ -50,8 +50,9 @@
unsigned int ret;
if (!logName) {
- return static_cast<log_id_t>(0xFFFFFFFF);
+ return static_cast<log_id_t>(LOG_ID_MAX);
}
+
b = strrchr(logName, '/');
if (!b) {
b = logName;
@@ -65,5 +66,6 @@
return static_cast<log_id_t>(ret);
}
}
- return static_cast<log_id_t>(0xFFFFFFFF); /* should never happen */
+
+ return static_cast<log_id_t>(LOG_ID_MAX);
}
diff --git a/libprocessgroup/Android.bp b/libprocessgroup/Android.bp
index d97f09f..07cbce9 100644
--- a/libprocessgroup/Android.bp
+++ b/libprocessgroup/Android.bp
@@ -45,5 +45,6 @@
cflags: [
"-Wall",
"-Werror",
+ "-Wexit-time-destructors",
],
}
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index b3b497f..1e66fa4 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -227,13 +227,16 @@
#endif
+// WARNING: This function should be called only from SetupCgroups and only once.
+// It intentionally leaks an FD, so additional invocation will result in additional leak.
static bool WriteRcFile(const std::map<std::string, CgroupDescriptor>& descriptors) {
- std::string cgroup_rc_path = StringPrintf("%s/%s", CGROUPS_RC_DIR, CgroupMap::CGROUPS_RC_FILE);
- unique_fd fd(TEMP_FAILURE_RETRY(open(cgroup_rc_path.c_str(),
- O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC,
- S_IRUSR | S_IRGRP | S_IROTH)));
+ // WARNING: We are intentionally leaking the FD to keep the file open forever.
+ // Let init keep the FD open to prevent file mappings from becoming invalid in
+ // case the file gets deleted somehow.
+ int fd = TEMP_FAILURE_RETRY(open(CGROUPS_RC_PATH, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC,
+ S_IRUSR | S_IRGRP | S_IROTH));
if (fd < 0) {
- PLOG(ERROR) << "open() failed for " << cgroup_rc_path;
+ PLOG(ERROR) << "open() failed for " << CGROUPS_RC_PATH;
return false;
}
@@ -242,14 +245,14 @@
fl.controller_count_ = descriptors.size();
int ret = TEMP_FAILURE_RETRY(write(fd, &fl, sizeof(fl)));
if (ret < 0) {
- PLOG(ERROR) << "write() failed for " << cgroup_rc_path;
+ PLOG(ERROR) << "write() failed for " << CGROUPS_RC_PATH;
return false;
}
for (const auto& [name, descriptor] : descriptors) {
ret = TEMP_FAILURE_RETRY(write(fd, descriptor.controller(), sizeof(CgroupController)));
if (ret < 0) {
- PLOG(ERROR) << "write() failed for " << cgroup_rc_path;
+ PLOG(ERROR) << "write() failed for " << CGROUPS_RC_PATH;
return false;
}
}
@@ -350,38 +353,37 @@
return true;
}
- std::string cgroup_rc_path = StringPrintf("%s/%s", CGROUPS_RC_DIR, CGROUPS_RC_FILE);
- unique_fd fd(TEMP_FAILURE_RETRY(open(cgroup_rc_path.c_str(), O_RDONLY | O_CLOEXEC)));
+ unique_fd fd(TEMP_FAILURE_RETRY(open(CGROUPS_RC_PATH, O_RDONLY | O_CLOEXEC)));
if (fd < 0) {
- PLOG(ERROR) << "open() failed for " << cgroup_rc_path;
+ PLOG(ERROR) << "open() failed for " << CGROUPS_RC_PATH;
return false;
}
if (fstat(fd, &sb) < 0) {
- PLOG(ERROR) << "fstat() failed for " << cgroup_rc_path;
+ PLOG(ERROR) << "fstat() failed for " << CGROUPS_RC_PATH;
return false;
}
size_t file_size = sb.st_size;
if (file_size < sizeof(CgroupFile)) {
- LOG(ERROR) << "Invalid file format " << cgroup_rc_path;
+ LOG(ERROR) << "Invalid file format " << CGROUPS_RC_PATH;
return false;
}
CgroupFile* file_data = (CgroupFile*)mmap(nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0);
if (file_data == MAP_FAILED) {
- PLOG(ERROR) << "Failed to mmap " << cgroup_rc_path;
+ PLOG(ERROR) << "Failed to mmap " << CGROUPS_RC_PATH;
return false;
}
if (file_data->version_ != CgroupFile::FILE_CURR_VERSION) {
- LOG(ERROR) << cgroup_rc_path << " file version mismatch";
+ LOG(ERROR) << CGROUPS_RC_PATH << " file version mismatch";
munmap(file_data, file_size);
return false;
}
if (file_size != sizeof(CgroupFile) + file_data->controller_count_ * sizeof(CgroupController)) {
- LOG(ERROR) << cgroup_rc_path << " file has invalid size";
+ LOG(ERROR) << CGROUPS_RC_PATH << " file has invalid size";
munmap(file_data, file_size);
return false;
}
@@ -412,6 +414,18 @@
bool CgroupMap::SetupCgroups() {
std::map<std::string, CgroupDescriptor> descriptors;
+ if (getpid() != 1) {
+ LOG(ERROR) << "Cgroup setup can be done only by init process";
+ return false;
+ }
+
+ // Make sure we do this only one time. No need for std::call_once because
+ // init is a single-threaded process
+ if (access(CGROUPS_RC_PATH, F_OK) == 0) {
+ LOG(WARNING) << "Attempt to call SetupCgroups more than once";
+ return true;
+ }
+
// load cgroups.json file
if (!ReadDescriptors(&descriptors)) {
LOG(ERROR) << "Failed to load cgroup description file";
@@ -428,8 +442,8 @@
}
// mkdir <CGROUPS_RC_DIR> 0711 system system
- if (!Mkdir(CGROUPS_RC_DIR, 0711, "system", "system")) {
- LOG(ERROR) << "Failed to create directory for <CGROUPS_RC_FILE> file";
+ if (!Mkdir(android::base::Dirname(CGROUPS_RC_PATH), 0711, "system", "system")) {
+ LOG(ERROR) << "Failed to create directory for " << CGROUPS_RC_PATH << " file";
return false;
}
@@ -438,13 +452,12 @@
// and limits infrormation shared with unprivileged processes
// to the minimum subset of information from cgroups.json
if (!WriteRcFile(descriptors)) {
- LOG(ERROR) << "Failed to write " << CGROUPS_RC_FILE << " file";
+ LOG(ERROR) << "Failed to write " << CGROUPS_RC_PATH << " file";
return false;
}
- std::string cgroup_rc_path = StringPrintf("%s/%s", CGROUPS_RC_DIR, CGROUPS_RC_FILE);
- // chmod 0644 <cgroup_rc_path>
- if (fchmodat(AT_FDCWD, cgroup_rc_path.c_str(), 0644, AT_SYMLINK_NOFOLLOW) < 0) {
+ // chmod 0644 <CGROUPS_RC_PATH>
+ if (fchmodat(AT_FDCWD, CGROUPS_RC_PATH, 0644, AT_SYMLINK_NOFOLLOW) < 0) {
PLOG(ERROR) << "fchmodat() failed";
return false;
}
diff --git a/libprocessgroup/cgroup_map.h b/libprocessgroup/cgroup_map.h
index 1c355cd..304ae15 100644
--- a/libprocessgroup/cgroup_map.h
+++ b/libprocessgroup/cgroup_map.h
@@ -75,8 +75,6 @@
class CgroupMap {
public:
- static constexpr const char* CGROUPS_RC_FILE = "cgroup.rc";
-
// Selinux policy ensures only init process can successfully use this function
static bool SetupCgroups();
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index 6f973b8..46b8676 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -24,7 +24,7 @@
__BEGIN_DECLS
static constexpr const char* CGROUPV2_CONTROLLER_NAME = "cgroup2";
-static constexpr const char* CGROUPS_RC_DIR = "/dev/cgroup_info";
+static constexpr const char* CGROUPS_RC_PATH = "/dev/cgroup_info/cgroup.rc";
bool CgroupSetupCgroups();
bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path);
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index a1c58dd..3f2e1c1 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -284,17 +284,9 @@
}
}
-std::string Unwinder::FormatFrame(size_t frame_num) {
- if (frame_num >= frames_.size()) {
- return "";
- }
- return FormatFrame(frames_[frame_num], regs_->Is32Bit());
-}
-
-std::string Unwinder::FormatFrame(const FrameData& frame, bool is32bit) {
+std::string Unwinder::FormatFrame(const FrameData& frame) {
std::string data;
-
- if (is32bit) {
+ if (regs_->Is32Bit()) {
data += android::base::StringPrintf(" #%02zu pc %08" PRIx64, frame.num, frame.rel_pc);
} else {
data += android::base::StringPrintf(" #%02zu pc %016" PRIx64, frame.num, frame.rel_pc);
@@ -320,9 +312,24 @@
}
data += ')';
}
+
+ MapInfo* map_info = maps_->Find(frame.map_start);
+ if (map_info != nullptr && display_build_id_) {
+ std::string build_id = map_info->GetPrintableBuildID();
+ if (!build_id.empty()) {
+ data += " (BuildId: " + build_id + ')';
+ }
+ }
return data;
}
+std::string Unwinder::FormatFrame(size_t frame_num) {
+ if (frame_num >= frames_.size()) {
+ return "";
+ }
+ return FormatFrame(frames_[frame_num]);
+}
+
void Unwinder::SetJitDebug(JitDebug* jit_debug, ArchEnum arch) {
jit_debug->SetArch(arch);
jit_debug_ = jit_debug;
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index a0554e2..8b01654 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -88,7 +88,7 @@
}
std::string FormatFrame(size_t frame_num);
- static std::string FormatFrame(const FrameData& frame, bool is32bit);
+ std::string FormatFrame(const FrameData& frame);
void SetJitDebug(JitDebug* jit_debug, ArchEnum arch);
@@ -105,6 +105,8 @@
// NOTE: This does nothing unless resolving names is enabled.
void SetEmbeddedSoname(bool embedded_soname) { embedded_soname_ = embedded_soname; }
+ void SetDisplayBuildID(bool display_build_id) { display_build_id_ = display_build_id; }
+
#if !defined(NO_LIBDEXFILE_SUPPORT)
void SetDexFiles(DexFiles* dex_files, ArchEnum arch);
#endif
@@ -130,6 +132,7 @@
#endif
bool resolve_names_ = true;
bool embedded_soname_ = true;
+ bool display_build_id_ = false;
ErrorData last_error_;
};
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index d6ca9b7..207d46e 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -23,6 +23,8 @@
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
+#include "Check.h"
+
namespace unwindstack {
class RegsFake : public Regs {
@@ -47,7 +49,10 @@
void IterateRegisters(std::function<void(const char*, uint64_t)>) override {}
- bool Is32Bit() { return false; }
+ bool Is32Bit() {
+ CHECK(fake_arch_ != ARCH_UNKNOWN);
+ return fake_arch_ == ARCH_ARM || fake_arch_ == ARCH_X86 || fake_arch_ == ARCH_MIPS;
+ }
uint64_t GetPcAdjustment(uint64_t, Elf*) override { return 2; }
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 504b57a..48e038e 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -58,7 +58,9 @@
maps_.reset(new Maps);
ElfFake* elf = new ElfFake(new MemoryFake);
- elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
+ ElfInterfaceFake* interface_fake = new ElfInterfaceFake(nullptr);
+ interface_fake->FakeSetBuildID("FAKE");
+ elf->FakeSetInterface(interface_fake);
AddMapInfo(0x1000, 0x8000, 0, PROT_READ | PROT_WRITE, "/system/fake/libc.so", elf);
AddMapInfo(0x10000, 0x12000, 0, PROT_READ | PROT_WRITE, "[stack]");
@@ -1102,7 +1104,15 @@
}
// Verify format frame code.
-TEST_F(UnwinderTest, format_frame_static) {
+TEST_F(UnwinderTest, format_frame) {
+ RegsFake regs_arm(10);
+ regs_arm.FakeSetArch(ARCH_ARM);
+ Unwinder unwinder32(10, maps_.get(), ®s_arm, process_memory_);
+
+ RegsFake regs_arm64(10);
+ regs_arm64.FakeSetArch(ARCH_ARM64);
+ Unwinder unwinder64(10, maps_.get(), ®s_arm64, process_memory_);
+
FrameData frame;
frame.num = 1;
frame.rel_pc = 0x1000;
@@ -1117,39 +1127,61 @@
frame.map_flags = PROT_READ;
EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (offset 0x2000) (function+100)",
- Unwinder::FormatFrame(frame, false));
+ unwinder64.FormatFrame(frame));
EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (offset 0x2000) (function+100)",
- Unwinder::FormatFrame(frame, true));
+ unwinder32.FormatFrame(frame));
frame.map_elf_start_offset = 0;
EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (function+100)",
- Unwinder::FormatFrame(frame, false));
- EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100)",
- Unwinder::FormatFrame(frame, true));
+ unwinder64.FormatFrame(frame));
+ EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100)", unwinder32.FormatFrame(frame));
frame.function_offset = 0;
EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (function)",
- Unwinder::FormatFrame(frame, false));
- EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function)", Unwinder::FormatFrame(frame, true));
+ unwinder64.FormatFrame(frame));
+ EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function)", unwinder32.FormatFrame(frame));
// Verify the function name is demangled.
frame.function_name = "_ZN4funcEv";
- EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (func())",
- Unwinder::FormatFrame(frame, false));
- EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (func())", Unwinder::FormatFrame(frame, true));
+ EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (func())", unwinder64.FormatFrame(frame));
+ EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (func())", unwinder32.FormatFrame(frame));
frame.function_name = "";
- EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so", Unwinder::FormatFrame(frame, false));
- EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so", Unwinder::FormatFrame(frame, true));
+ EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so", unwinder64.FormatFrame(frame));
+ EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so", unwinder32.FormatFrame(frame));
frame.map_name = "";
- EXPECT_EQ(" #01 pc 0000000000001000 <anonymous:3000>", Unwinder::FormatFrame(frame, false));
- EXPECT_EQ(" #01 pc 00001000 <anonymous:3000>", Unwinder::FormatFrame(frame, true));
+ EXPECT_EQ(" #01 pc 0000000000001000 <anonymous:3000>", unwinder64.FormatFrame(frame));
+ EXPECT_EQ(" #01 pc 00001000 <anonymous:3000>", unwinder32.FormatFrame(frame));
frame.map_start = 0;
frame.map_end = 0;
- EXPECT_EQ(" #01 pc 0000000000001000 <unknown>", Unwinder::FormatFrame(frame, false));
- EXPECT_EQ(" #01 pc 00001000 <unknown>", Unwinder::FormatFrame(frame, true));
+ EXPECT_EQ(" #01 pc 0000000000001000 <unknown>", unwinder64.FormatFrame(frame));
+ EXPECT_EQ(" #01 pc 00001000 <unknown>", unwinder32.FormatFrame(frame));
+}
+
+TEST_F(UnwinderTest, format_frame_build_id) {
+ RegsFake regs(10);
+ regs.FakeSetArch(ARCH_ARM);
+ Unwinder unwinder(10, maps_.get(), ®s, process_memory_);
+
+ FrameData frame;
+ frame.num = 1;
+ frame.rel_pc = 0x1000;
+ frame.pc = 0x4000;
+ frame.sp = 0x1000;
+ frame.function_name = "function";
+ frame.function_offset = 100;
+ frame.map_name = "/fake/libfake.so";
+ frame.map_elf_start_offset = 0;
+ frame.map_start = 0x3000;
+ frame.map_end = 0x6000;
+ frame.map_flags = PROT_READ;
+
+ EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100)", unwinder.FormatFrame(frame));
+ unwinder.SetDisplayBuildID(true);
+ EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100) (BuildId: 46414b45)",
+ unwinder.FormatFrame(frame));
}
static std::string ArchToString(ArchEnum arch) {
@@ -1167,7 +1199,7 @@
}
// Verify format frame code.
-TEST_F(UnwinderTest, format_frame) {
+TEST_F(UnwinderTest, format_frame_by_arch) {
std::vector<Regs*> reg_list;
RegsArm* arm = new RegsArm;
arm->set_pc(0x2300);
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 9538bba..bc1543b 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -38,6 +38,19 @@
],
},
},
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ "unsigned-integer-overflow",
+ "shift",
+ "integer-divide-by-zero",
+ "implicit-signed-integer-truncation",
+ // TODO: Fix crash when we enable this option
+ // "implicit-unsigned-integer-truncation",
+ // TODO: not tested yet.
+ // "implicit-integer-sign-change",
+ ],
+ },
}
cc_defaults {
diff --git a/libziparchive/zip_writer.cc b/libziparchive/zip_writer.cc
index 981df3a..0df0fa5 100644
--- a/libziparchive/zip_writer.cc
+++ b/libziparchive/zip_writer.cc
@@ -30,9 +30,13 @@
#include "entry_name_utils-inl.h"
#include "zip_archive_common.h"
-#if !defined(powerof2)
-#define powerof2(x) ((((x)-1) & (x)) == 0)
-#endif
+#undef powerof2
+#define powerof2(x) \
+ ({ \
+ __typeof__(x) _x = (x); \
+ __typeof__(x) _x2; \
+ __builtin_add_overflow(_x, -1, &_x2) ? 1 : ((_x2 & _x) == 0); \
+ })
/* Zip compression methods we support */
enum {
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 2d3fbfc..2de7378 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -110,7 +110,7 @@
*/
#define PSI_WINDOW_SIZE_MS 1000
/* Polling period after initial PSI signal */
-#define PSI_POLL_PERIOD_MS 40
+#define PSI_POLL_PERIOD_MS 10
/* Poll for the duration of one window after initial PSI signal */
#define PSI_POLL_COUNT (PSI_WINDOW_SIZE_MS / PSI_POLL_PERIOD_MS)
diff --git a/logcat/event.logtags b/logcat/event.logtags
index da8d2d4..3a1d36f 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -116,8 +116,8 @@
# audio
# 61000 - 61199 reserved for audioserver
-# 0 for screen off, 1 for screen on, 2 for key-guard done
-70000 screen_toggled (screen_state|1|5)
+# com.android.server.policy
+# 70000 - 70199 reserved for PhoneWindowManager and other policies
# aggregation service
70200 aggregation (aggregation time|2|3)
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index d5c40be..b32b437 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -33,6 +33,7 @@
#include <android-base/file.h>
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <gtest/gtest.h>
#include <log/event_tag_map.h>
#include <log/log.h>
@@ -1747,3 +1748,13 @@
EXPECT_EQ(logcatHelpTextSize * 2, logcatLastHelpTextSize);
#endif
}
+
+TEST(logcat, invalid_buffer) {
+ FILE* fp = popen("logcat -b foo 2>&1", "r");
+ ASSERT_NE(nullptr, fp);
+ std::string output;
+ ASSERT_TRUE(android::base::ReadFdToString(fileno(fp), &output));
+ pclose(fp);
+
+ ASSERT_TRUE(android::base::StartsWith(output, "unknown buffer foo\n"));
+}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 54b019e..f78a926 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -8,6 +8,7 @@
LOCAL_SRC_FILES := $(LOCAL_MODULE)
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+LOCAL_REQUIRED_MODULES := fsverity_init
# The init symlink must be a post install command of a file that is to TARGET_ROOT_OUT.
# Since init.rc is required for init and satisfies that requirement, we hijack it to create the symlink.
@@ -57,6 +58,15 @@
endif
#######################################
+# fsverity_init
+
+include $(CLEAR_VARS)
+LOCAL_MODULE:= fsverity_init
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_SRC_FILES := fsverity_init.sh
+include $(BUILD_PREBUILT)
+
+#######################################
# init.environ.rc
include $(CLEAR_VARS)
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index 9cf93ca..0fccd31 100644
--- a/rootdir/etc/ld.config.legacy.txt
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -11,14 +11,13 @@
dir.legacy = /odm
dir.legacy = /sbin
-dir.legacy = /data/nativetest
-dir.legacy = /data/nativetest64
-dir.legacy = /data/benchmarktest
-dir.legacy = /data/benchmarktest64
-
# Except for /postinstall, where only /system and /product are searched
dir.postinstall = /postinstall
+# Fallback entry to provide APEX namespace lookups for binaries anywhere else.
+# This must be last.
+dir.legacy = /data
+
[legacy]
namespace.default.isolated = false
@@ -54,8 +53,7 @@
# Visible because some libraries are dlopen'ed, e.g. libopenjdk is dlopen'ed by
# libart.
namespace.default.visible = true
-namespace.default.link.runtime.shared_libs = libart.so:libartd.so
-namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs = libdexfile_external.so
namespace.default.link.runtime.shared_libs += libnativebridge.so
namespace.default.link.runtime.shared_libs += libnativehelper.so
namespace.default.link.runtime.shared_libs += libnativeloader.so
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 85deacf..2b0ef4c 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -27,13 +27,12 @@
# necessary) the unrestricted subdirs above. Then clean this up.
dir.unrestricted = /data/local/tmp
-dir.system = /data/nativetest
-dir.system = /data/nativetest64
-dir.system = /data/benchmarktest
-dir.system = /data/benchmarktest64
-
dir.postinstall = /postinstall
+# Fallback entry to provide APEX namespace lookups for binaries anywhere else.
+# This must be last.
+dir.system = /data
+
[system]
additional.namespaces = runtime,conscrypt,media,resolv,sphal,vndk,rs
@@ -133,8 +132,7 @@
# Visible because some libraries are dlopen'ed, e.g. libopenjdk is dlopen'ed by
# libart.
namespace.default.visible = true
-namespace.default.link.runtime.shared_libs = libart.so:libartd.so
-namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs = libdexfile_external.so
namespace.default.link.runtime.shared_libs += libnativebridge.so
namespace.default.link.runtime.shared_libs += libnativehelper.so
namespace.default.link.runtime.shared_libs += libnativeloader.so
@@ -577,8 +575,7 @@
namespace.default.links = runtime,resolv
namespace.default.visible = true
-namespace.default.link.runtime.shared_libs = libart.so:libartd.so
-namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs = libdexfile_external.so
namespace.default.link.runtime.shared_libs += libnativebridge.so
namespace.default.link.runtime.shared_libs += libnativehelper.so
namespace.default.link.runtime.shared_libs += libnativeloader.so
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 26e1dd9..c8312df 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -27,13 +27,12 @@
# necessary) the unrestricted subdirs above. Then clean this up.
dir.unrestricted = /data/local/tmp
-dir.system = /data/nativetest
-dir.system = /data/nativetest64
-dir.system = /data/benchmarktest
-dir.system = /data/benchmarktest64
-
dir.postinstall = /postinstall
+# Fallback entry to provide APEX namespace lookups for binaries anywhere else.
+# This must be last.
+dir.system = /data
+
[system]
additional.namespaces = runtime,conscrypt,media,resolv,sphal,vndk,rs
@@ -74,8 +73,7 @@
# Visible because some libraries are dlopen'ed, e.g. libopenjdk is dlopen'ed by
# libart.
namespace.default.visible = true
-namespace.default.link.runtime.shared_libs = libart.so:libartd.so
-namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs = libdexfile_external.so
namespace.default.link.runtime.shared_libs += libnativebridge.so
namespace.default.link.runtime.shared_libs += libnativehelper.so
namespace.default.link.runtime.shared_libs += libnativeloader.so
@@ -400,8 +398,7 @@
namespace.default.links = runtime,resolv
namespace.default.visible = true
-namespace.default.link.runtime.shared_libs = libart.so:libartd.so
-namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs = libdexfile_external.so
namespace.default.link.runtime.shared_libs += libnativebridge.so
namespace.default.link.runtime.shared_libs += libnativehelper.so
namespace.default.link.runtime.shared_libs += libnativeloader.so
diff --git a/rootdir/fsverity_init.sh b/rootdir/fsverity_init.sh
new file mode 100644
index 0000000..29e4519
--- /dev/null
+++ b/rootdir/fsverity_init.sh
@@ -0,0 +1,29 @@
+#!/system/bin/sh
+#
+# Copyright (C) 2019 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.
+#
+
+# Enforce fsverity signature checking
+echo 1 > /proc/sys/fs/verity/require_signatures
+
+# Load all keys
+for cert in /product/etc/security/fsverity/*.der; do
+ /system/bin/mini-keyctl padd asymmetric fsv_product .fs-verity < "$cert" ||
+ log -p e -t fsverity_init "Failed to load $cert"
+done
+
+# Prevent future key links to .fs-verity keyring
+/system/bin/mini-keyctl restrict_keyring .fs-verity ||
+ log -p e -t fsverity_init "Failed to restrict .fs-verity keyring"
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 8e63a81..2b6e9c7 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -222,6 +222,9 @@
chmod 0664 /dev/cpuset/restricted/tasks
chmod 0664 /dev/cpuset/tasks
+ # make the PSI monitor accessible to others
+ chown system system /proc/pressure/memory
+ chmod 0664 /proc/pressure/memory
# qtaguid will limit access to specific data based on group memberships.
# net_bw_acct grants impersonation of socket owners.
@@ -420,12 +423,7 @@
# Load fsverity keys. This needs to happen before apexd, as post-install of
# APEXes may rely on keys.
- exec -- /system/bin/mini-keyctl dadd asymmetric product_cert /product/etc/security/cacerts_fsverity .fs-verity
- exec -- /system/bin/mini-keyctl dadd asymmetric vendor_cert /vendor/etc/security/cacerts_fsverity .fs-verity
- # Prevent future key links to fsverity keyring
- exec -- /system/bin/mini-keyctl restrict_keyring .fs-verity
- # Enforce fsverity signature checking
- write /proc/sys/fs/verity/require_signatures 1
+ exec -- /system/bin/fsverity_init
# Make sure that apexd is started in the default namespace
enter_default_mount_ns