Merge "adb: make `adb reconnect` perform a USB reset."
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index 8a50003..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();
@@ -274,11 +276,16 @@
{ .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) {
@@ -330,13 +337,13 @@
}
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) {
@@ -361,6 +368,10 @@
}
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);
@@ -590,6 +601,8 @@
}
std::thread monitor_thread_;
+
+ bool worker_started_;
std::thread worker_thread_;
std::atomic<bool> stopped_;
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/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/tests/Android.bp b/fs_mgr/tests/Android.bp
index 19737fe..eb9f525 100644
--- a/fs_mgr/tests/Android.bp
+++ b/fs_mgr/tests/Android.bp
@@ -52,6 +52,14 @@
host_supported: true,
}
+sh_test {
+ name: "adb-remount-sh",
+ src: "adb-remount-test.sh",
+ filename: "adb-remount-test.sh",
+ test_suites: ["general-tests"],
+ test_config: "adb-remount-sh.xml",
+}
+
java_test_host {
name: "fs_mgr_vendor_overlay_test",
diff --git a/fs_mgr/tests/adb-remount-sh.xml b/fs_mgr/tests/adb-remount-sh.xml
new file mode 100644
index 0000000..716e324
--- /dev/null
+++ b/fs_mgr/tests/adb-remount-sh.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for adb remount test cases">
+ <option name="test-suite-tag" value="adb-remount" />
+ <!-- This test requires a device, so it's not annotated with a null-device -->
+ <test class="com.android.tradefed.testtype.binary.ExecutableHostTest" >
+ <option name="binary" value="adb-remount-test.sh" />
+ </test>
+</configuration>
+
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_draw.cpp b/healthd/healthd_draw.cpp
index 706dc80..3da8bda 100644
--- a/healthd/healthd_draw.cpp
+++ b/healthd/healthd_draw.cpp
@@ -64,7 +64,8 @@
clear_screen();
/* try to display *something* */
- if (batt_anim->cur_level < 0 || batt_anim->num_frames == 0)
+ if (batt_anim->cur_status == BATTERY_STATUS_UNKNOWN || batt_anim->cur_level < 0 ||
+ batt_anim->num_frames == 0)
draw_unknown(surf_unknown);
else
draw_battery(batt_anim);
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index bde5fbe..0e5aa4f 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -77,6 +77,7 @@
#define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC)
#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC)
#define UNPLUGGED_DISPLAY_TIME (3 * MSEC_PER_SEC)
+#define MAX_BATT_LEVEL_WAIT_TIME (3 * MSEC_PER_SEC)
#define LAST_KMSG_MAX_SZ (32 * 1024)
@@ -105,6 +106,7 @@
int64_t next_screen_transition;
int64_t next_key_check;
int64_t next_pwr_check;
+ int64_t wait_batt_level_timestamp;
key_state keys[KEY_MAX + 1];
@@ -290,6 +292,21 @@
if (!batt_anim->run || now < charger->next_screen_transition) return;
+ // If battery level is not ready, keep checking in the defined time
+ if (batt_prop == nullptr ||
+ (batt_prop->batteryLevel == 0 && batt_prop->batteryStatus == BATTERY_STATUS_UNKNOWN)) {
+ if (charger->wait_batt_level_timestamp == 0) {
+ // Set max delay time and skip drawing screen
+ charger->wait_batt_level_timestamp = now + MAX_BATT_LEVEL_WAIT_TIME;
+ LOGV("[%" PRId64 "] wait for battery capacity ready\n", now);
+ return;
+ } else if (now <= charger->wait_batt_level_timestamp) {
+ // Do nothing, keep waiting
+ return;
+ }
+ // If timeout and battery level is still not ready, draw unknown battery
+ }
+
if (healthd_draw == nullptr) {
if (healthd_config && healthd_config->screen_on) {
if (!healthd_config->screen_on(batt_prop)) {
@@ -709,6 +726,7 @@
charger->next_screen_transition = -1;
charger->next_key_check = -1;
charger->next_pwr_check = -1;
+ charger->wait_batt_level_timestamp = 0;
// Initialize Health implementation (which initializes the internal BatteryMonitor).
Health::initInstance(config);
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/libcutils/Android.bp b/libcutils/Android.bp
index 83a7140..a27ecef 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -83,6 +83,8 @@
],
},
windows: {
+ host_ldlibs: ["-lws2_32"],
+
srcs: [
"socket_inaddr_any_server_windows.cpp",
"socket_network_client_windows.cpp",
@@ -91,9 +93,6 @@
],
enabled: true,
- shared: {
- enabled: false,
- },
cflags: [
"-D_GNU_SOURCE",
],
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/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/DwarfEhFrameWithHdr.cpp b/libunwindstack/DwarfEhFrameWithHdr.cpp
index 668527a..802beca 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.cpp
+++ b/libunwindstack/DwarfEhFrameWithHdr.cpp
@@ -61,6 +61,14 @@
table_encoding_ = data[3];
table_entry_size_ = memory_.template GetEncodedSize<AddressType>(table_encoding_);
+ // If we can't perform a binary search on the entries, it's not worth
+ // using this object. The calling code will fall back to the DwarfEhFrame
+ // object in this case.
+ if (table_entry_size_ == 0) {
+ last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
+ return false;
+ }
+
memory_.set_pc_offset(memory_.cur_offset());
if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding_, &ptr_offset_)) {
last_error_.code = DWARF_ERROR_MEMORY_INVALID;
@@ -137,13 +145,13 @@
}
template <typename AddressType>
-bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset,
- uint64_t total_entries) {
- CHECK(fde_count_ > 0);
- CHECK(total_entries <= fde_count_);
+bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
+ if (fde_count_ == 0) {
+ return false;
+ }
size_t first = 0;
- size_t last = total_entries;
+ size_t last = fde_count_;
while (first < last) {
size_t current = (first + last) / 2;
const FdeInfo* info = GetFdeInfoFromIndex(current);
@@ -172,87 +180,6 @@
}
template <typename AddressType>
-bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) {
- CHECK(fde_count_ != 0);
- last_error_.code = DWARF_ERROR_NONE;
- last_error_.address = 0;
-
- // We can do a binary search if the pc is in the range of the elements
- // that have already been cached.
- if (!fde_info_.empty()) {
- const FdeInfo* info = &fde_info_[fde_info_.size() - 1];
- if (pc >= info->pc) {
- *fde_offset = info->offset;
- return true;
- }
- if (pc < info->pc) {
- return GetFdeOffsetBinary(pc, fde_offset, fde_info_.size());
- }
- }
-
- if (cur_entries_offset_ == 0) {
- // All entries read, or error encountered.
- return false;
- }
-
- memory_.set_data_offset(entries_data_offset_);
- memory_.set_cur_offset(cur_entries_offset_);
- memory_.set_pc_offset(0);
- cur_entries_offset_ = 0;
-
- FdeInfo* prev_info = nullptr;
- for (size_t current = fde_info_.size();
- current < fde_count_ && memory_.cur_offset() < entries_end_; current++) {
- FdeInfo* info = &fde_info_[current];
- uint64_t value;
- if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) ||
- !memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) {
- fde_info_.erase(current);
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- // Relative encodings require adding in the load bias.
- if (IsEncodingRelative(table_encoding_)) {
- value += load_bias_;
- }
- info->pc = value;
-
- if (pc < info->pc) {
- if (prev_info == nullptr) {
- return false;
- }
- cur_entries_offset_ = memory_.cur_offset();
- *fde_offset = prev_info->offset;
- return true;
- }
- prev_info = info;
- }
-
- if (fde_count_ == fde_info_.size() && pc >= prev_info->pc) {
- *fde_offset = prev_info->offset;
- return true;
- }
- return false;
-}
-
-template <typename AddressType>
-bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
- if (fde_count_ == 0) {
- return false;
- }
-
- if (table_entry_size_ > 0) {
- // Do a binary search since the size of each table entry is fixed.
- return GetFdeOffsetBinary(pc, fde_offset, fde_count_);
- } else {
- // Do a sequential search since each table entry size is variable.
- return GetFdeOffsetSequential(pc, fde_offset);
- }
-}
-
-template <typename AddressType>
void DwarfEhFrameWithHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
for (size_t i = 0; i < fde_count_; i++) {
const FdeInfo* info = GetFdeInfoFromIndex(i);
diff --git a/libunwindstack/DwarfEhFrameWithHdr.h b/libunwindstack/DwarfEhFrameWithHdr.h
index e3e9ca8..0e5eef7 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.h
+++ b/libunwindstack/DwarfEhFrameWithHdr.h
@@ -69,10 +69,6 @@
const FdeInfo* GetFdeInfoFromIndex(size_t index);
- bool GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset);
-
- bool GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries);
-
void GetFdes(std::vector<const DwarfFde*>* fdes) override;
protected:
diff --git a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
index 910ae36..be9e721 100644
--- a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
@@ -95,6 +95,13 @@
EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset());
EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset());
+ // Verify a zero table entry size fails to init.
+ this->memory_.SetData8(0x1003, 0x1);
+ ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0));
+ ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode());
+ // Reset the value back to the original.
+ this->memory_.SetData8(0x1003, DW_EH_PE_sdata4);
+
// Verify a zero fde count fails to init.
this->memory_.SetData32(0x1006, 0);
ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0));
@@ -276,9 +283,8 @@
EXPECT_EQ(0x500U, info->offset);
}
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_verify) {
+TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_verify) {
this->eh_frame_->TestSetTableEntrySize(0x10);
- this->eh_frame_->TestSetFdeCount(10);
typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
for (size_t i = 0; i < 10; i++) {
@@ -288,105 +294,42 @@
}
uint64_t fde_offset;
- EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x100, &fde_offset, 10));
+ this->eh_frame_->TestSetFdeCount(10);
+ EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
// Not an error, just not found.
ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
// Even number of elements.
for (size_t i = 0; i < 10; i++) {
+ SCOPED_TRACE(testing::Message() << "Failed at index " << i);
TypeParam pc = 0x1000 * (i + 1);
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 10)) << "Failed at index " << i;
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 10))
- << "Failed at index " << i;
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 10))
- << "Failed at index " << i;
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
+ EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset));
+ EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
+ EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset));
+ EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
+ EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset));
+ EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
}
+
// Odd number of elements.
+ this->eh_frame_->TestSetFdeCount(9);
for (size_t i = 0; i < 9; i++) {
+ SCOPED_TRACE(testing::Message() << "Failed at index " << i);
TypeParam pc = 0x1000 * (i + 1);
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 9)) << "Failed at index " << i;
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 9))
- << "Failed at index " << i;
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 9))
- << "Failed at index " << i;
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
+ EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset));
+ EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
+ EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset));
+ EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
+ EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset));
+ EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
}
}
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_index_fail) {
+TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_index_fail) {
this->eh_frame_->TestSetTableEntrySize(0x10);
this->eh_frame_->TestSetFdeCount(10);
uint64_t fde_offset;
- EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x1000, &fde_offset, 10));
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential) {
- this->eh_frame_->TestSetFdeCount(10);
- this->eh_frame_->TestSetEntriesDataOffset(0x100);
- this->eh_frame_->TestSetEntriesEnd(0x2000);
- this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
-
- this->memory_.SetData32(0x1040, 0x340);
- this->memory_.SetData32(0x1044, 0x500);
-
- this->memory_.SetData32(0x1048, 0x440);
- this->memory_.SetData32(0x104c, 0x600);
-
- // Verify that if entries is zero, that it fails.
- uint64_t fde_offset;
- ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset));
- this->eh_frame_->TestSetCurEntriesOffset(0x1040);
-
- ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset));
- EXPECT_EQ(0x500U, fde_offset);
-
- ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset));
- EXPECT_EQ(0x600U, fde_offset);
-
- // Expect that the data is cached so no more memory reads will occur.
- this->memory_.Clear();
- ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset));
- EXPECT_EQ(0x600U, fde_offset);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential_last_element) {
- this->eh_frame_->TestSetFdeCount(2);
- this->eh_frame_->TestSetEntriesDataOffset(0x100);
- this->eh_frame_->TestSetEntriesEnd(0x2000);
- this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
- this->eh_frame_->TestSetCurEntriesOffset(0x1040);
-
- this->memory_.SetData32(0x1040, 0x340);
- this->memory_.SetData32(0x1044, 0x500);
-
- this->memory_.SetData32(0x1048, 0x440);
- this->memory_.SetData32(0x104c, 0x600);
-
- uint64_t fde_offset;
- ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset));
- EXPECT_EQ(0x600U, fde_offset);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential_end_check) {
- this->eh_frame_->TestSetFdeCount(2);
- this->eh_frame_->TestSetEntriesDataOffset(0x100);
- this->eh_frame_->TestSetEntriesEnd(0x1048);
- this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
-
- this->memory_.SetData32(0x1040, 0x340);
- this->memory_.SetData32(0x1044, 0x500);
-
- this->memory_.SetData32(0x1048, 0x440);
- this->memory_.SetData32(0x104c, 0x600);
-
- uint64_t fde_offset;
- ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset));
- ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
+ EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset));
}
TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) {
@@ -397,7 +340,7 @@
ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
}
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_binary_search) {
+TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_search) {
this->eh_frame_->TestSetTableEntrySize(16);
this->eh_frame_->TestSetFdeCount(10);
@@ -417,26 +360,6 @@
EXPECT_EQ(0x10700U, fde_offset);
}
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_sequential_search) {
- this->eh_frame_->TestSetFdeCount(10);
- this->eh_frame_->TestSetTableEntrySize(0);
-
- typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
- info.pc = 0x50;
- info.offset = 0x10000;
- this->eh_frame_->TestSetFdeInfo(0, info);
- info.pc = 0x150;
- info.offset = 0x10100;
- this->eh_frame_->TestSetFdeInfo(1, info);
- info.pc = 0x250;
- info.offset = 0x10200;
- this->eh_frame_->TestSetFdeInfo(2, info);
-
- uint64_t fde_offset;
- ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x200, &fde_offset));
- EXPECT_EQ(0x10100U, fde_offset);
-}
-
TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) {
// CIE 32 information.
this->memory_.SetData32(0xf000, 0x100);
@@ -526,10 +449,8 @@
REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, GetFdes,
GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel,
GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached,
- GetFdeOffsetBinary_verify, GetFdeOffsetBinary_index_fail,
- GetFdeOffsetSequential, GetFdeOffsetSequential_last_element,
- GetFdeOffsetSequential_end_check, GetFdeOffsetFromPc_fail_fde_count,
- GetFdeOffsetFromPc_binary_search, GetFdeOffsetFromPc_sequential_search,
+ GetFdeOffsetFromPc_verify, GetFdeOffsetFromPc_index_fail,
+ GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_search,
GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found);
typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes;
diff --git a/libutils/Android.bp b/libutils/Android.bp
index c67ff8f..3e7d0ba 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -69,6 +69,7 @@
],
shared_libs: [
+ "libcutils",
"liblog",
],
@@ -83,7 +84,6 @@
cflags: ["-fvisibility=protected"],
shared_libs: [
- "libcutils",
"libprocessgroup",
"libdl",
"libvndksupport",
@@ -98,14 +98,6 @@
exclude_shared_libs: ["libvndksupport"],
},
- host: {
- cflags: ["-DLIBUTILS_NATIVE=1"],
-
- shared: {
- enabled: false,
- },
- },
-
linux_bionic: {
enabled: true,
},
@@ -180,18 +172,20 @@
},
},
+ shared_libs: [
+ "libutils",
+ "libbacktrace",
+ ],
+
target: {
- android: {
- shared_libs: [
- "libutils",
- "libbacktrace",
- ],
- },
linux: {
srcs: [
"ProcessCallStack.cpp",
],
},
+ windows: {
+ enabled: false,
+ },
},
}
diff --git a/libutils/Mutex_test.cpp b/libutils/Mutex_test.cpp
index 8a1805f..79f4302 100644
--- a/libutils/Mutex_test.cpp
+++ b/libutils/Mutex_test.cpp
@@ -29,4 +29,20 @@
android::Mutex::Autolock _l(mLock);
i = 0;
modifyLockedVariable();
-}
\ No newline at end of file
+}
+
+TEST(Mutex, tryLock) {
+ if (mLock.tryLock() != 0) {
+ return;
+ }
+ mLock.unlock();
+}
+
+#if defined(__ANDROID__)
+TEST(Mutex, timedLock) {
+ if (mLock.timedLock(1) != 0) {
+ return;
+ }
+ mLock.unlock();
+}
+#endif
diff --git a/libutils/include/utils/Mutex.h b/libutils/include/utils/Mutex.h
index 29c2e8c..1325bf3 100644
--- a/libutils/include/utils/Mutex.h
+++ b/libutils/include/utils/Mutex.h
@@ -108,7 +108,7 @@
void unlock() RELEASE();
// lock if possible; returns 0 on success, error otherwise
- status_t tryLock() TRY_ACQUIRE(true);
+ status_t tryLock() TRY_ACQUIRE(0);
#if defined(__ANDROID__)
// Lock the mutex, but don't wait longer than timeoutNs (relative time).
@@ -122,7 +122,7 @@
// which is subject to NTP adjustments, and includes time during suspend,
// so a timeout may occur even though no processes could run.
// Not holding a partial wakelock may lead to a system suspend.
- status_t timedLock(nsecs_t timeoutNs) TRY_ACQUIRE(true);
+ status_t timedLock(nsecs_t timeoutNs) TRY_ACQUIRE(0);
#endif
// Manages the mutex automatically. It'll be locked when Autolock is
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/rootdir/Android.mk b/rootdir/Android.mk
index 54b019e..5d307b8 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)
@@ -366,3 +376,5 @@
$(hide) echo -n > $@
$(hide) $(foreach lib,$(PRIVATE_VNDK_SAMEPROCESS_LIBRARIES), \
echo $(lib).so >> $@;)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/rootdir/avb/Android.mk b/rootdir/avb/Android.mk
new file mode 100644
index 0000000..5dc019c
--- /dev/null
+++ b/rootdir/avb/Android.mk
@@ -0,0 +1,46 @@
+LOCAL_PATH:= $(call my-dir)
+
+#######################################
+# q-gsi.avbpubkey
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := q-gsi.avbpubkey
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
+else
+LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
+endif
+
+include $(BUILD_PREBUILT)
+
+#######################################
+# r-gsi.avbpubkey
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := r-gsi.avbpubkey
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
+else
+LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
+endif
+
+include $(BUILD_PREBUILT)
+
+#######################################
+# s-gsi.avbpubkey
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := s-gsi.avbpubkey
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
+else
+LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
+endif
+
+include $(BUILD_PREBUILT)
diff --git a/rootdir/avb/q-gsi.avbpubkey b/rootdir/avb/q-gsi.avbpubkey
new file mode 100644
index 0000000..5ed7543
--- /dev/null
+++ b/rootdir/avb/q-gsi.avbpubkey
Binary files differ
diff --git a/rootdir/avb/r-gsi.avbpubkey b/rootdir/avb/r-gsi.avbpubkey
new file mode 100644
index 0000000..2609b30
--- /dev/null
+++ b/rootdir/avb/r-gsi.avbpubkey
Binary files differ
diff --git a/rootdir/avb/s-gsi.avbpubkey b/rootdir/avb/s-gsi.avbpubkey
new file mode 100644
index 0000000..9065fb8
--- /dev/null
+++ b/rootdir/avb/s-gsi.avbpubkey
Binary files differ
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index c23ee95..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
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 6034f03..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
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index d769c34..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
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..473cd8d 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
@@ -654,6 +652,12 @@
write /proc/sys/vm/dirty_expire_centisecs 200
write /proc/sys/vm/dirty_background_ratio 5
+ # F2FS tuning. Set cp_interval larger than dirty_expire_centisecs
+ # to avoid power consumption when system becomes mostly idle. Be careful
+ # to make it too large, since it may bring userdata loss, if they
+ # are not aware of using fsync()/sync() to prepare sudden power-cut.
+ write /sys/fs/f2fs/${dev.mnt.blk.data}/cp_interval 200
+
# Permissions for System Server and daemons.
chown radio system /sys/android_power/state
chown radio system /sys/android_power/request_state
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index 7ad6f1c..1f852ff 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -7,6 +7,8 @@
"-Wno-unused-const-variable",
"-D_FILE_OFFSET_BITS=64",
"-DWITHOUT_NLS",
+ "-DWITHOUT_BZ2",
+ "-DWITHOUT_GZIP",
],
}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/file.c b/toolbox/upstream-netbsd/usr.bin/grep/file.c
index cf4a0fa..ef057ba 100644
--- a/toolbox/upstream-netbsd/usr.bin/grep/file.c
+++ b/toolbox/upstream-netbsd/usr.bin/grep/file.c
@@ -1,4 +1,4 @@
-/* $NetBSD: file.c,v 1.7 2011/04/18 22:46:48 joerg Exp $ */
+/* $NetBSD: file.c,v 1.10 2018/08/12 09:03:21 christos Exp $ */
/* $FreeBSD: head/usr.bin/grep/file.c 211496 2010-08-19 09:28:59Z des $ */
/* $OpenBSD: file.c,v 1.11 2010/07/02 20:48:48 nicm Exp $ */
@@ -35,15 +35,12 @@
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: file.c,v 1.7 2011/04/18 22:46:48 joerg Exp $");
+__RCSID("$NetBSD: file.c,v 1.10 2018/08/12 09:03:21 christos Exp $");
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
-#ifndef __ANDROID__
-#include <bzlib.h>
-#endif
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@@ -53,17 +50,16 @@
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>
-#ifndef __ANDROID__
-#include <zlib.h>
-#endif
#include "grep.h"
#define MAXBUFSIZ (32 * 1024)
#define LNBUFBUMP 80
-#ifndef __ANDROID__
+#ifndef WITHOUT_GZIP
static gzFile gzbufdesc;
+#endif
+#ifndef WITHOUT_BZ2
static BZFILE* bzbufdesc;
#endif
@@ -77,18 +73,21 @@
static inline int
grep_refill(struct file *f)
{
- ssize_t nr;
-#ifndef __ANDROID__
+ ssize_t nr = -1;
int bzerr;
-#endif
bufpos = buffer;
bufrem = 0;
-#ifndef __ANDROID__
- if (filebehave == FILE_GZIP)
+#ifndef WITHOUT_GZIP
+ if (filebehave == FILE_GZIP) {
nr = gzread(gzbufdesc, buffer, MAXBUFSIZ);
- else if (filebehave == FILE_BZIP && bzbufdesc != NULL) {
+ if (nr == -1)
+ return -1;
+ }
+#endif
+#ifndef WITHOUT_BZ2
+ if (filebehave == FILE_BZIP && bzbufdesc != NULL) {
nr = BZ2_bzRead(&bzerr, bzbufdesc, buffer, MAXBUFSIZ);
switch (bzerr) {
case BZ_OK:
@@ -114,9 +113,13 @@
/* Make sure we exit with an error */
nr = -1;
}
- } else
+ if (nr == -1)
+ return -1;
+ }
#endif
+ if (nr == -1) {
nr = read(f->fd, buffer, MAXBUFSIZ);
+ }
if (nr < 0)
return (-1);
@@ -204,11 +207,13 @@
grep_file_init(struct file *f)
{
-#ifndef __ANDROID__
+#ifndef WITHOUT_GZIP
if (filebehave == FILE_GZIP &&
(gzbufdesc = gzdopen(f->fd, "r")) == NULL)
goto error;
+#endif
+#ifndef WITHOUT_BZ2
if (filebehave == FILE_BZIP &&
(bzbufdesc = BZ2_bzdopen(f->fd, "r")) == NULL)
goto error;
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/grep.c b/toolbox/upstream-netbsd/usr.bin/grep/grep.c
index 1ea6ed3..bad2a73 100644
--- a/toolbox/upstream-netbsd/usr.bin/grep/grep.c
+++ b/toolbox/upstream-netbsd/usr.bin/grep/grep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: grep.c,v 1.12 2014/07/11 16:30:45 christos Exp $ */
+/* $NetBSD: grep.c,v 1.15 2018/08/12 09:03:21 christos Exp $ */
/* $FreeBSD: head/usr.bin/grep/grep.c 211519 2010-08-19 22:55:17Z delphij $ */
/* $OpenBSD: grep.c,v 1.42 2010/07/02 22:18:03 tedu Exp $ */
@@ -34,7 +34,7 @@
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: grep.c,v 1.12 2014/07/11 16:30:45 christos Exp $");
+__RCSID("$NetBSD: grep.c,v 1.15 2018/08/12 09:03:21 christos Exp $");
#include <sys/stat.h>
#include <sys/types.h>
@@ -170,7 +170,9 @@
struct option long_options[] =
{
{"binary-files", required_argument, NULL, BIN_OPT},
+#ifndef WITHOUT_GZIP
{"decompress", no_argument, NULL, DECOMPRESS_OPT},
+#endif
{"help", no_argument, NULL, HELP_OPT},
{"mmap", no_argument, NULL, MMAP_OPT},
{"line-buffered", no_argument, NULL, LINEBUF_OPT},
@@ -197,7 +199,9 @@
{"no-filename", no_argument, NULL, 'h'},
{"with-filename", no_argument, NULL, 'H'},
{"ignore-case", no_argument, NULL, 'i'},
+#ifndef WITHOUT_BZ2
{"bz2decompress", no_argument, NULL, 'J'},
+#endif
{"files-with-matches", no_argument, NULL, 'l'},
{"files-without-match", no_argument, NULL, 'L'},
{"max-count", required_argument, NULL, 'm'},
@@ -338,6 +342,7 @@
case 'g':
grepbehave = GREP_BASIC;
break;
+#ifndef WITHOUT_GZIP
case 'z':
filebehave = FILE_GZIP;
switch(__progname[1]) {
@@ -352,6 +357,7 @@
break;
}
break;
+#endif
}
lastc = '\0';
@@ -491,9 +497,11 @@
iflag = true;
cflags |= REG_ICASE;
break;
+#ifndef WITHOUT_BZ2
case 'J':
filebehave = FILE_BZIP;
break;
+#endif
case 'L':
lflag = false;
Lflag = true;
@@ -596,9 +604,11 @@
strcasecmp("no", optarg) != 0)
errx(2, getstr(3), "--color");
break;
+#ifndef WITHOUT_GZIP
case DECOMPRESS_OPT:
filebehave = FILE_GZIP;
break;
+#endif
case LABEL_OPT:
label = optarg;
break;
@@ -679,8 +689,13 @@
}
}
- if (lbflag)
+ if (lbflag) {
+#ifdef _IOLBF
+ setvbuf(stdout, NULL, _IOLBF, 0);
+#else
setlinebuf(stdout);
+#endif
+ }
if ((aargc == 0 || aargc == 1) && !Hflag)
hflag = true;
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/grep.h b/toolbox/upstream-netbsd/usr.bin/grep/grep.h
index fa2a3e3..b7ef7fa 100644
--- a/toolbox/upstream-netbsd/usr.bin/grep/grep.h
+++ b/toolbox/upstream-netbsd/usr.bin/grep/grep.h
@@ -1,4 +1,4 @@
-/* $NetBSD: grep.h,v 1.8 2012/05/06 22:27:00 joerg Exp $ */
+/* $NetBSD: grep.h,v 1.10 2018/08/12 09:03:21 christos Exp $ */
/* $OpenBSD: grep.h,v 1.15 2010/04/05 03:03:55 tedu Exp $ */
/* $FreeBSD: head/usr.bin/grep/grep.h 211496 2010-08-19 09:28:59Z des $ */
@@ -29,14 +29,14 @@
* SUCH DAMAGE.
*/
-#ifndef __ANDROID__
+#ifndef WITHOUT_BZ2
#include <bzlib.h>
#endif
#include <limits.h>
#include <regex.h>
#include <stdbool.h>
#include <stdio.h>
-#ifndef __ANDROID__
+#ifndef WITHOUT_GZIP
#include <zlib.h>
#endif
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/util.c b/toolbox/upstream-netbsd/usr.bin/grep/util.c
index ecd948d..a3c9e4c 100644
--- a/toolbox/upstream-netbsd/usr.bin/grep/util.c
+++ b/toolbox/upstream-netbsd/usr.bin/grep/util.c
@@ -1,4 +1,4 @@
-/* $NetBSD: util.c,v 1.17 2013/01/21 03:24:43 msaitoh Exp $ */
+/* $NetBSD: util.c,v 1.19 2018/02/05 22:14:26 mrg Exp $ */
/* $FreeBSD: head/usr.bin/grep/util.c 211496 2010-08-19 09:28:59Z des $ */
/* $OpenBSD: util.c,v 1.39 2010/07/02 22:18:03 tedu Exp $ */
@@ -34,7 +34,7 @@
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: util.c,v 1.17 2013/01/21 03:24:43 msaitoh Exp $");
+__RCSID("$NetBSD: util.c,v 1.19 2018/02/05 22:14:26 mrg Exp $");
#include <sys/stat.h>
#include <sys/types.h>
@@ -478,9 +478,10 @@
if (color)
fprintf(stdout, "\33[%sm\33[K", color);
- fwrite(line->dat + matches[i].rm_so,
- matches[i].rm_eo - matches[i].rm_so, 1,
- stdout);
+ fwrite(line->dat + matches[i].rm_so,
+ matches[i].rm_eo - matches[i].rm_so, 1,
+ stdout);
+
if (color)
fprintf(stdout, "\33[m\33[K");
a = matches[i].rm_eo;