Merge "Fix liblog#__security failure" into oc-dev
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 224444f..3b84853 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -58,28 +58,31 @@
}
bool debuggerd_trigger_dump(pid_t pid, unique_fd output_fd, DebuggerdDumpType dump_type,
- int timeout_ms) {
+ unsigned int timeout_ms) {
LOG(INFO) << "libdebuggerd_client: started dumping process " << pid;
unique_fd sockfd;
const auto end = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeout_ms);
- auto time_left = [timeout_ms, &end]() { return end - std::chrono::steady_clock::now(); };
+ auto time_left = [&end]() { return end - std::chrono::steady_clock::now(); };
auto set_timeout = [timeout_ms, &time_left](int sockfd) {
if (timeout_ms <= 0) {
- return -1;
+ return sockfd;
}
auto remaining = time_left();
if (remaining < decltype(remaining)::zero()) {
- LOG(ERROR) << "timeout expired";
+ LOG(ERROR) << "libdebuggerd_client: timeout expired";
return -1;
}
+
struct timeval timeout;
populate_timeval(&timeout, remaining);
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) != 0) {
+ PLOG(ERROR) << "libdebuggerd_client: failed to set receive timeout";
return -1;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) != 0) {
+ PLOG(ERROR) << "libdebuggerd_client: failed to set send timeout";
return -1;
}
@@ -158,8 +161,10 @@
// Forward output from the pipe to the output fd.
while (true) {
- auto remaining_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_left());
- if (remaining_ms <= 1ms) {
+ auto remaining_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_left()).count();
+ if (timeout_ms <= 0) {
+ remaining_ms = -1;
+ } else if (remaining_ms < 0) {
LOG(ERROR) << "libdebuggerd_client: timeout expired";
return false;
}
@@ -168,7 +173,7 @@
.fd = pipe_read.get(), .events = POLLIN, .revents = 0,
};
- rc = poll(&pfd, 1, remaining_ms.count());
+ rc = poll(&pfd, 1, remaining_ms);
if (rc == -1) {
if (errno == EINTR) {
continue;
diff --git a/debuggerd/client/debuggerd_client_test.cpp b/debuggerd/client/debuggerd_client_test.cpp
index 86d0314..aff03e5 100644
--- a/debuggerd/client/debuggerd_client_test.cpp
+++ b/debuggerd/client/debuggerd_client_test.cpp
@@ -89,3 +89,23 @@
EXPECT_EQ(1, found_end) << "\nOutput: \n" << result;
}
+
+TEST(debuggerd_client, no_timeout) {
+ unique_fd pipe_read, pipe_write;
+ ASSERT_TRUE(Pipe(&pipe_read, &pipe_write));
+
+ pid_t forkpid = fork();
+ ASSERT_NE(-1, forkpid);
+ if (forkpid == 0) {
+ pipe_write.reset();
+ char dummy;
+ TEMP_FAILURE_RETRY(read(pipe_read.get(), &dummy, sizeof(dummy)));
+ exit(0);
+ }
+
+ pipe_read.reset();
+
+ unique_fd output_read, output_write;
+ ASSERT_TRUE(Pipe(&output_read, &output_write));
+ ASSERT_TRUE(debuggerd_trigger_dump(forkpid, std::move(output_write), kDebuggerdBacktrace, 0));
+}
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index fa2838e..b705e27 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -500,9 +500,6 @@
TEST(crash_dump, zombie) {
pid_t forkpid = fork();
- int pipefd[2];
- ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
-
pid_t rc;
int status;
diff --git a/debuggerd/include/debuggerd/client.h b/debuggerd/include/debuggerd/client.h
index 91f143b..01de57b 100644
--- a/debuggerd/include/debuggerd/client.h
+++ b/debuggerd/include/debuggerd/client.h
@@ -28,9 +28,9 @@
};
// Trigger a dump of specified process to output_fd.
-// output_fd is *not* consumed, timeouts <= 0 will wait forever.
+// output_fd is consumed, timeout of 0 will wait forever.
bool debuggerd_trigger_dump(pid_t pid, android::base::unique_fd output_fd,
- enum DebuggerdDumpType dump_type, int timeout_ms);
+ enum DebuggerdDumpType dump_type, unsigned int timeout_ms);
int dump_backtrace_to_file(pid_t tid, int fd);
int dump_backtrace_to_file_timeout(pid_t tid, int fd, int timeout_secs);
diff --git a/libgrallocusage/GrallocUsageConversion.cpp b/libgrallocusage/GrallocUsageConversion.cpp
index 10e728d..8164beb 100644
--- a/libgrallocusage/GrallocUsageConversion.cpp
+++ b/libgrallocusage/GrallocUsageConversion.cpp
@@ -30,17 +30,13 @@
/* ProducerUsage::CPU_WRITE_OFTEN | */
ProducerUsage::GPU_RENDER_TARGET | ProducerUsage::PROTECTED |
ProducerUsage::CAMERA | ProducerUsage::VIDEO_DECODER |
- ProducerUsage::SENSOR_DIRECT_DATA |
- /* Private flags may be consumer or producer */
- GRALLOC_USAGE_PRIVATE_MASK;
+ ProducerUsage::SENSOR_DIRECT_DATA;
constexpr uint64_t CONSUMER_MASK = ConsumerUsage::CPU_READ |
/* ConsumerUsage::CPU_READ_OFTEN | */
ConsumerUsage::GPU_TEXTURE | ConsumerUsage::HWCOMPOSER |
ConsumerUsage::CLIENT_TARGET | ConsumerUsage::CURSOR |
ConsumerUsage::VIDEO_ENCODER | ConsumerUsage::CAMERA |
- ConsumerUsage::RENDERSCRIPT | ConsumerUsage::GPU_DATA_BUFFER |
- /* Private flags may be consumer or producer */
- GRALLOC_USAGE_PRIVATE_MASK;
+ ConsumerUsage::RENDERSCRIPT | ConsumerUsage::GPU_DATA_BUFFER;
*producerUsage = static_cast<uint64_t>(usage) & PRODUCER_MASK;
*consumerUsage = static_cast<uint64_t>(usage) & CONSUMER_MASK;
if ((static_cast<uint32_t>(usage) & GRALLOC_USAGE_SW_READ_OFTEN) == GRALLOC_USAGE_SW_READ_OFTEN) {
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index bdbe725..8ef9328 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -1093,8 +1093,10 @@
it = mLogElements.begin();
} else {
LogBufferElementCollection::iterator last;
- // 30 second limit to continue search for out-of-order entries.
- log_time min = start - log_time(30, 0);
+ // 3 second limit to continue search for out-of-order entries.
+ log_time min = start - log_time(3, 0);
+ // Cap to 300 iterations we look back for out-of-order entries.
+ size_t count = 300;
// Client wants to start from some specified time. Chances are
// we are better off starting from the end of the time sorted list.
for (last = it = mLogElements.end(); it != mLogElements.begin();
@@ -1103,7 +1105,7 @@
LogBufferElement* element = *it;
if (element->getRealTime() > start) {
last = it;
- } else if (element->getRealTime() < min) {
+ } else if (!--count || (element->getRealTime() < min)) {
break;
}
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 28406c8..f064fed 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -301,6 +301,9 @@
start logd
start hwservicemanager
+ # HALs required before data is mounted
+ class_start early_hal
+
# once everything is setup, no need to modify /
mount rootfs rootfs / ro remount
# Mount shared so changes propagate into child namespaces
diff --git a/storaged/include/storaged.h b/storaged/include/storaged.h
index b6a0850..514798b 100644
--- a/storaged/include/storaged.h
+++ b/storaged/include/storaged.h
@@ -27,6 +27,7 @@
#include <vector>
#include <batteryservice/IBatteryPropertiesListener.h>
+#include <batteryservice/IBatteryPropertiesRegistrar.h>
#include "storaged_info.h"
#include "storaged_uid_monitor.h"
@@ -245,7 +246,8 @@
int event_time_check_usec; // check how much cputime spent in event loop
};
-class storaged_t : public BnBatteryPropertiesListener {
+class storaged_t : public BnBatteryPropertiesListener,
+ public IBinder::DeathRecipient {
private:
time_t mTimer;
storaged_config mConfig;
@@ -253,6 +255,7 @@
disk_stats_monitor mDsm;
uid_monitor mUidm;
time_t mStarttime;
+ sp<IBatteryPropertiesRegistrar> battery_properties;
public:
storaged_t(void);
~storaged_t() {}
@@ -281,6 +284,7 @@
void init_battery_service();
virtual void batteryPropertiesChanged(struct BatteryProperties props);
+ void binderDied(const wp<IBinder>& who);
};
// Eventlog tag
diff --git a/storaged/main.cpp b/storaged/main.cpp
index 2f2273d..4d1e430 100644
--- a/storaged/main.cpp
+++ b/storaged/main.cpp
@@ -42,11 +42,11 @@
#include <storaged_service.h>
#include <storaged_utils.h>
-storaged_t storaged;
+sp<storaged_t> storaged;
// Function of storaged's main thread
-void* storaged_main(void* s) {
- storaged_t* storaged = (storaged_t*)s;
+void* storaged_main(void* /* unused */) {
+ storaged = new storaged_t();
storaged->init_battery_service();
@@ -116,7 +116,7 @@
report_storage_health();
// Start the main thread of storaged
pthread_t storaged_main_thread;
- errno = pthread_create(&storaged_main_thread, NULL, storaged_main, &storaged);
+ errno = pthread_create(&storaged_main_thread, NULL, storaged_main, NULL);
if (errno != 0) {
PLOG_TO(SYSTEM, ERROR) << "Failed to create main thread";
return -1;
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 1770922..54d429c 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -23,6 +23,7 @@
#include <android-base/logging.h>
#include <batteryservice/BatteryServiceConstants.h>
#include <batteryservice/IBatteryPropertiesRegistrar.h>
+#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <log/log.h>
@@ -173,7 +174,7 @@
if (!mConfig.proc_uid_io_available)
return;
- sp<IBatteryPropertiesRegistrar> battery_properties = get_battery_properties_service();
+ battery_properties = get_battery_properties_service();
if (battery_properties == NULL) {
LOG_TO(SYSTEM, WARNING) << "failed to find batteryproperties service";
return;
@@ -185,6 +186,18 @@
// register listener after init uid_monitor
battery_properties->registerListener(this);
+ IInterface::asBinder(battery_properties)->linkToDeath(this);
+}
+
+void storaged_t::binderDied(const wp<IBinder>& who) {
+ if (battery_properties != NULL &&
+ IInterface::asBinder(battery_properties) == who) {
+ LOG_TO(SYSTEM, ERROR) << "batteryproperties service died, exiting";
+ IPCThreadState::self()->stopProcess();
+ exit(1);
+ } else {
+ LOG_TO(SYSTEM, ERROR) << "unknown service died";
+ }
}
/* storaged_t */
diff --git a/storaged/storaged_service.cpp b/storaged/storaged_service.cpp
index 33e85e3..b1d3bfd 100644
--- a/storaged/storaged_service.cpp
+++ b/storaged/storaged_service.cpp
@@ -33,7 +33,7 @@
using namespace android::base;
-extern storaged_t storaged;
+extern sp<storaged_t> storaged;
std::vector<struct uid_info> BpStoraged::dump_uids(const char* /*option*/) {
Parcel data, reply;
@@ -74,7 +74,7 @@
std::vector<struct uid_info> Storaged::dump_uids(const char* /* option */) {
std::vector<struct uid_info> uids_v;
- std::unordered_map<uint32_t, struct uid_info> uids_m = storaged.get_uids();
+ std::unordered_map<uint32_t, struct uid_info> uids_m = storaged->get_uids();
for (const auto& it : uids_m) {
uids_v.push_back(it.second);
@@ -127,7 +127,7 @@
uint64_t last_ts = 0;
const std::map<uint64_t, struct uid_records>& records =
- storaged.get_uid_records(hours, threshold, force_report);
+ storaged->get_uid_records(hours, threshold, force_report);
for (const auto& it : records) {
if (last_ts != it.second.start_ts) {
dprintf(fd, "%llu", (unsigned long long)it.second.start_ts);
@@ -150,7 +150,7 @@
}
if (time_window) {
- storaged.update_uid_io_interval(time_window);
+ storaged->update_uid_io_interval(time_window);
}
return NO_ERROR;
diff --git a/tzdatacheck/tzdatacheck.cpp b/tzdatacheck/tzdatacheck.cpp
index 381df5a..8fcd17f 100644
--- a/tzdatacheck/tzdatacheck.cpp
+++ b/tzdatacheck/tzdatacheck.cpp
@@ -30,6 +30,19 @@
#include "android-base/logging.h"
+// The name of the directory that holds a staged time zone update distro. If this exists it should
+// replace the one in CURRENT_DIR_NAME.
+// See also libcore.tzdata.update2.TimeZoneDistroInstaller.
+static const char* STAGED_DIR_NAME = "/staged";
+
+// The name of the directory that holds the (optional) installed time zone update distro.
+// See also libcore.tzdata.update2.TimeZoneDistroInstaller.
+static const char* CURRENT_DIR_NAME = "/current";
+
+// The name of a file in the staged dir that indicates the staged operation is an "uninstall".
+// See also libcore.tzdata.update2.TimeZoneDistroInstaller.
+static const char* UNINSTALL_TOMBSTONE_FILE_NAME = "/STAGED_UNINSTALL_TOMBSTONE";
+
// The name of the file containing the distro version information.
// See also libcore.tzdata.shared2.TimeZoneDistro / libcore.tzdata.shared2.DistroVersion.
static const char* DISTRO_VERSION_FILENAME = "/distro_version";
@@ -75,7 +88,6 @@
static const char TZ_DATA_HEADER_PREFIX[] = "tzdata";
static const size_t TZ_DATA_HEADER_PREFIX_LEN = sizeof(TZ_DATA_HEADER_PREFIX) - 1; // exclude \0
-
static void usage() {
std::cerr << "Usage: tzdatacheck SYSTEM_TZ_DIR DATA_TZ_DIR\n"
"\n"
@@ -184,7 +196,7 @@
return 0;
}
-enum PathStatus { ERR, NONE, IS_DIR, NOT_DIR };
+enum PathStatus { ERR, NONE, IS_DIR, IS_REG, UNKNOWN };
static PathStatus checkPath(const std::string& path) {
struct stat buf;
@@ -195,7 +207,31 @@
}
return NONE;
}
- return S_ISDIR(buf.st_mode) ? IS_DIR : NOT_DIR;
+ return S_ISDIR(buf.st_mode) ? IS_DIR : S_ISREG(buf.st_mode) ? IS_REG : UNKNOWN;
+}
+
+/*
+ * Deletes fileToDelete and returns true if it is successful. If fileToDelete is not a file or
+ * cannot be accessed this method returns false.
+ */
+static bool deleteFile(const std::string& fileToDelete) {
+ // Check whether the file exists.
+ PathStatus pathStatus = checkPath(fileToDelete);
+ if (pathStatus == NONE) {
+ LOG(INFO) << "Path " << fileToDelete << " does not exist";
+ return true;
+ }
+ if (pathStatus != IS_REG) {
+ LOG(WARNING) << "Path " << fileToDelete << " failed to stat() or is not a file.";
+ return false;
+ }
+
+ // Attempt the deletion.
+ int rc = unlink(fileToDelete.c_str());
+ if (rc != 0) {
+ PLOG(WARNING) << "unlink() failed for " << fileToDelete;
+ }
+ return rc == 0;
}
/*
@@ -260,8 +296,7 @@
std::string dataUpdatesDirName(dataZoneInfoDir);
dataUpdatesDirName += "/updates";
LOG(INFO) << "Removing: " << dataUpdatesDirName;
- bool deleted = deleteDir(dataUpdatesDirName);
- if (!deleted) {
+ if (!deleteDir(dataUpdatesDirName)) {
LOG(WARNING) << "Deletion of install metadata " << dataUpdatesDirName
<< " was not successful";
}
@@ -270,14 +305,151 @@
/*
* Deletes the timezone update distro directory.
*/
-static void deleteUpdateDistroDir(std::string& distroDirName) {
+static void deleteUpdateDistroDir(const std::string& distroDirName) {
LOG(INFO) << "Removing: " << distroDirName;
- bool deleted = deleteDir(distroDirName);
- if (!deleted) {
+ if (!deleteDir(distroDirName)) {
LOG(WARNING) << "Deletion of distro dir " << distroDirName << " was not successful";
}
}
+static void handleStagedUninstall(const std::string& dataStagedDirName,
+ const std::string& dataCurrentDirName,
+ const PathStatus dataCurrentDirStatus) {
+ LOG(INFO) << "Staged operation is an uninstall.";
+
+ // Delete the current install directory.
+ switch (dataCurrentDirStatus) {
+ case NONE:
+ // This is unexpected: No uninstall should be staged if there is nothing to
+ // uninstall. Carry on anyway.
+ LOG(WARNING) << "No current install to delete.";
+ break;
+ case IS_DIR:
+ // This is normal. Delete the current install dir.
+ if (!deleteDir(dataCurrentDirName)) {
+ LOG(WARNING) << "Deletion of current distro " << dataCurrentDirName
+ << " was not successful";
+ // If this happens we don't know whether we were able to delete or not. We don't
+ // delete the staged operation so it will be retried next boot unless overridden.
+ return;
+ }
+ break;
+ case IS_REG:
+ default:
+ // This is unexpected: We can try to delete the unexpected file and carry on.
+ LOG(WARNING) << "Current distro dir " << dataCurrentDirName
+ << " is not actually a directory. Attempting deletion.";
+ if (!deleteFile(dataCurrentDirName)) {
+ LOG(WARNING) << "Could not delete " << dataCurrentDirName;
+ return;
+ }
+ break;
+ }
+
+ // Delete the staged uninstall dir.
+ if (!deleteDir(dataStagedDirName)) {
+ LOG(WARNING) << "Deletion of current distro " << dataCurrentDirName
+ << " was not successful";
+ // If this happens we don't know whether we were able to delete the staged operation
+ // or not.
+ return;
+ }
+ LOG(INFO) << "Staged uninstall complete.";
+}
+
+static void handleStagedInstall(const std::string& dataStagedDirName,
+ const std::string& dataCurrentDirName,
+ const PathStatus dataCurrentDirStatus) {
+ LOG(INFO) << "Staged operation is an install.";
+
+ switch (dataCurrentDirStatus) {
+ case NONE:
+ // This is expected: This is the first install.
+ LOG(INFO) << "No current install to replace.";
+ break;
+ case IS_DIR:
+ // This is expected: We are replacing an existing install.
+ // Delete the current dir so we can replace it.
+ if (!deleteDir(dataCurrentDirName)) {
+ LOG(WARNING) << "Deletion of current distro " << dataCurrentDirName
+ << " was not successful";
+ // If this happens, we cannot proceed.
+ return;
+ }
+ break;
+ case IS_REG:
+ default:
+ // This is unexpected: We can try to delete the unexpected file and carry on.
+ LOG(WARNING) << "Current distro dir " << dataCurrentDirName
+ << " is not actually a directory. Attempting deletion.";
+ if (!deleteFile(dataCurrentDirName)) {
+ LOG(WARNING) << "Could not delete " << dataCurrentDirName;
+ return;
+ }
+ break;
+ }
+
+ // Move the staged dir so it is the new current dir, completing the install.
+ LOG(INFO) << "Moving " << dataStagedDirName << " to " << dataCurrentDirName;
+ int rc = rename(dataStagedDirName.c_str(), dataCurrentDirName.c_str());
+ if (rc == -1) {
+ PLOG(WARNING) << "Unable to rename directory from " << dataStagedDirName << " to "
+ << &dataCurrentDirName[0];
+ return;
+ }
+
+ LOG(INFO) << "Staged install complete.";
+}
+/*
+ * Process a staged operation if there is one.
+ */
+static void processStagedOperation(const std::string& dataStagedDirName,
+ const std::string& dataCurrentDirName) {
+ PathStatus dataStagedDirStatus = checkPath(dataStagedDirName);
+
+ // Exit early for the common case.
+ if (dataStagedDirStatus == NONE) {
+ LOG(DEBUG) << "No staged time zone operation.";
+ return;
+ }
+
+ // Check known directory names are in a good starting state.
+ if (dataStagedDirStatus != IS_DIR) {
+ LOG(WARNING) << "Staged distro dir " << dataStagedDirName
+ << " could not be accessed or is not a directory."
+ << " stagedDirStatus=" << dataStagedDirStatus;
+ return;
+ }
+
+ // dataStagedDirStatus == IS_DIR.
+
+ // Work out whether there is anything currently installed.
+ PathStatus dataCurrentDirStatus = checkPath(dataCurrentDirName);
+ if (dataCurrentDirStatus == ERR) {
+ LOG(WARNING) << "Current install dir " << dataCurrentDirName << " could not be accessed"
+ << " dataCurrentDirStatus=" << dataCurrentDirStatus;
+ return;
+ }
+
+ // We must perform the staged operation.
+
+ // Check to see if the staged directory contains an uninstall or an install operation.
+ std::string uninstallTombStoneFile(dataStagedDirName);
+ uninstallTombStoneFile += UNINSTALL_TOMBSTONE_FILE_NAME;
+ int uninstallTombStoneFileStatus = checkPath(uninstallTombStoneFile);
+ if (uninstallTombStoneFileStatus != IS_REG && uninstallTombStoneFileStatus != NONE) {
+ // Error case.
+ LOG(WARNING) << "Unable to determine if the staged operation is an uninstall.";
+ return;
+ }
+ if (uninstallTombStoneFileStatus == IS_REG) {
+ handleStagedUninstall(dataStagedDirName, dataCurrentDirName, dataCurrentDirStatus);
+ } else {
+ // uninstallTombStoneFileStatus == NONE meaning this is a staged install.
+ handleStagedInstall(dataStagedDirName, dataCurrentDirName, dataCurrentDirStatus);
+ }
+}
+
/*
* After a platform update it is likely that timezone data found on the system partition will be
* newer than the version found in the data partition. This tool detects this case and removes the
@@ -300,15 +472,25 @@
const char* systemZoneInfoDir = argv[1];
const char* dataZoneInfoDir = argv[2];
- // Check the distro directory exists. If it does not, exit quickly: nothing to do.
+ std::string dataStagedDirName(dataZoneInfoDir);
+ dataStagedDirName += STAGED_DIR_NAME;
+
std::string dataCurrentDirName(dataZoneInfoDir);
- dataCurrentDirName += "/current";
- int dataCurrentDirStatus = checkPath(dataCurrentDirName);
+ dataCurrentDirName += CURRENT_DIR_NAME;
+
+ // Check for an process any staged operation.
+ // If the staged operation could not be handled we still have to validate the current installed
+ // directory so we do not check for errors and do not quit early.
+ processStagedOperation(dataStagedDirName, dataCurrentDirName);
+
+ // Check the distro directory exists. If it does not, exit quickly: nothing to do.
+ PathStatus dataCurrentDirStatus = checkPath(dataCurrentDirName);
if (dataCurrentDirStatus == NONE) {
LOG(INFO) << "timezone distro dir " << dataCurrentDirName
<< " does not exist. No action required.";
return 0;
}
+
// If the distro directory path is not a directory or we can't stat() the path, exit with a
// warning: either there's a problem accessing storage or the world is not as it should be;
// nothing to do.