Merge "Change call to mmap64."
diff --git a/adb/client/transport_mdns.cpp b/adb/client/transport_mdns.cpp
index 2b6aa7c..c9993b7 100644
--- a/adb/client/transport_mdns.cpp
+++ b/adb/client/transport_mdns.cpp
@@ -144,7 +144,7 @@
return initialized_;
}
- virtual ~AsyncServiceRef() {
+ void DestroyServiceRef() {
if (!initialized_) {
return;
}
@@ -152,9 +152,13 @@
// Order matters here! Must destroy the fdevent first since it has a
// reference to |sdRef_|.
fdevent_destroy(fde_);
+ D("DNSServiceRefDeallocate(sdRef=%p)", sdRef_);
DNSServiceRefDeallocate(sdRef_);
+ initialized_ = false;
}
+ virtual ~AsyncServiceRef() { DestroyServiceRef(); }
+
protected:
DNSServiceRef sdRef_;
@@ -203,6 +207,7 @@
if (ret != kDNSServiceErr_NoError) {
D("Got %d from DNSServiceGetAddrInfo.", ret);
} else {
+ D("DNSServiceGetAddrInfo(sdRef=%p, hosttarget=%s)", sdRef_, hosttarget);
Initialize();
}
@@ -223,7 +228,7 @@
return true;
}
- void Connect(const sockaddr* address) {
+ bool AddToServiceRegistry(const sockaddr* address) {
sa_family_ = address->sa_family;
if (sa_family_ == AF_INET) {
@@ -234,13 +239,13 @@
addr_format_ = "[%s]:%hu";
} else { // Should be impossible
D("mDNS resolved non-IP address.");
- return;
+ return false;
}
// Winsock version requires the const cast Because Microsoft.
if (!inet_ntop(sa_family_, const_cast<void*>(ip_addr_data_), ip_addr_, sizeof(ip_addr_))) {
D("Could not convert IP address to string.");
- return;
+ return false;
}
// adb secure service needs to do something different from just
@@ -264,19 +269,32 @@
}
int adbSecureServiceType = serviceIndex();
+ ServiceRegistry* services = nullptr;
switch (adbSecureServiceType) {
case kADBTransportServiceRefIndex:
- sAdbTransportServices->push_back(this);
+ services = sAdbTransportServices;
break;
case kADBSecurePairingServiceRefIndex:
- sAdbSecurePairingServices->push_back(this);
+ services = sAdbSecurePairingServices;
break;
case kADBSecureConnectServiceRefIndex:
- sAdbSecureConnectServices->push_back(this);
+ services = sAdbSecureConnectServices;
break;
default:
- break;
+ LOG(WARNING) << "No registry available for reg_type=[" << regType_ << "]";
+ return false;
}
+
+ if (!services->empty()) {
+ // Remove the previous resolved service, if any.
+ services->erase(std::remove_if(services->begin(), services->end(),
+ [&](std::unique_ptr<ResolvedService>& service) {
+ return (serviceName_ == service->serviceName());
+ }));
+ }
+ services->push_back(std::unique_ptr<ResolvedService>(this));
+
+ return true;
}
int serviceIndex() const { return adb_DNSServiceIndexByName(regType_.c_str()); }
@@ -291,7 +309,7 @@
uint16_t port() const { return port_; }
- using ServiceRegistry = std::vector<ResolvedService*>;
+ using ServiceRegistry = std::vector<std::unique_ptr<ResolvedService>>;
// unencrypted tcp connections
static ServiceRegistry* sAdbTransportServices;
@@ -321,13 +339,13 @@
};
// static
-std::vector<ResolvedService*>* ResolvedService::sAdbTransportServices = NULL;
+ResolvedService::ServiceRegistry* ResolvedService::sAdbTransportServices = NULL;
// static
-std::vector<ResolvedService*>* ResolvedService::sAdbSecurePairingServices = NULL;
+ResolvedService::ServiceRegistry* ResolvedService::sAdbSecurePairingServices = NULL;
// static
-std::vector<ResolvedService*>* ResolvedService::sAdbSecureConnectServices = NULL;
+ResolvedService::ServiceRegistry* ResolvedService::sAdbSecureConnectServices = NULL;
// static
void ResolvedService::initAdbServiceRegistries() {
@@ -348,7 +366,7 @@
adb_secure_foreach_service_callback cb) {
initAdbServiceRegistries();
- for (auto service : services) {
+ for (const auto& service : services) {
auto service_name = service->serviceName();
auto reg_type = service->regType();
auto ip = service->ipAddress();
@@ -366,7 +384,7 @@
bool ResolvedService::connectByServiceName(const ServiceRegistry& services,
const std::string& service_name) {
initAdbServiceRegistries();
- for (auto service : services) {
+ for (const auto& service : services) {
if (service_name == service->serviceName()) {
D("Got service_name match [%s]", service->serviceName().c_str());
return service->ConnectSecureWifiDevice();
@@ -393,23 +411,28 @@
service_name);
}
-static void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/,
- DNSServiceFlags /*flags*/,
+static void DNSSD_API register_service_ip(DNSServiceRef sdRef, DNSServiceFlags flags,
uint32_t /*interfaceIndex*/,
- DNSServiceErrorType /*errorCode*/,
- const char* /*hostname*/,
- const sockaddr* address,
- uint32_t /*ttl*/,
- void* context) {
- D("Got IP for service.");
+ DNSServiceErrorType errorCode, const char* hostname,
+ const sockaddr* address, uint32_t ttl, void* context) {
+ D("%s: sdRef=%p flags=0x%08x errorCode=%u ttl=%u", __func__, sdRef, flags, errorCode, ttl);
std::unique_ptr<ResolvedService> data(
reinterpret_cast<ResolvedService*>(context));
- data->Connect(address);
+ // Only resolve the address once. If the address or port changes, we'll just get another
+ // registration.
+ data->DestroyServiceRef();
- // For ADB Secure services, keep those ResolvedService's around
- // for later processing with secure connection establishment.
- if (data->serviceIndex() != kADBTransportServiceRefIndex) {
- data.release();
+ if (errorCode != kDNSServiceErr_NoError) {
+ D("Got error while looking up ipaddr [%u]", errorCode);
+ return;
+ }
+
+ if (flags & kDNSServiceFlagsAdd) {
+ D("Resolved IP address for [%s]. Adding to service registry.", hostname);
+ auto* ptr = data.release();
+ if (!ptr->AddToServiceRegistry(address)) {
+ data.reset(ptr);
+ }
}
}
@@ -459,6 +482,7 @@
};
static void adb_RemoveDNSService(const char* regType, const char* serviceName) {
+ D("%s: regType=[%s] serviceName=[%s]", __func__, regType, serviceName);
int index = adb_DNSServiceIndexByName(regType);
ResolvedService::ServiceRegistry* services;
switch (index) {
@@ -475,10 +499,15 @@
return;
}
+ if (services->empty()) {
+ return;
+ }
+
std::string sName(serviceName);
- services->erase(std::remove_if(
- services->begin(), services->end(),
- [&sName](ResolvedService* service) { return (sName == service->serviceName()); }));
+ services->erase(std::remove_if(services->begin(), services->end(),
+ [&sName](std::unique_ptr<ResolvedService>& service) {
+ return (sName == service->serviceName());
+ }));
}
// Returns the version the device wanted to advertise,
diff --git a/adb/test_adb.py b/adb/test_adb.py
index 03bdcbd..9912f11 100755
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -659,14 +659,14 @@
print(f"Registering {serv_instance}.{serv_type} ...")
with zeroconf_register_service(zc, service_info) as info:
"""Give adb some time to register the service"""
- time.sleep(0.25)
+ time.sleep(1)
print(f"services={_mdns_services(server_port)}")
self.assertTrue(any((serv_instance in line and serv_type in line)
for line in _mdns_services(server_port)))
"""Give adb some time to unregister the service"""
print("Unregistering mdns service...")
- time.sleep(0.25)
+ time.sleep(1)
print(f"services={_mdns_services(server_port)}")
self.assertFalse(any((serv_instance in line and serv_type in line)
for line in _mdns_services(server_port)))
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index d67b522..31c2d5d 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -169,6 +169,7 @@
"libdebuggerd/backtrace.cpp",
"libdebuggerd/gwp_asan.cpp",
"libdebuggerd/open_files_list.cpp",
+ "libdebuggerd/scudo.cpp",
"libdebuggerd/tombstone.cpp",
"libdebuggerd/utility.cpp",
],
@@ -176,8 +177,13 @@
local_include_dirs: ["libdebuggerd/include"],
export_include_dirs: ["libdebuggerd/include"],
- // Needed for private/bionic_fdsan.h
- include_dirs: ["bionic/libc"],
+ include_dirs: [
+ // Needed for private/bionic_fdsan.h
+ "bionic/libc",
+
+ // Needed for scudo/interface.h
+ "external/scudo/standalone/include",
+ ],
header_libs: [
"bionic_libc_platform_headers",
"gwp_asan_headers",
@@ -192,7 +198,10 @@
"liblog",
],
- whole_static_libs: ["gwp_asan_crash_handler"],
+ whole_static_libs: [
+ "gwp_asan_crash_handler",
+ "libscudo",
+ ],
target: {
recovery: {
@@ -206,6 +215,9 @@
debuggable: {
cflags: ["-DROOT_POSSIBLE"],
},
+ experimental_mte: {
+ cflags: ["-DANDROID_EXPERIMENTAL_MTE"],
+ },
},
}
@@ -256,6 +268,10 @@
"gwp_asan_headers",
],
+ include_dirs: [
+ "external/scudo/standalone/include",
+ ],
+
local_include_dirs: [
"libdebuggerd",
],
@@ -271,6 +287,12 @@
},
test_suites: ["device-tests"],
+
+ product_variables: {
+ experimental_mte: {
+ cflags: ["-DANDROID_EXPERIMENTAL_MTE"],
+ },
+ },
}
cc_benchmark {
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 0cd2350..d7cb972 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -289,6 +289,8 @@
process_info->fdsan_table_address = crash_info->data.d.fdsan_table_address;
process_info->gwp_asan_state = crash_info->data.d.gwp_asan_state;
process_info->gwp_asan_metadata = crash_info->data.d.gwp_asan_metadata;
+ process_info->scudo_stack_depot = crash_info->data.d.scudo_stack_depot;
+ process_info->scudo_region_info = crash_info->data.d.scudo_region_info;
FALLTHROUGH_INTENDED;
case 1:
case 2:
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 054f836..25417a9 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -31,6 +31,9 @@
#include <android/fdsan.h>
#include <android/set_abort_message.h>
+#include <bionic/malloc.h>
+#include <bionic/mte.h>
+#include <bionic/mte_kernel.h>
#include <bionic/reserved_signals.h>
#include <android-base/cmsg.h>
@@ -331,6 +334,173 @@
R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr (0x100000000000dead|0xdead))");
}
+#if defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE)
+static void SetTagCheckingLevelSync() {
+ int tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
+ if (tagged_addr_ctrl < 0) {
+ abort();
+ }
+
+ tagged_addr_ctrl = (tagged_addr_ctrl & ~PR_MTE_TCF_MASK) | PR_MTE_TCF_SYNC;
+ if (prctl(PR_SET_TAGGED_ADDR_CTRL, tagged_addr_ctrl, 0, 0, 0) != 0) {
+ abort();
+ }
+
+ HeapTaggingLevel heap_tagging_level = M_HEAP_TAGGING_LEVEL_SYNC;
+ if (!android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &heap_tagging_level, sizeof(heap_tagging_level))) {
+ abort();
+ }
+}
+#endif
+
+TEST_F(CrasherTest, mte_uaf) {
+#if defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE)
+ if (!mte_supported()) {
+ GTEST_SKIP() << "Requires MTE";
+ }
+
+ int intercept_result;
+ unique_fd output_fd;
+ StartProcess([]() {
+ SetTagCheckingLevelSync();
+ volatile int* p = (volatile int*)malloc(16);
+ free((void *)p);
+ p[0] = 42;
+ });
+
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ AssertDeath(SIGSEGV);
+ FinishIntercept(&intercept_result);
+
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::string result;
+ ConsumeFd(std::move(output_fd), &result);
+
+ ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 9 \(SEGV_MTESERR\))");
+ ASSERT_MATCH(result, R"(Cause: \[MTE\]: Use After Free, 0 bytes into a 16-byte allocation)");
+#else
+ GTEST_SKIP() << "Requires aarch64 + ANDROID_EXPERIMENTAL_MTE";
+#endif
+}
+
+TEST_F(CrasherTest, mte_overflow) {
+#if defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE)
+ if (!mte_supported()) {
+ GTEST_SKIP() << "Requires MTE";
+ }
+
+ int intercept_result;
+ unique_fd output_fd;
+ StartProcess([]() {
+ SetTagCheckingLevelSync();
+ volatile int* p = (volatile int*)malloc(16);
+ p[4] = 42;
+ });
+
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ AssertDeath(SIGSEGV);
+ FinishIntercept(&intercept_result);
+
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::string result;
+ ConsumeFd(std::move(output_fd), &result);
+
+ ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
+ ASSERT_MATCH(result, R"(Cause: \[MTE\]: Buffer Overflow, 0 bytes right of a 16-byte allocation)");
+#else
+ GTEST_SKIP() << "Requires aarch64 + ANDROID_EXPERIMENTAL_MTE";
+#endif
+}
+
+TEST_F(CrasherTest, mte_underflow) {
+#if defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE)
+ if (!mte_supported()) {
+ GTEST_SKIP() << "Requires MTE";
+ }
+
+ int intercept_result;
+ unique_fd output_fd;
+ StartProcess([]() {
+ SetTagCheckingLevelSync();
+ volatile int* p = (volatile int*)malloc(16);
+ p[-1] = 42;
+ });
+
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ AssertDeath(SIGSEGV);
+ FinishIntercept(&intercept_result);
+
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::string result;
+ ConsumeFd(std::move(output_fd), &result);
+
+ ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 9 \(SEGV_MTESERR\))");
+ ASSERT_MATCH(result, R"(Cause: \[MTE\]: Buffer Underflow, 4 bytes left of a 16-byte allocation)");
+#else
+ GTEST_SKIP() << "Requires aarch64 + ANDROID_EXPERIMENTAL_MTE";
+#endif
+}
+
+TEST_F(CrasherTest, mte_multiple_causes) {
+#if defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE)
+ if (!mte_supported()) {
+ GTEST_SKIP() << "Requires MTE";
+ }
+
+ int intercept_result;
+ unique_fd output_fd;
+ StartProcess([]() {
+ SetTagCheckingLevelSync();
+
+ // Make two allocations with the same tag and close to one another. Check for both properties
+ // with a bounds check -- this relies on the fact that only if the allocations have the same tag
+ // would they be measured as closer than 128 bytes to each other. Otherwise they would be about
+ // (some non-zero value << 56) apart.
+ //
+ // The out-of-bounds access will be considered either an overflow of one or an underflow of the
+ // other.
+ std::set<uintptr_t> allocs;
+ for (int i = 0; i != 4096; ++i) {
+ uintptr_t alloc = reinterpret_cast<uintptr_t>(malloc(16));
+ auto it = allocs.insert(alloc).first;
+ if (it != allocs.begin() && *std::prev(it) + 128 > alloc) {
+ *reinterpret_cast<int*>(*std::prev(it) + 16) = 42;
+ }
+ if (std::next(it) != allocs.end() && alloc + 128 > *std::next(it)) {
+ *reinterpret_cast<int*>(alloc + 16) = 42;
+ }
+ }
+ });
+
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ AssertDeath(SIGSEGV);
+ FinishIntercept(&intercept_result);
+
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::string result;
+ ConsumeFd(std::move(output_fd), &result);
+
+ ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
+ ASSERT_MATCH(
+ result,
+ R"(Note: multiple potential causes for this crash were detected, listing them in decreasing order of probability.)");
+
+ // Adjacent untracked allocations may cause us to see the wrong underflow here (or only
+ // overflows), so we can't match explicitly for an underflow message.
+ ASSERT_MATCH(result, R"(Cause: \[MTE\]: Buffer Overflow, 0 bytes right of a 16-byte allocation)");
+#else
+ GTEST_SKIP() << "Requires aarch64 + ANDROID_EXPERIMENTAL_MTE";
+#endif
+}
+
TEST_F(CrasherTest, LD_PRELOAD) {
int intercept_result;
unique_fd output_fd;
diff --git a/debuggerd/include/debuggerd/handler.h b/debuggerd/include/debuggerd/handler.h
index 6650294..254ed4f 100644
--- a/debuggerd/include/debuggerd/handler.h
+++ b/debuggerd/include/debuggerd/handler.h
@@ -40,6 +40,8 @@
void* fdsan_table;
const gwp_asan::AllocatorState* gwp_asan_state;
const gwp_asan::AllocationMetadata* gwp_asan_metadata;
+ const char* scudo_stack_depot;
+ const char* scudo_region_info;
};
// These callbacks are called in a signal handler, and thus must be async signal safe.
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h b/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h
new file mode 100644
index 0000000..4d00ece
--- /dev/null
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include "types.h"
+#include "utility.h"
+
+#include <memory.h>
+
+#include "scudo/interface.h"
+
+class ScudoCrashData {
+ public:
+ ScudoCrashData() = delete;
+ ~ScudoCrashData() = default;
+ ScudoCrashData(unwindstack::Memory* process_memory, const ProcessInfo& process_info);
+
+ bool CrashIsMine() const;
+
+ void DumpCause(log_t* log, unwindstack::Unwinder* unwinder) const;
+
+ private:
+ scudo_error_info error_info_ = {};
+ uintptr_t untagged_fault_addr_;
+
+ void DumpReport(const scudo_error_report* report, log_t* log,
+ unwindstack::Unwinder* unwinder) const;
+};
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index 35c3fd6..04c4b5c 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -41,6 +41,8 @@
uintptr_t fdsan_table_address = 0;
uintptr_t gwp_asan_state = 0;
uintptr_t gwp_asan_metadata = 0;
+ uintptr_t scudo_stack_depot = 0;
+ uintptr_t scudo_region_info = 0;
bool has_fault_address = false;
uintptr_t fault_address = 0;
diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp
new file mode 100644
index 0000000..f8bfe07
--- /dev/null
+++ b/debuggerd/libdebuggerd/scudo.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "libdebuggerd/scudo.h"
+#include "libdebuggerd/gwp_asan.h"
+
+#include "unwindstack/Memory.h"
+#include "unwindstack/Unwinder.h"
+
+#include <bionic/macros.h>
+
+std::unique_ptr<char[]> AllocAndReadFully(unwindstack::Memory* process_memory, uint64_t addr,
+ size_t size) {
+ auto buf = std::make_unique<char[]>(size);
+ if (!process_memory->ReadFully(addr, buf.get(), size)) {
+ return std::unique_ptr<char[]>();
+ }
+ return buf;
+}
+
+static const uintptr_t kTagGranuleSize = 16;
+
+ScudoCrashData::ScudoCrashData(unwindstack::Memory* process_memory,
+ const ProcessInfo& process_info) {
+ if (!process_info.has_fault_address) {
+ return;
+ }
+
+ auto stack_depot = AllocAndReadFully(process_memory, process_info.scudo_stack_depot,
+ __scudo_get_stack_depot_size());
+ auto region_info = AllocAndReadFully(process_memory, process_info.scudo_region_info,
+ __scudo_get_region_info_size());
+
+ untagged_fault_addr_ = untag_address(process_info.fault_address);
+ uintptr_t fault_page = untagged_fault_addr_ & ~(PAGE_SIZE - 1);
+
+ uintptr_t memory_begin = fault_page - PAGE_SIZE * 16;
+ if (memory_begin > fault_page) {
+ return;
+ }
+
+ uintptr_t memory_end = fault_page + PAGE_SIZE * 16;
+ if (memory_end < fault_page) {
+ return;
+ }
+
+ auto memory = std::make_unique<char[]>(memory_end - memory_begin);
+ for (auto i = memory_begin; i != memory_end; i += PAGE_SIZE) {
+ process_memory->ReadFully(i, memory.get() + i - memory_begin, PAGE_SIZE);
+ }
+
+ auto memory_tags = std::make_unique<char[]>((memory_end - memory_begin) / kTagGranuleSize);
+ for (auto i = memory_begin; i != memory_end; i += kTagGranuleSize) {
+ memory_tags[(i - memory_begin) / kTagGranuleSize] = process_memory->ReadTag(i);
+ }
+
+ __scudo_get_error_info(&error_info_, process_info.fault_address, stack_depot.get(),
+ region_info.get(), memory.get(), memory_tags.get(), memory_begin,
+ memory_end - memory_begin);
+}
+
+bool ScudoCrashData::CrashIsMine() const {
+ return error_info_.reports[0].error_type != UNKNOWN;
+}
+
+void ScudoCrashData::DumpCause(log_t* log, unwindstack::Unwinder* unwinder) const {
+ if (error_info_.reports[1].error_type != UNKNOWN) {
+ _LOG(log, logtype::HEADER,
+ "\nNote: multiple potential causes for this crash were detected, listing them in "
+ "decreasing order of probability.\n");
+ }
+
+ size_t report_num = 0;
+ while (report_num < sizeof(error_info_.reports) / sizeof(error_info_.reports[0]) &&
+ error_info_.reports[report_num].error_type != UNKNOWN) {
+ DumpReport(&error_info_.reports[report_num++], log, unwinder);
+ }
+}
+
+void ScudoCrashData::DumpReport(const scudo_error_report* report, log_t* log,
+ unwindstack::Unwinder* unwinder) const {
+ const char *error_type_str;
+ switch (report->error_type) {
+ case USE_AFTER_FREE:
+ error_type_str = "Use After Free";
+ break;
+ case BUFFER_OVERFLOW:
+ error_type_str = "Buffer Overflow";
+ break;
+ case BUFFER_UNDERFLOW:
+ error_type_str = "Buffer Underflow";
+ break;
+ default:
+ error_type_str = "Unknown";
+ break;
+ }
+
+ uintptr_t diff;
+ const char* location_str;
+
+ if (untagged_fault_addr_ < report->allocation_address) {
+ // Buffer Underflow, 6 bytes left of a 41-byte allocation at 0xdeadbeef.
+ location_str = "left of";
+ diff = report->allocation_address - untagged_fault_addr_;
+ } else if (untagged_fault_addr_ - report->allocation_address < report->allocation_size) {
+ // Use After Free, 40 bytes into a 41-byte allocation at 0xdeadbeef.
+ location_str = "into";
+ diff = untagged_fault_addr_ - report->allocation_address;
+ } else {
+ // Buffer Overflow, 6 bytes right of a 41-byte allocation at 0xdeadbeef.
+ location_str = "right of";
+ diff = untagged_fault_addr_ - report->allocation_address - report->allocation_size;
+ }
+
+ // Suffix of 'bytes', i.e. 4 bytes' vs. '1 byte'.
+ const char* byte_suffix = "s";
+ if (diff == 1) {
+ byte_suffix = "";
+ }
+ _LOG(log, logtype::HEADER,
+ "\nCause: [MTE]: %s, %" PRIuPTR " byte%s %s a %zu-byte allocation at 0x%" PRIxPTR "\n",
+ error_type_str, diff, byte_suffix, location_str, report->allocation_size,
+ report->allocation_address);
+
+ if (report->allocation_trace[0]) {
+ _LOG(log, logtype::BACKTRACE, "\nallocated by thread %u:\n", report->allocation_tid);
+ unwinder->SetDisplayBuildID(true);
+ for (size_t i = 0; i < 64 && report->allocation_trace[i]; ++i) {
+ unwindstack::FrameData frame_data =
+ unwinder->BuildFrameFromPcOnly(report->allocation_trace[i]);
+ frame_data.num = i;
+ _LOG(log, logtype::BACKTRACE, " %s\n", unwinder->FormatFrame(frame_data).c_str());
+ }
+ }
+
+ if (report->deallocation_trace[0]) {
+ _LOG(log, logtype::BACKTRACE, "\ndeallocated by thread %u:\n", report->deallocation_tid);
+ unwinder->SetDisplayBuildID(true);
+ for (size_t i = 0; i < 64 && report->deallocation_trace[i]; ++i) {
+ unwindstack::FrameData frame_data =
+ unwinder->BuildFrameFromPcOnly(report->deallocation_trace[i]);
+ frame_data.num = i;
+ _LOG(log, logtype::BACKTRACE, " %s\n", unwinder->FormatFrame(frame_data).c_str());
+ }
+ }
+}
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index d6b2e25..ab65dd1 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -56,6 +56,7 @@
#include "libdebuggerd/backtrace.h"
#include "libdebuggerd/gwp_asan.h"
#include "libdebuggerd/open_files_list.h"
+#include "libdebuggerd/scudo.h"
#include "libdebuggerd/utility.h"
#include "gwp_asan/common.h"
@@ -389,14 +390,17 @@
}
std::unique_ptr<GwpAsanCrashData> gwp_asan_crash_data;
+ std::unique_ptr<ScudoCrashData> scudo_crash_data;
if (primary_thread) {
gwp_asan_crash_data = std::make_unique<GwpAsanCrashData>(unwinder->GetProcessMemory().get(),
process_info, thread_info);
+ scudo_crash_data =
+ std::make_unique<ScudoCrashData>(unwinder->GetProcessMemory().get(), process_info);
}
if (primary_thread && gwp_asan_crash_data->CrashIsMine()) {
gwp_asan_crash_data->DumpCause(log);
- } else if (thread_info.siginfo) {
+ } else if (thread_info.siginfo && !(primary_thread && scudo_crash_data->CrashIsMine())) {
dump_probable_cause(log, thread_info.siginfo, unwinder->GetMaps(),
thread_info.registers.get());
}
@@ -427,6 +431,8 @@
gwp_asan_crash_data->DumpAllocationTrace(log, unwinder);
}
+ scudo_crash_data->DumpCause(log, unwinder);
+
unwindstack::Maps* maps = unwinder->GetMaps();
dump_memory_and_code(log, maps, unwinder->GetProcessMemory().get(),
thread_info.registers.get());
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 3bf28b6..c8a3431 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -35,6 +35,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
+#include <bionic/mte_kernel.h>
#include <bionic/reserved_signals.h>
#include <debuggerd/handler.h>
#include <log/log.h>
@@ -374,6 +375,12 @@
return "SEGV_ADIDERR";
case SEGV_ADIPERR:
return "SEGV_ADIPERR";
+#if defined(ANDROID_EXPERIMENTAL_MTE)
+ case SEGV_MTEAERR:
+ return "SEGV_MTEAERR";
+ case SEGV_MTESERR:
+ return "SEGV_MTESERR";
+#endif
}
static_assert(NSIGSEGV == SEGV_ADIPERR, "missing SEGV_* si_code");
break;
diff --git a/debuggerd/protocol.h b/debuggerd/protocol.h
index e85660c..53a76ea 100644
--- a/debuggerd/protocol.h
+++ b/debuggerd/protocol.h
@@ -95,6 +95,8 @@
uintptr_t fdsan_table_address;
uintptr_t gwp_asan_state;
uintptr_t gwp_asan_metadata;
+ uintptr_t scudo_stack_depot;
+ uintptr_t scudo_region_info;
};
struct __attribute__((__packed__)) CrashInfo {
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 5acd039..2d6071f 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -580,6 +580,10 @@
bool ProcessUpdateStateOnDataWipe(bool allow_forward_merge,
const std::function<bool()>& callback);
+ // Return device string of a mapped image, or if it is not available, the mapped image path.
+ bool GetMappedImageDeviceStringOrPath(const std::string& device_name,
+ std::string* device_string_or_mapped_path);
+
std::string gsid_dir_;
std::string metadata_dir_;
std::unique_ptr<IDeviceInfo> device_;
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 03efd68..488009a 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -1691,7 +1691,7 @@
return false;
}
std::string cow_device;
- if (!dm.GetDeviceString(cow_name, &cow_device)) {
+ if (!GetMappedImageDeviceStringOrPath(cow_name, &cow_device)) {
LOG(ERROR) << "Could not determine major/minor for: " << cow_name;
return false;
}
@@ -1788,7 +1788,7 @@
// If the COW image exists, append it as the last extent.
if (snapshot_status.cow_file_size() > 0) {
std::string cow_image_device;
- if (!dm.GetDeviceString(cow_image_name, &cow_image_device)) {
+ if (!GetMappedImageDeviceStringOrPath(cow_image_name, &cow_image_device)) {
LOG(ERROR) << "Cannot determine major/minor for: " << cow_image_name;
return false;
}
@@ -2364,7 +2364,6 @@
const std::map<std::string, SnapshotStatus>& all_snapshot_status) {
CHECK(lock);
- auto& dm = DeviceMapper::Instance();
CreateLogicalPartitionParams cow_params{
.block_device = LP_METADATA_DEFAULT_PARTITION_NAME,
.metadata = exported_target_metadata,
@@ -2389,7 +2388,7 @@
}
std::string cow_path;
- if (!dm.GetDmDevicePathByName(cow_name, &cow_path)) {
+ if (!images_->GetMappedImageDevice(cow_name, &cow_path)) {
LOG(ERROR) << "Cannot determine path for " << cow_name;
return Return::Error();
}
@@ -2742,5 +2741,24 @@
return SnapshotMergeStats::GetInstance(*this);
}
+bool SnapshotManager::GetMappedImageDeviceStringOrPath(const std::string& device_name,
+ std::string* device_string_or_mapped_path) {
+ auto& dm = DeviceMapper::Instance();
+ // Try getting the device string if it is a device mapper device.
+ if (dm.GetState(device_name) != DmDeviceState::INVALID) {
+ return dm.GetDeviceString(device_name, device_string_or_mapped_path);
+ }
+
+ // Otherwise, get path from IImageManager.
+ if (!images_->GetMappedImageDevice(device_name, device_string_or_mapped_path)) {
+ return false;
+ }
+
+ LOG(WARNING) << "Calling GetMappedImageDevice with local image manager; device "
+ << (device_string_or_mapped_path ? *device_string_or_mapped_path : "(nullptr)")
+ << "may not be available in first stage init! ";
+ return true;
+}
+
} // namespace snapshot
} // namespace android
diff --git a/liblog/README.md b/liblog/README.md
index f64f376..74a2cd7 100644
--- a/liblog/README.md
+++ b/liblog/README.md
@@ -60,8 +60,6 @@
LOG_EVENT_INT(tag, value)
LOG_EVENT_LONG(tag, value)
- clockid_t android_log_clockid()
-
log_id_t android_logger_get_id(struct logger *logger)
int android_logger_clear(struct logger *logger)
int android_logger_get_log_size(struct logger *logger)
@@ -119,7 +117,7 @@
multiple logs can be opened with `android_logger_list_alloc()`, calling in turn the
`android_logger_open()` for each log id. Each entry can be retrieved with
`android_logger_list_read()`. The log(s) can be closed with `android_logger_list_free()`.
-`ANDROID_LOG_NONBLOCK` mode will report when the log reading is done with an `EAGAIN` error return
+`ANDROID_LOG_NONBLOCK` mode will report when the log reading is done with an `EAGAIN` error return
code, otherwise the `android_logger_list_read()` call will block for new entries.
The `ANDROID_LOG_WRAP` mode flag to the `android_logger_list_alloc_time()` signals logd to quiesce
diff --git a/liblog/include/log/log.h b/liblog/include/log/log.h
index 820b7cb..d7e9b7d 100644
--- a/liblog/include/log/log.h
+++ b/liblog/include/log/log.h
@@ -133,12 +133,6 @@
(void)__android_log_bswrite(_tag, _value);
#endif
-#ifdef __linux__
-
-clockid_t android_log_clockid(void);
-
-#endif /* __linux__ */
-
/* --------------------------------------------------------------------- */
/*
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index 3a75fa3..22c7eca 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -192,7 +192,7 @@
return -EINVAL;
}
- clock_gettime(android_log_clockid(), &ts);
+ clock_gettime(CLOCK_REALTIME, &ts);
if (log_id == LOG_ID_SECURITY) {
if (vec[0].iov_len < 4) {
diff --git a/liblog/logprint.cpp b/liblog/logprint.cpp
index 9e8d277..238431f 100644
--- a/liblog/logprint.cpp
+++ b/liblog/logprint.cpp
@@ -216,11 +216,7 @@
p_ret->year_output = false;
p_ret->zone_output = false;
p_ret->epoch_output = false;
-#ifdef __ANDROID__
- p_ret->monotonic_output = android_log_clockid() == CLOCK_MONOTONIC;
-#else
p_ret->monotonic_output = false;
-#endif
p_ret->uid_output = false;
p_ret->descriptive_output = false;
descriptive_output = false;
@@ -1465,13 +1461,10 @@
nsec = entry->tv_nsec;
#if __ANDROID__
if (p_format->monotonic_output) {
- /* prevent convertMonotonic from being called if logd is monotonic */
- if (android_log_clockid() != CLOCK_MONOTONIC) {
- struct timespec time;
- convertMonotonic(&time, entry);
- now = time.tv_sec;
- nsec = time.tv_nsec;
- }
+ struct timespec time;
+ convertMonotonic(&time, entry);
+ now = time.tv_sec;
+ nsec = time.tv_nsec;
}
#endif
if (now < 0) {
diff --git a/liblog/pmsg_writer.cpp b/liblog/pmsg_writer.cpp
index 0751e2c..8e676bd 100644
--- a/liblog/pmsg_writer.cpp
+++ b/liblog/pmsg_writer.cpp
@@ -188,7 +188,7 @@
return -EINVAL;
}
- clock_gettime(android_log_clockid(), &ts);
+ clock_gettime(CLOCK_REALTIME, &ts);
cp = strdup(filename);
if (!cp) {
diff --git a/liblog/properties.cpp b/liblog/properties.cpp
index 37670ec..f5e060c 100644
--- a/liblog/properties.cpp
+++ b/liblog/properties.cpp
@@ -365,29 +365,6 @@
return c;
}
-static unsigned char evaluate_persist_ro(const struct cache2_char* self) {
- unsigned char c = self->cache_persist.c;
-
- if (c) {
- return c;
- }
-
- return self->cache_ro.c;
-}
-
-/*
- * Timestamp state generally remains constant, but can change at any time
- * to handle developer requirements.
- */
-clockid_t android_log_clockid() {
- static struct cache2_char clockid = {PTHREAD_MUTEX_INITIALIZER, 0,
- "persist.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
- "ro.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
- evaluate_persist_ro};
-
- return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
-}
-
/*
* Security state generally remains constant, but the DO must be able
* to turn off logging should it become spammy after an attack is detected.
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index f4734b9..a4e4def 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -184,7 +184,7 @@
*/
struct timespec ts;
- clock_gettime(android_log_clockid(), &ts);
+ clock_gettime(CLOCK_REALTIME, &ts);
android_pmsg_log_header_t pmsg_header;
pmsg_header.magic = LOGGER_MAGIC;
@@ -260,7 +260,7 @@
*/
struct timespec ts;
- clock_gettime(android_log_clockid(), &ts);
+ clock_gettime(CLOCK_REALTIME, &ts);
struct packet {
android_pmsg_log_header_t pmsg_header;
@@ -335,7 +335,7 @@
*/
struct timespec ts;
- clock_gettime(android_log_clockid(), &ts);
+ clock_gettime(CLOCK_REALTIME, &ts);
struct packet {
android_pmsg_log_header_t pmsg_header;
@@ -410,7 +410,7 @@
*/
struct timespec ts;
- clock_gettime(android_log_clockid(), &ts);
+ clock_gettime(CLOCK_REALTIME, &ts);
struct packet {
android_pmsg_log_header_t pmsg_header;
@@ -483,7 +483,7 @@
*/
struct timespec ts;
- clock_gettime(android_log_clockid(), &ts);
+ clock_gettime(CLOCK_REALTIME, &ts);
struct packet {
android_pmsg_log_header_t pmsg_header;
@@ -792,16 +792,6 @@
BENCHMARK(BM_is_loggable);
/*
- * Measure the time it takes for android_log_clockid.
- */
-static void BM_clockid(benchmark::State& state) {
- while (state.KeepRunning()) {
- android_log_clockid();
- }
-}
-BENCHMARK(BM_clockid);
-
-/*
* Measure the time it takes for __android_log_security.
*/
static void BM_security(benchmark::State& state) {
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index d3d8e91..bbc985a 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -329,8 +329,6 @@
#ifdef __ANDROID__
pid_t pid = getpid();
- log_time ts(android_log_clockid());
-
size_t num_lines = 1, size = 0, length = 0, total = 0;
const char* cp = message;
while (*cp) {
@@ -432,7 +430,6 @@
pid_t pid = getpid();
static const char tag[] = "TEST__android_log_buf_write";
- log_time ts(android_log_clockid());
auto write_function = [&] {
EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO, tag, message));
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 8185f01..13023f2 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -459,7 +459,7 @@
closedir);
if (!dir.get()) return retval;
- log_time now(android_log_clockid());
+ log_time now(CLOCK_REALTIME);
size_t len = strlen(file);
log_time modulo(0, NS_PER_SEC);
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index b32b437..3a55c4e 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -174,11 +174,6 @@
}
TEST(logcat, year) {
- if (android_log_clockid() == CLOCK_MONOTONIC) {
- fprintf(stderr, "Skipping test, logd is monotonic time\n");
- return;
- }
-
int count;
int tries = 3; // in case run too soon after system start or buffer clear
@@ -249,11 +244,6 @@
}
TEST(logcat, tz) {
- if (android_log_clockid() == CLOCK_MONOTONIC) {
- fprintf(stderr, "Skipping test, logd is monotonic time\n");
- return;
- }
-
int tries = 4; // in case run too soon after system start or buffer clear
int count;
diff --git a/logd/Android.bp b/logd/Android.bp
index b6d30cd..ea1054d 100644
--- a/logd/Android.bp
+++ b/logd/Android.bp
@@ -52,7 +52,9 @@
export_include_dirs: ["."],
- cflags: ["-Werror"] + event_flag,
+ cflags: [
+ "-Wextra",
+ ] + event_flag,
}
cc_binary {
@@ -75,7 +77,9 @@
"libcap",
],
- cflags: ["-Werror"],
+ cflags: [
+ "-Wextra",
+ ],
}
cc_binary {
@@ -90,10 +94,8 @@
shared_libs: ["libbase"],
cflags: [
- "-Wall",
+ "-Wconversion",
"-Wextra",
- "-Werror",
- "-Wconversion"
],
}
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 37067bd..bcc187d 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -247,22 +247,10 @@
static const char audit_str[] = " audit(";
char* timeptr = strstr(str, audit_str);
- if (timeptr &&
- ((cp = now.strptime(timeptr + sizeof(audit_str) - 1, "%s.%q"))) &&
+ if (timeptr && ((cp = now.strptime(timeptr + sizeof(audit_str) - 1, "%s.%q"))) &&
(*cp == ':')) {
memcpy(timeptr + sizeof(audit_str) - 1, "0.0", 3);
memmove(timeptr + sizeof(audit_str) - 1 + 3, cp, strlen(cp) + 1);
- if (!isMonotonic()) {
- if (android::isMonotonic(now)) {
- LogKlog::convertMonotonicToReal(now);
- }
- } else {
- if (!android::isMonotonic(now)) {
- LogKlog::convertRealToMonotonic(now);
- }
- }
- } else if (isMonotonic()) {
- now = log_time(CLOCK_MONOTONIC);
} else {
now = log_time(CLOCK_REALTIME);
}
diff --git a/logd/LogAudit.h b/logd/LogAudit.h
index c3d7a3e..7df0a5d 100644
--- a/logd/LogAudit.h
+++ b/logd/LogAudit.h
@@ -36,9 +36,6 @@
public:
LogAudit(LogBuffer* buf, LogReader* reader, int fdDmesg);
int log(char* buf, size_t len);
- bool isMonotonic() {
- return logbuf->isMonotonic();
- }
protected:
virtual bool onDataAvailable(SocketClient* cli);
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index a7323e8..2cb0c5e 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -50,48 +50,6 @@
setSize(i, LOG_BUFFER_MIN_SIZE);
}
}
- bool lastMonotonic = monotonic;
- monotonic = android_log_clockid() == CLOCK_MONOTONIC;
- if (lastMonotonic != monotonic) {
- //
- // Fixup all timestamps, may not be 100% accurate, but better than
- // throwing what we have away when we get 'surprised' by a change.
- // In-place element fixup so no need to check reader-lock. Entries
- // should already be in timestamp order, but we could end up with a
- // few out-of-order entries if new monotonics come in before we
- // are notified of the reinit change in status. A Typical example would
- // be:
- // --------- beginning of system
- // 10.494082 184 201 D Cryptfs : Just triggered post_fs_data
- // --------- beginning of kernel
- // 0.000000 0 0 I : Initializing cgroup subsys
- // as the act of mounting /data would trigger persist.logd.timestamp to
- // be corrected. 1/30 corner case YMMV.
- //
- rdlock();
- LogBufferElementCollection::iterator it = mLogElements.begin();
- while ((it != mLogElements.end())) {
- LogBufferElement* e = *it;
- if (monotonic) {
- if (!android::isMonotonic(e->mRealTime)) {
- LogKlog::convertRealToMonotonic(e->mRealTime);
- if ((e->mRealTime.tv_nsec % 1000) == 0) {
- e->mRealTime.tv_nsec++;
- }
- }
- } else {
- if (android::isMonotonic(e->mRealTime)) {
- LogKlog::convertMonotonicToReal(e->mRealTime);
- if ((e->mRealTime.tv_nsec % 1000) == 0) {
- e->mRealTime.tv_nsec++;
- }
- }
- }
- ++it;
- }
- unlock();
- }
-
// Release any sleeping reader threads to dump their current content.
LogReaderThread::wrlock();
@@ -106,10 +64,7 @@
}
LogBuffer::LogBuffer(LastLogTimes* times, LogTags* tags, PruneList* prune)
- : monotonic(android_log_clockid() == CLOCK_MONOTONIC),
- mTimes(*times),
- tags_(tags),
- prune_(prune) {
+ : mTimes(*times), tags_(tags), prune_(prune) {
pthread_rwlock_init(&mLogElementsLock, nullptr);
log_id_for_each(i) {
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index eb41efb..3c45667 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -32,46 +32,6 @@
#include "LogTags.h"
#include "LogWhiteBlackList.h"
-//
-// We are either in 1970ish (MONOTONIC) or 2016+ish (REALTIME) so to
-// differentiate without prejudice, we use 1972 to delineate, earlier
-// is likely monotonic, later is real. Otherwise we start using a
-// dividing line between monotonic and realtime if more than a minute
-// difference between them.
-//
-namespace android {
-
-static bool isMonotonic(const log_time& mono) {
- static const uint32_t EPOCH_PLUS_2_YEARS = 2 * 24 * 60 * 60 * 1461 / 4;
- static const uint32_t EPOCH_PLUS_MINUTE = 60;
-
- if (mono.tv_sec >= EPOCH_PLUS_2_YEARS) {
- return false;
- }
-
- log_time now(CLOCK_REALTIME);
-
- /* Timezone and ntp time setup? */
- if (now.tv_sec >= EPOCH_PLUS_2_YEARS) {
- return true;
- }
-
- /* no way to differentiate realtime from monotonic time */
- if (now.tv_sec < EPOCH_PLUS_MINUTE) {
- return false;
- }
-
- log_time cpu(CLOCK_MONOTONIC);
- /* too close to call to differentiate monotonic times from realtime */
- if ((cpu.tv_sec + EPOCH_PLUS_MINUTE) >= now.tv_sec) {
- return false;
- }
-
- /* dividing line half way between monotonic and realtime */
- return mono.tv_sec < ((cpu.tv_sec + now.tv_sec) / 2);
-}
-}
-
typedef std::list<LogBufferElement*> LogBufferElementCollection;
class LogBuffer {
@@ -91,8 +51,6 @@
unsigned long mMaxSize[LOG_ID_MAX];
- bool monotonic;
-
LogBufferElement* lastLoggedElements[LOG_ID_MAX];
LogBufferElement* droppedElements[LOG_ID_MAX];
void log(LogBufferElement* elem);
@@ -103,9 +61,6 @@
LogBuffer(LastLogTimes* times, LogTags* tags, PruneList* prune);
~LogBuffer();
void init();
- bool isMonotonic() {
- return monotonic;
- }
int log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char* msg,
uint16_t len);
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index 5788ada..c308073 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -309,8 +309,6 @@
}
buf = cp;
- if (isMonotonic()) return now;
-
const char* b;
if (((b = android::strnstr(cp, len, suspendStr))) &&
(((b += strlen(suspendStr)) - cp) < len)) {
@@ -356,11 +354,7 @@
convertMonotonicToReal(now);
} else {
- if (isMonotonic()) {
- now = log_time(CLOCK_MONOTONIC);
- } else {
- now = log_time(CLOCK_REALTIME);
- }
+ now = log_time(CLOCK_REALTIME);
}
return now;
}
@@ -431,45 +425,6 @@
return pri;
}
-// Passed the entire SYSLOG_ACTION_READ_ALL buffer and interpret a
-// compensated start time.
-void LogKlog::synchronize(const char* buf, ssize_t len) {
- const char* cp = android::strnstr(buf, len, suspendStr);
- if (!cp) {
- cp = android::strnstr(buf, len, resumeStr);
- if (!cp) return;
- } else {
- const char* rp = android::strnstr(buf, len, resumeStr);
- if (rp && (rp < cp)) cp = rp;
- }
-
- do {
- --cp;
- } while ((cp > buf) && (*cp != '\n'));
- if (*cp == '\n') {
- ++cp;
- }
- parseKernelPrio(cp, len - (cp - buf));
-
- log_time now = sniffTime(cp, len - (cp - buf), true);
-
- const char* suspended = android::strnstr(buf, len, suspendedStr);
- if (!suspended || (suspended > cp)) {
- return;
- }
- cp = suspended;
-
- do {
- --cp;
- } while ((cp > buf) && (*cp != '\n'));
- if (*cp == '\n') {
- ++cp;
- }
- parseKernelPrio(cp, len - (cp - buf));
-
- sniffTime(cp, len - (cp - buf), true);
-}
-
// Convert kernel log priority number into an Android Logger priority number
static int convertKernelPrioToAndroidPrio(int pri) {
switch (pri & LOG_PRIMASK) {
@@ -789,7 +744,7 @@
memcpy(np, p, b);
np[b] = '\0';
- if (!isMonotonic()) {
+ {
// Watch out for singular race conditions with timezone causing near
// integer quarter-hour jumps in the time and compensate accordingly.
// Entries will be temporal within near_seconds * 2. b/21868540
diff --git a/logd/LogKlog.h b/logd/LogKlog.h
index 6bfd6a8..4c09751 100644
--- a/logd/LogKlog.h
+++ b/logd/LogKlog.h
@@ -42,17 +42,10 @@
LogKlog(LogBuffer* buf, LogReader* reader, int fdWrite, int fdRead,
bool auditd);
int log(const char* buf, ssize_t len);
- void synchronize(const char* buf, ssize_t len);
- bool isMonotonic() {
- return logbuf->isMonotonic();
- }
static void convertMonotonicToReal(log_time& real) {
real += correction;
}
- static void convertRealToMonotonic(log_time& real) {
- real -= correction;
- }
protected:
log_time sniffTime(const char*& buf, ssize_t len, bool reverse);
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 4702de5..a590cef 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -150,9 +150,8 @@
// Convert realtime to sequence number
if (start != log_time::EPOCH) {
bool start_time_set = false;
- bool is_monotonic = logbuf().isMonotonic() && android::isMonotonic(start);
uint64_t last = sequence;
- auto log_find_start = [pid, logMask, start, is_monotonic, &sequence, &start_time_set,
+ auto log_find_start = [pid, logMask, start, &sequence, &start_time_set,
&last](const LogBufferElement* element) -> int {
if (pid && pid != element->getPid()) {
return 0;
@@ -164,15 +163,13 @@
sequence = element->getSequence();
start_time_set = true;
return -1;
- } else if (!is_monotonic || android::isMonotonic(element->getRealTime())) {
+ } else {
if (start < element->getRealTime()) {
sequence = last;
start_time_set = true;
return -1;
}
last = element->getSequence();
- } else {
- last = element->getSequence();
}
return 0;
};
diff --git a/logd/LogTags.cpp b/logd/LogTags.cpp
index 3e52b38..082e4a1 100644
--- a/logd/LogTags.cpp
+++ b/logd/LogTags.cpp
@@ -99,8 +99,7 @@
struct tm tm;
localtime_r(&now, &tm);
char timebuf[20];
- size_t len =
- strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", &tm);
+ strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", &tm);
android::base::WriteStringToFd(
android::base::StringPrintf(
"# Rebuilt %.20s, content owned by logd\n", timebuf),
@@ -189,7 +188,6 @@
// Read the event log tags file, and build up our internal database
void LogTags::ReadFileEventLogTags(const char* filename, bool warn) {
bool etc = !strcmp(filename, system_event_log_tags);
- bool debug = !etc && !strcmp(filename, debug_event_log_tags);
if (!etc) {
RebuildFileEventLogTags(filename, warn);
@@ -548,7 +546,7 @@
*/
struct timespec ts;
- clock_gettime(android_log_clockid(), &ts);
+ clock_gettime(CLOCK_REALTIME, &ts);
android_log_header_t header = {
.id = LOG_ID_EVENTS,
diff --git a/logd/README.property b/logd/README.property
index 1b7e165..6a9369a 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -44,10 +44,6 @@
oldest entries of chattiest UID, and
the chattiest PID of system
(1000, or AID_SYSTEM).
-persist.logd.timestamp string ro The recording timestamp source.
- "m[onotonic]" is the only supported
- key character, otherwise realtime.
-ro.logd.timestamp string realtime default for persist.logd.timestamp
log.tag string persist The global logging level, VERBOSE,
DEBUG, INFO, WARN, ERROR, ASSERT or
SILENT. Only the first character is
diff --git a/logd/main.cpp b/logd/main.cpp
index cc45eb3..d9dd249 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -109,21 +109,6 @@
return 0;
}
-// Property helper
-static bool check_flag(const char* prop, const char* flag) {
- const char* cp = strcasestr(prop, flag);
- if (!cp) {
- return false;
- }
- // We only will document comma (,)
- static const char sep[] = ",:;|+ \t\f";
- if ((cp != prop) && !strchr(sep, cp[-1])) {
- return false;
- }
- cp += strlen(flag);
- return !*cp || !!strchr(sep, *cp);
-}
-
static int fdDmesg = -1;
void android::prdebug(const char* fmt, ...) {
if (fdDmesg < 0) {
@@ -201,10 +186,6 @@
}
buf[--len] = '\0';
- if (kl && kl->isMonotonic()) {
- kl->synchronize(buf.get(), len);
- }
-
ssize_t sublen;
for (char *ptr = nullptr, *tok = buf.get();
(rc >= 0) && !!(tok = android::log_strntok_r(tok, len, ptr, sublen));
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 1dd5c86..55737e9 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -606,7 +606,7 @@
// A few tries to get it right just in case wrap kicks in due to
// content providers being active during the test.
int i = 5;
- log_time start(android_log_clockid());
+ log_time start(CLOCK_REALTIME);
start.tv_sec -= 30; // reach back a moderate period of time
while (--i) {
@@ -682,7 +682,7 @@
if (msg > start) {
start = msg;
start.tv_sec += 30;
- log_time now = log_time(android_log_clockid());
+ log_time now = log_time(CLOCK_REALTIME);
if (start > now) {
start = now;
--start.tv_sec;