Merge "adb: make pulling symlinks and devices work."
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 3ed2a7d..b132118 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -30,12 +30,31 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include "adb.h"
#include "adb_trace.h"
#include "sysdeps.h"
ADB_MUTEX_DEFINE(basename_lock);
ADB_MUTEX_DEFINE(dirname_lock);
+#if defined(_WIN32)
+constexpr char kNullFileName[] = "NUL";
+#else
+constexpr char kNullFileName[] = "/dev/null";
+#endif
+
+void close_stdin() {
+ int fd = unix_open(kNullFileName, O_RDONLY);
+ if (fd == -1) {
+ fatal_errno("failed to open %s", kNullFileName);
+ }
+
+ if (TEMP_FAILURE_RETRY(dup2(fd, STDIN_FILENO)) == -1) {
+ fatal_errno("failed to redirect stdin to %s", kNullFileName);
+ }
+ unix_close(fd);
+}
+
bool getcwd(std::string* s) {
char* cwd = getcwd(nullptr, 0);
if (cwd != nullptr) *s = cwd;
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index 537d0e4..388d7dd 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -19,6 +19,8 @@
#include <string>
+void close_stdin();
+
bool getcwd(std::string* cwd);
bool directory_exists(const std::string& path);
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 3ce5242..b37d04d 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -34,11 +34,10 @@
#include "adb.h"
#include "adb_auth.h"
#include "adb_listeners.h"
+#include "adb_utils.h"
#include "transport.h"
#if defined(_WIN32)
-static const char kNullFileName[] = "NUL";
-
static BOOL WINAPI ctrlc_handler(DWORD type) {
// TODO: Consider trying to kill a starting up adb server (if we're in
// launch_server) by calling GenerateConsoleCtrlEvent().
@@ -66,24 +65,11 @@
return temp_path_utf8 + log_name;
}
#else
-static const char kNullFileName[] = "/dev/null";
-
static std::string GetLogFilePath() {
return std::string("/tmp/adb.log");
}
#endif
-static void close_stdin() {
- int fd = unix_open(kNullFileName, O_RDONLY);
- if (fd == -1) {
- fatal("cannot open '%s': %s", kNullFileName, strerror(errno));
- }
- if (dup2(fd, STDIN_FILENO) == -1) {
- fatal("cannot redirect stdin: %s", strerror(errno));
- }
- unix_close(fd);
-}
-
static void setup_daemon_logging(void) {
const std::string log_file_path(GetLogFilePath());
int fd = unix_open(log_file_path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0640);
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index d244f7d..8575c86 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -112,9 +112,10 @@
" (-a preserves file timestamp and mode)\n"
" adb sync [ <directory> ] - copy host->device only if changed\n"
" (-l means list but don't copy)\n"
- " adb shell [-e escape] [-Tt] [-x] [command]\n"
+ " adb shell [-e escape] [-n] [-Tt] [-x] [command]\n"
" - run remote shell command (interactive shell if no command given)\n"
" (-e: choose escape character, or \"none\"; default '~')\n"
+ " (-n: don't read from stdin)\n"
" (-T: disable PTY allocation)\n"
" (-t: force PTY allocation)\n"
" (-x: disable remote exit codes and stdout/stderr separation)\n"
@@ -733,6 +734,11 @@
use_shell_protocol = false;
--argc;
++argv;
+ } else if (!strcmp(argv[0], "-n")) {
+ close_stdin();
+
+ --argc;
+ ++argv;
} else {
break;
}
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 10c5296..feea7a3 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -34,6 +34,7 @@
#include "adb.h"
#include "adb_auth.h"
#include "adb_listeners.h"
+#include "adb_utils.h"
#include "transport.h"
static const char* root_seclabel = nullptr;
@@ -106,33 +107,7 @@
#endif // ALLOW_ADBD_ROOT
}
-int adbd_main(int server_port) {
- umask(0);
-
- signal(SIGPIPE, SIG_IGN);
-
- init_transport_registration();
-
- // We need to call this even if auth isn't enabled because the file
- // descriptor will always be open.
- adbd_cloexec_auth_socket();
-
- if (ALLOW_ADBD_NO_AUTH && property_get_bool("ro.adb.secure", 0) == 0) {
- auth_required = false;
- }
-
- adbd_auth_init();
-
- // Our external storage path may be different than apps, since
- // we aren't able to bind mount after dropping root.
- const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE");
- if (adb_external_storage != nullptr) {
- setenv("EXTERNAL_STORAGE", adb_external_storage, 1);
- } else {
- D("Warning: ADB_EXTERNAL_STORAGE is not set. Leaving EXTERNAL_STORAGE"
- " unchanged.\n");
- }
-
+static void drop_privileges(int server_port) {
// Add extra groups:
// AID_ADB to access the USB driver
// AID_LOG to read system logs (adb logcat)
@@ -180,6 +155,36 @@
<< error;
}
}
+}
+
+int adbd_main(int server_port) {
+ umask(0);
+
+ signal(SIGPIPE, SIG_IGN);
+
+ init_transport_registration();
+
+ // We need to call this even if auth isn't enabled because the file
+ // descriptor will always be open.
+ adbd_cloexec_auth_socket();
+
+ if (ALLOW_ADBD_NO_AUTH && property_get_bool("ro.adb.secure", 0) == 0) {
+ auth_required = false;
+ }
+
+ adbd_auth_init();
+
+ // Our external storage path may be different than apps, since
+ // we aren't able to bind mount after dropping root.
+ const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE");
+ if (adb_external_storage != nullptr) {
+ setenv("EXTERNAL_STORAGE", adb_external_storage, 1);
+ } else {
+ D("Warning: ADB_EXTERNAL_STORAGE is not set. Leaving EXTERNAL_STORAGE"
+ " unchanged.\n");
+ }
+
+ drop_privileges(server_port);
bool is_usb = false;
if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {
@@ -217,16 +222,6 @@
return 0;
}
-static void close_stdin() {
- int fd = unix_open("/dev/null", O_RDONLY);
- if (fd == -1) {
- perror("failed to open /dev/null, stdin will remain open");
- return;
- }
- dup2(fd, STDIN_FILENO);
- unix_close(fd);
-}
-
int main(int argc, char** argv) {
while (true) {
static struct option opts[] = {
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index c7eeea7..c68f28b 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -76,6 +76,8 @@
ReadOrderlyShutdown(fd);
}
adb_close(fd);
+
+ line_printer_.KeepInfoLine();
}
bool IsValid() { return fd >= 0; }
@@ -243,8 +245,7 @@
}
void Print(const std::string& s) {
- // TODO: we actually don't want ELIDE; we want "ELIDE if smart, FULL if dumb".
- line_printer_.Print(s, LinePrinter::ELIDE);
+ line_printer_.Print(s, LinePrinter::INFO);
}
void Printf(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
@@ -265,7 +266,7 @@
android::base::StringAppendV(&s, fmt, ap);
va_end(ap);
- line_printer_.Print(s, LinePrinter::FULL);
+ line_printer_.Print(s, LinePrinter::ERROR);
}
void Warning(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
@@ -276,7 +277,7 @@
android::base::StringAppendV(&s, fmt, ap);
va_end(ap);
- line_printer_.Print(s, LinePrinter::FULL);
+ line_printer_.Print(s, LinePrinter::WARNING);
}
uint64_t total_bytes;
@@ -654,7 +655,7 @@
}
}
- sc.Printf("%s: %d file%s pushed. %d file%s skipped.%s\n", rpath.c_str(),
+ sc.Printf("%s: %d file%s pushed. %d file%s skipped.%s", rpath.c_str(),
pushed, (pushed == 1) ? "" : "s", skipped,
(skipped == 1) ? "" : "s", sc.TransferRate().c_str());
return true;
@@ -729,7 +730,6 @@
success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode);
}
- sc.Print("\n");
return success;
}
@@ -862,7 +862,7 @@
}
}
- sc.Printf("%s: %d file%s pulled. %d file%s skipped.%s\n", rpath.c_str(),
+ sc.Printf("%s: %d file%s pulled. %d file%s skipped.%s", rpath.c_str(),
pulled, (pulled == 1) ? "" : "s", skipped,
(skipped == 1) ? "" : "s", sc.TransferRate().c_str());
return true;
@@ -976,7 +976,6 @@
}
}
- sc.Print("\n");
return success;
}
diff --git a/adb/line_printer.cpp b/adb/line_printer.cpp
index 4c57c7e..e8fe6c9 100644
--- a/adb/line_printer.cpp
+++ b/adb/line_printer.cpp
@@ -43,7 +43,7 @@
return result;
}
-LinePrinter::LinePrinter() : have_blank_line_(true), console_locked_(false) {
+LinePrinter::LinePrinter() : have_blank_line_(true) {
#ifndef _WIN32
const char* term = getenv("TERM");
smart_terminal_ = unix_isatty(1) && term && string(term) != "dumb";
@@ -59,20 +59,24 @@
#endif
}
+static void Out(const std::string& s) {
+ // Avoid printf and C strings, since the actual output might contain null
+ // bytes like UTF-16 does (yuck).
+ fwrite(s.data(), 1, s.size(), stdout);
+}
+
void LinePrinter::Print(string to_print, LineType type) {
- if (console_locked_) {
- line_buffer_ = to_print;
- line_type_ = type;
+ if (!smart_terminal_) {
+ Out(to_print);
return;
}
- if (smart_terminal_) {
- printf("\r"); // Print over previous line, if any.
- // On Windows, calling a C library function writing to stdout also handles
- // pausing the executable when the "Pause" key or Ctrl-S is pressed.
- }
+ // Print over previous line, if any.
+ // On Windows, calling a C library function writing to stdout also handles
+ // pausing the executable when the "Pause" key or Ctrl-S is pressed.
+ printf("\r");
- if (smart_terminal_ && type == ELIDE) {
+ if (type == INFO) {
#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(console_, &csbi);
@@ -105,57 +109,19 @@
if ((ioctl(0, TIOCGWINSZ, &size) == 0) && size.ws_col) {
to_print = ElideMiddle(to_print, size.ws_col);
}
- printf("%s", to_print.c_str());
+ Out(to_print);
printf("\x1B[K"); // Clear to end of line.
fflush(stdout);
#endif
have_blank_line_ = false;
} else {
- printf("%s\n", to_print.c_str());
+ Out(to_print);
+ Out("\n");
+ have_blank_line_ = true;
}
}
-void LinePrinter::PrintOrBuffer(const char* data, size_t size) {
- if (console_locked_) {
- output_buffer_.append(data, size);
- } else {
- // Avoid printf and C strings, since the actual output might contain null
- // bytes like UTF-16 does (yuck).
- fwrite(data, 1, size, stdout);
- }
-}
-
-void LinePrinter::PrintOnNewLine(const string& to_print) {
- if (console_locked_ && !line_buffer_.empty()) {
- output_buffer_.append(line_buffer_);
- output_buffer_.append(1, '\n');
- line_buffer_.clear();
- }
- if (!have_blank_line_) {
- PrintOrBuffer("\n", 1);
- }
- if (!to_print.empty()) {
- PrintOrBuffer(&to_print[0], to_print.size());
- }
- have_blank_line_ = to_print.empty() || *to_print.rbegin() == '\n';
-}
-
-void LinePrinter::SetConsoleLocked(bool locked) {
- if (locked == console_locked_)
- return;
-
- if (locked)
- PrintOnNewLine("");
-
- console_locked_ = locked;
-
- if (!locked) {
- PrintOnNewLine(output_buffer_);
- if (!line_buffer_.empty()) {
- Print(line_buffer_, line_type_);
- }
- output_buffer_.clear();
- line_buffer_.clear();
- }
+void LinePrinter::KeepInfoLine() {
+ if (!have_blank_line_) Out("\n");
}
diff --git a/adb/line_printer.h b/adb/line_printer.h
index 3d0a5bd..42345e2 100644
--- a/adb/line_printer.h
+++ b/adb/line_printer.h
@@ -26,20 +26,14 @@
bool is_smart_terminal() const { return smart_terminal_; }
void set_smart_terminal(bool smart) { smart_terminal_ = smart; }
- enum LineType {
- FULL,
- ELIDE
- };
- /// Overprints the current line. If type is ELIDE, elides to_print to fit on
- /// one line.
+ enum LineType { INFO, WARNING, ERROR };
+
+ /// Outputs the given line. INFO output will be overwritten.
+ /// WARNING and ERROR appear on a line to themselves.
void Print(std::string to_print, LineType type);
- /// Prints a string on a new line, not overprinting previous output.
- void PrintOnNewLine(const std::string& to_print);
-
- /// Lock or unlock the console. Any output sent to the LinePrinter while the
- /// console is locked will not be printed until it is unlocked.
- void SetConsoleLocked(bool locked);
+ /// If there's an INFO line, keep it. If not, do nothing.
+ void KeepInfoLine();
private:
/// Whether we can do fancy terminal control codes.
@@ -48,24 +42,9 @@
/// Whether the caret is at the beginning of a blank line.
bool have_blank_line_;
- /// Whether console is locked.
- bool console_locked_;
-
- /// Buffered current line while console is locked.
- std::string line_buffer_;
-
- /// Buffered line type while console is locked.
- LineType line_type_;
-
- /// Buffered console output while console is locked.
- std::string output_buffer_;
-
#ifdef _WIN32
void* console_;
#endif
-
- /// Print the given data to the console, or buffer it if it is locked.
- void PrintOrBuffer(const char *data, size_t size);
};
#endif // NINJA_LINE_PRINTER_H_
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index 6c06669..3fc70b0 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -289,6 +289,7 @@
// TODO: $HOSTNAME? Normally bash automatically sets that, but mksh doesn't.
passwd* pw = getpwuid(getuid());
if (pw != nullptr) {
+ setenv("HOME", pw->pw_dir, 1);
setenv("LOGNAME", pw->pw_name, 1);
setenv("SHELL", pw->pw_shell, 1);
setenv("USER", pw->pw_name, 1);
@@ -297,8 +298,6 @@
setenv("TERM", terminal_type_.c_str(), 1);
}
- setenv("HOME", "/data/local/tmp", 1);
- chdir(getenv("HOME"));
if (is_interactive()) {
execl(_PATH_BSHELL, _PATH_BSHELL, "-", nullptr);
} else {
diff --git a/crash_reporter/Android.mk b/crash_reporter/Android.mk
index 81cb458..565963c 100644
--- a/crash_reporter/Android.mk
+++ b/crash_reporter/Android.mk
@@ -43,11 +43,12 @@
LOCAL_C_INCLUDES := $(crash_reporter_includes)
LOCAL_RTTI_FLAG := -frtti
LOCAL_SHARED_LIBRARIES := libchrome \
+ libbinder \
libbrillo \
libcutils \
- libdbus \
libmetrics \
libpcrecpp
+LOCAL_STATIC_LIBRARIES := libmetricscollectorservice
LOCAL_SRC_FILES := $(crash_reporter_src)
include $(BUILD_STATIC_LIBRARY)
@@ -60,18 +61,19 @@
LOCAL_REQUIRED_MODULES := core2md \
crash_reporter_logs.conf \
crash_sender \
- crash_server \
- dbus-send
+ crash_server
LOCAL_INIT_RC := crash_reporter.rc
LOCAL_RTTI_FLAG := -frtti
LOCAL_SHARED_LIBRARIES := libchrome \
+ libbinder \
libbrillo \
libcutils \
- libdbus \
libmetrics \
- libpcrecpp
+ libpcrecpp \
+ libutils
LOCAL_SRC_FILES := crash_reporter.cc
-LOCAL_STATIC_LIBRARIES := libcrash
+LOCAL_STATIC_LIBRARIES := libcrash \
+ libmetricscollectorservice
include $(BUILD_EXECUTABLE)
# Crash sender script.
@@ -140,7 +142,6 @@
LOCAL_SHARED_LIBRARIES := libchrome \
libbrillo \
libcutils \
- libdbus \
libpcrecpp
LOCAL_SRC_FILES := $(crash_reporter_test_src)
LOCAL_STATIC_LIBRARIES := libcrash libgmock
diff --git a/crash_reporter/crash_reporter.cc b/crash_reporter/crash_reporter.cc
index 3955fe5..26ffa38 100644
--- a/crash_reporter/crash_reporter.cc
+++ b/crash_reporter/crash_reporter.cc
@@ -25,10 +25,13 @@
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
+#include <binder/IServiceManager.h>
#include <brillo/flag_helper.h>
-#include <brillo/process.h>
#include <brillo/syslog_logging.h>
+#include <metrics/metrics_collector_service_client.h>
#include <metrics/metrics_library.h>
+#include <utils/String16.h>
+
#include "kernel_collector.h"
#include "kernel_warning_collector.h"
@@ -37,8 +40,6 @@
#include "user_collector.h"
static const char kCrashCounterHistogram[] = "Logging.CrashCounter";
-static const char kUserCrashSignal[] =
- "org.chromium.CrashReporter.UserCrash";
static const char kKernelCrashDetected[] = "/var/run/kernel-crash-detected";
static const char kUncleanShutdownDetected[] =
"/var/run/unclean-shutdown-detected";
@@ -56,6 +57,7 @@
static MetricsLibrary s_metrics_lib;
+using android::brillo::metrics::IMetricsCollectorService;
using base::FilePath;
using base::StringPrintf;
@@ -88,32 +90,14 @@
static void CountUserCrash() {
SendCrashMetrics(kCrashKindUser, "user");
- // Announce through D-Bus whenever a user crash happens. This is
- // used by the metrics daemon to log active use time between
- // crashes.
- //
- // We run in the background in case dbus-daemon itself is crashed
- // and not responding. This allows us to not block and potentially
- // deadlock on a dbus-daemon crash. If dbus-daemon crashes without
- // restarting, each crash will fork off a lot of dbus-send
- // processes. Such a system is in a unusable state and will need
- // to be restarted anyway.
- //
- // Note: This will mean that the dbus-send process will become a zombie and
- // reparent to init for reaping, but that's OK -- see above.
+ // Tell the metrics collector about the user crash, in order to log active
+ // use time between crashes.
+ MetricsCollectorServiceClient metrics_collector_service;
- brillo::ProcessImpl dbus_send;
- dbus_send.AddArg("/system/bin/dbus-send");
- dbus_send.AddArg("--type=signal");
- dbus_send.AddArg("--system");
- dbus_send.AddArg("/");
- dbus_send.AddArg(kUserCrashSignal);
- bool status = dbus_send.Start();
- if (status) {
- dbus_send.Release();
- } else {
- PLOG(WARNING) << "Sending UserCrash DBus signal failed";
- }
+ if (metrics_collector_service.Init())
+ metrics_collector_service.notifyUserCrash();
+ else
+ LOG(ERROR) << "Failed to send user crash notification to metrics_collector";
}
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index cc9f06c..1ab9436 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -279,6 +279,10 @@
" override the fs type and/or size\n"
" the bootloader reports.\n"
" getvar <variable> Display a bootloader variable.\n"
+ " set_active <suffix> Sets the active slot. If slots are\n"
+ " not supported, this does nothing.\n"
+ " note: suffixes starting with a '-'\n"
+ " must use set_active -- <suffix>\n"
" boot <kernel> [ <ramdisk> [ <second> ] ] Download and boot kernel.\n"
" flash:raw boot <kernel> [ <ramdisk> [ <second> ] ]\n"
" Create bootimage and flash it.\n"
@@ -321,7 +325,8 @@
" -a, --set-active[=<suffix>] Sets the active slot. If no suffix is\n"
" provided, this will default to the value\n"
" given by --slot. If slots are not\n"
- " supported, this does nothing.\n"
+ " supported, this does nothing. This will\n"
+ " run after all non-reboot commands.\n"
" --unbuffered Do not buffer input or output.\n"
" --version Display version.\n"
" -h, --help show this message.\n"
@@ -724,9 +729,19 @@
return android::base::Split(suffix_list, ",");
}
-static std::string verify_slot(Transport* transport, const char *slot) {
+static std::string verify_slot(Transport* transport, const char *slot, bool allow_all) {
if (strcmp(slot, "all") == 0) {
- return "all";
+ if (allow_all) {
+ return "all";
+ } else {
+ std::vector<std::string> suffixes = get_suffixes(transport);
+ if (!suffixes.empty()) {
+ return suffixes[0];
+ } else {
+ fprintf(stderr, "No known slots.\n");
+ exit(1);
+ }
+ }
}
std::vector<std::string> suffixes = get_suffixes(transport);
for (const std::string &suffix : suffixes) {
@@ -740,6 +755,10 @@
exit(1);
}
+static std::string verify_slot(Transport* transport, const char *slot) {
+ return verify_slot(transport, slot, true);
+}
+
static void do_for_partition(Transport* transport, const char *part, const char *slot,
std::function<void(const std::string&)> func, bool force_slot) {
std::string has_slot;
@@ -1220,14 +1239,14 @@
if (slot_override != "")
slot_override = verify_slot(transport, slot_override.c_str());
if (next_active != "")
- next_active = verify_slot(transport, next_active.c_str());
+ next_active = verify_slot(transport, next_active.c_str(), false);
if (wants_set_active) {
if (next_active == "") {
if (slot_override == "") {
wants_set_active = false;
} else {
- next_active = slot_override;
+ next_active = verify_slot(transport, slot_override.c_str(), false);
}
}
}
@@ -1385,6 +1404,12 @@
do_update(transport, "update.zip", slot_override.c_str(), erase_first);
skip(1);
}
+ wants_reboot = 1;
+ } else if(!strcmp(*argv, "set_active")) {
+ require(2);
+ std::string slot = verify_slot(transport, argv[1], false);
+ fb_set_active(slot.c_str());
+ skip(2);
wants_reboot = true;
} else if(!strcmp(*argv, "oem")) {
argc = do_oem_command(argc, argv);
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 928d56c..b5141c9 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -254,7 +254,7 @@
res = snprintf(buf, bufsize, "%s 2 " VERITY_TABLE_OPT_IGNZERO " %s", params->table,
mode_flag);
} else {
- res = strlcpy(buf, params->table, bufsize);
+ res = snprintf(buf, bufsize, "%s 1 " VERITY_TABLE_OPT_IGNZERO, params->table);
}
if (res < 0 || (size_t)res >= bufsize) {
@@ -695,31 +695,27 @@
int match = 0;
off64_t offset = 0;
+ /* unless otherwise specified, use EIO mode */
+ *mode = VERITY_MODE_EIO;
+
/* use the kernel parameter if set */
property_get("ro.boot.veritymode", propbuf, "");
if (*propbuf != '\0') {
if (!strcmp(propbuf, "enforcing")) {
*mode = VERITY_MODE_DEFAULT;
- return 0;
- } else if (!strcmp(propbuf, "logging")) {
- *mode = VERITY_MODE_LOGGING;
- return 0;
- } else {
- INFO("Unknown value %s for veritymode; ignoring", propbuf);
}
+ return 0;
}
if (get_verity_state_offset(fstab, &offset) < 0) {
/* fall back to stateless behavior */
- *mode = VERITY_MODE_EIO;
return 0;
}
if (was_verity_restart()) {
/* device was restarted after dm-verity detected a corrupted
- * block, so switch to logging mode */
- *mode = VERITY_MODE_LOGGING;
+ * block, so use EIO mode */
return write_verity_state(fstab->verity_loc, offset, *mode);
}
@@ -784,7 +780,6 @@
int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback)
{
alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
- bool use_state = true;
char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
char *mount_point;
char propbuf[PROPERTY_VALUE_MAX];
@@ -793,15 +788,11 @@
int i;
int mode;
int rc = -1;
- off64_t offset = 0;
struct dm_ioctl *io = (struct dm_ioctl *) buffer;
struct fstab *fstab = NULL;
- /* check if we need to store the state */
- property_get("ro.boot.veritymode", propbuf, "");
-
- if (*propbuf != '\0') {
- use_state = false; /* state is kept by the bootloader */
+ if (!callback) {
+ return -1;
}
if (fs_mgr_load_verity_state(&mode) == -1) {
@@ -841,16 +832,7 @@
status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
- if (use_state && *status == 'C') {
- if (write_verity_state(fstab->recs[i].verity_loc, offset,
- VERITY_MODE_LOGGING) < 0) {
- continue;
- }
- }
-
- if (callback) {
- callback(&fstab->recs[i], mount_point, mode, *status);
- }
+ callback(&fstab->recs[i], mount_point, mode, *status);
}
rc = 0;
@@ -962,13 +944,43 @@
// load the verity mapping table
if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms,
- format_verity_table) < 0 &&
- // try the legacy format for backwards compatibility
- load_verity_table(io, mount_point, verity.data_size, fd, ¶ms,
- format_legacy_verity_table) < 0) {
- goto out;
+ format_verity_table) == 0) {
+ goto loaded;
}
+ if (params.ecc.valid) {
+ // kernel may not support error correction, try without
+ INFO("Disabling error correction for %s\n", mount_point);
+ params.ecc.valid = false;
+
+ if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms,
+ format_verity_table) == 0) {
+ goto loaded;
+ }
+ }
+
+ // try the legacy format for backwards compatibility
+ if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms,
+ format_legacy_verity_table) == 0) {
+ goto loaded;
+ }
+
+ if (params.mode != VERITY_MODE_EIO) {
+ // as a last resort, EIO mode should always be supported
+ INFO("Falling back to EIO mode for %s\n", mount_point);
+ params.mode = VERITY_MODE_EIO;
+
+ if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms,
+ format_legacy_verity_table) == 0) {
+ goto loaded;
+ }
+ }
+
+ ERROR("Failed to load verity table for %s\n", mount_point);
+ goto out;
+
+loaded:
+
// activate the device
if (resume_verity_table(io, mount_point, fd) < 0) {
goto out;
diff --git a/include/log/log.h b/include/log/log.h
index 619bf23..3d9240d 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -604,7 +604,8 @@
LOG_ID_EVENTS = 2,
LOG_ID_SYSTEM = 3,
LOG_ID_CRASH = 4,
- LOG_ID_KERNEL = 5,
+ LOG_ID_SECURITY = 5,
+ LOG_ID_KERNEL = 6, /* place last, third-parties can not use it */
#endif
LOG_ID_MAX
diff --git a/include/log/logd.h b/include/log/logd.h
index 0fe515f..b7aedaf 100644
--- a/include/log/logd.h
+++ b/include/log/logd.h
@@ -44,6 +44,8 @@
size_t len);
int __android_log_bswrite(int32_t tag, const char *payload);
+int __android_log_security_bwrite(int32_t tag, const void *payload, size_t len);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/log/logger.h b/include/log/logger.h
index b3928a7..60d47a2 100644
--- a/include/log/logger.h
+++ b/include/log/logger.h
@@ -64,12 +64,24 @@
char msg[0]; /* the entry's payload */
} __attribute__((__packed__));
+struct logger_entry_v4 {
+ uint16_t len; /* length of the payload */
+ uint16_t hdr_size; /* sizeof(struct logger_entry_v4) */
+ int32_t pid; /* generating process's pid */
+ uint32_t tid; /* generating process's tid */
+ uint32_t sec; /* seconds since Epoch */
+ uint32_t nsec; /* nanoseconds */
+ uint32_t lid; /* log id of the payload, bottom 4 bits currently */
+ uint32_t uid; /* generating process's uid */
+ char msg[0]; /* the entry's payload */
+} __attribute__((__packed__));
+
/*
* The maximum size of the log entry payload that can be
* written to the logger. An attempt to write more than
* this amount will result in a truncated log entry.
*/
-#define LOGGER_ENTRY_MAX_PAYLOAD 4076
+#define LOGGER_ENTRY_MAX_PAYLOAD 4068
/*
* The maximum size of a log entry which can be read from the
@@ -83,7 +95,8 @@
struct log_msg {
union {
unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
- struct logger_entry_v3 entry;
+ struct logger_entry_v4 entry;
+ struct logger_entry_v4 entry_v4;
struct logger_entry_v3 entry_v3;
struct logger_entry_v2 entry_v2;
struct logger_entry entry_v1;
diff --git a/include/log/logprint.h b/include/log/logprint.h
index 204b3f2..539d1dc 100644
--- a/include/log/logprint.h
+++ b/include/log/logprint.h
@@ -44,6 +44,7 @@
FORMAT_MODIFIER_ZONE, /* Adds zone to date */
FORMAT_MODIFIER_EPOCH, /* Print time as seconds since Jan 1 1970 */
FORMAT_MODIFIER_MONOTONIC, /* Print cpu time as seconds since start */
+ FORMAT_MODIFIER_UID, /* Adds uid */
} AndroidLogPrintFormat;
typedef struct AndroidLogFormat_t AndroidLogFormat;
@@ -52,6 +53,7 @@
time_t tv_sec;
long tv_nsec;
android_LogPriority priority;
+ int32_t uid;
int32_t pid;
int32_t tid;
const char * tag;
diff --git a/include/nativeloader/native_loader.h b/include/nativeloader/native_loader.h
index 18b7ba4..e7c69d6 100644
--- a/include/nativeloader/native_loader.h
+++ b/include/nativeloader/native_loader.h
@@ -24,7 +24,7 @@
__attribute__((visibility("default")))
void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
- jobject class_loader, jstring library_path);
+ jobject class_loader, jstring library_path, jstring permitted_path);
}; // namespace android
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 58dbce1..10f9d81 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -642,7 +642,7 @@
static int do_verity_load_state(const std::vector<std::string>& args) {
int mode = -1;
int rc = fs_mgr_load_verity_state(&mode);
- if (rc == 0 && mode == VERITY_MODE_LOGGING) {
+ if (rc == 0 && mode != VERITY_MODE_DEFAULT) {
ActionManager::GetInstance().QueueEventTrigger("verity-logging");
}
return rc;
diff --git a/init/init.cpp b/init/init.cpp
index 9f4f625..4aef823 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -350,6 +350,18 @@
}
}
+static void export_oem_lock_status() {
+ if (property_get("ro.oem_unlock_supported") != "1") {
+ return;
+ }
+
+ std::string value = property_get("ro.boot.verifiedbootstate");
+
+ if (!value.empty()) {
+ property_set("ro.boot.flash.locked", value == "orange" ? "0" : "1");
+ }
+}
+
static void export_kernel_boot_props() {
struct {
const char *src_prop;
@@ -614,6 +626,7 @@
signal_handler_init();
property_load_boot_defaults();
+ export_oem_lock_status();
start_property_service();
const BuiltinFunctionMap function_map;
diff --git a/libbacktrace/BacktraceOffline.cpp b/libbacktrace/BacktraceOffline.cpp
index 27dfb83..abc186b 100644
--- a/libbacktrace/BacktraceOffline.cpp
+++ b/libbacktrace/BacktraceOffline.cpp
@@ -22,7 +22,9 @@
}
#include <stdint.h>
+#include <stdio.h>
#include <string.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <ucontext.h>
#include <unistd.h>
@@ -616,7 +618,30 @@
return debug_frame;
}
+static bool IsValidElfPath(const std::string& filename) {
+ static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
+
+ struct stat st;
+ if (stat(filename.c_str(), &st) != 0 || !S_ISREG(st.st_mode)) {
+ return false;
+ }
+ FILE* fp = fopen(filename.c_str(), "reb");
+ if (fp == nullptr) {
+ return false;
+ }
+ char buf[4];
+ if (fread(buf, 4, 1, fp) != 1) {
+ fclose(fp);
+ return false;
+ }
+ fclose(fp);
+ return memcmp(buf, elf_magic, 4) == 0;
+}
+
static DebugFrameInfo* ReadDebugFrameFromFile(const std::string& filename) {
+ if (!IsValidElfPath(filename)) {
+ return nullptr;
+ }
auto owning_binary = llvm::object::createBinary(llvm::StringRef(filename));
if (owning_binary.getError()) {
return nullptr;
diff --git a/liblog/log_read.c b/liblog/log_read.c
index fb86757..8aa887b 100644
--- a/liblog/log_read.c
+++ b/liblog/log_read.c
@@ -208,6 +208,7 @@
[LOG_ID_EVENTS] = "events",
[LOG_ID_SYSTEM] = "system",
[LOG_ID_CRASH] = "crash",
+ [LOG_ID_SECURITY] = "security",
[LOG_ID_KERNEL] = "kernel",
};
@@ -634,6 +635,7 @@
android_log_header_t l;
} buf;
static uint8_t preread_count;
+ bool is_system;
memset(log_msg, 0, sizeof(*log_msg));
@@ -690,12 +692,15 @@
}
uid = get_best_effective_uid();
- if (!uid_has_log_permission(uid) && (uid != buf.p.uid)) {
+ is_system = uid_has_log_permission(uid);
+ if (!is_system && (uid != buf.p.uid)) {
break;
}
ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
- log_msg->entry_v3.msg,
+ is_system ?
+ log_msg->entry_v4.msg :
+ log_msg->entry_v3.msg,
buf.p.len - sizeof(buf)));
if (ret < 0) {
return -errno;
@@ -704,13 +709,18 @@
return -EIO;
}
- log_msg->entry_v3.len = buf.p.len - sizeof(buf);
- log_msg->entry_v3.hdr_size = sizeof(log_msg->entry_v3);
- log_msg->entry_v3.pid = buf.p.pid;
- log_msg->entry_v3.tid = buf.l.tid;
- log_msg->entry_v3.sec = buf.l.realtime.tv_sec;
- log_msg->entry_v3.nsec = buf.l.realtime.tv_nsec;
- log_msg->entry_v3.lid = buf.l.id;
+ log_msg->entry_v4.len = buf.p.len - sizeof(buf);
+ log_msg->entry_v4.hdr_size = is_system ?
+ sizeof(log_msg->entry_v4) :
+ sizeof(log_msg->entry_v3);
+ log_msg->entry_v4.pid = buf.p.pid;
+ log_msg->entry_v4.tid = buf.l.tid;
+ log_msg->entry_v4.sec = buf.l.realtime.tv_sec;
+ log_msg->entry_v4.nsec = buf.l.realtime.tv_nsec;
+ log_msg->entry_v4.lid = buf.l.id;
+ if (is_system) {
+ log_msg->entry_v4.uid = buf.p.uid;
+ }
return ret;
}
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 11c6d9c..c2b0ec2 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -84,7 +84,7 @@
#endif /* !defined(_WIN32) */
#if FAKE_LOG_DEVICE
-static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 };
+static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1, -1 };
#else
static int logd_fd = -1;
static int pstore_fd = -1;
@@ -181,6 +181,7 @@
static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
static pid_t last_pid = (pid_t) -1;
static atomic_int_fast32_t dropped;
+ static atomic_int_fast32_t dropped_security;
if (!nr) {
return -EINVAL;
@@ -192,6 +193,23 @@
if (last_pid == (pid_t) -1) {
last_pid = getpid();
}
+ if (log_id == LOG_ID_SECURITY) {
+ if ((last_uid != AID_SYSTEM) && (last_uid != AID_ROOT)) {
+ uid_t uid = geteuid();
+ if ((uid != AID_SYSTEM) && (uid != AID_ROOT)) {
+ gid_t gid = getgid();
+ if ((gid != AID_SYSTEM) && (gid != AID_ROOT)) {
+ gid = getegid();
+ if ((gid != AID_SYSTEM) && (gid != AID_ROOT)) {
+ return -EPERM;
+ }
+ }
+ }
+ }
+ if (!__android_log_security()) {
+ return -EPERM;
+ }
+ }
/*
* struct {
* // what we provide to pstore
@@ -229,7 +247,26 @@
newVec[1].iov_len = sizeof(header);
if (logd_fd > 0) {
- int32_t snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
+ int32_t snapshot = atomic_exchange_explicit(&dropped_security, 0,
+ memory_order_relaxed);
+ if (snapshot) {
+ android_log_event_int_t buffer;
+
+ header.id = LOG_ID_SECURITY;
+ buffer.header.tag = htole32(LIBLOG_LOG_TAG);
+ buffer.payload.type = EVENT_TYPE_INT;
+ buffer.payload.data = htole32(snapshot);
+
+ newVec[2].iov_base = &buffer;
+ newVec[2].iov_len = sizeof(buffer);
+
+ ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
+ if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
+ atomic_fetch_add_explicit(&dropped_security, snapshot,
+ memory_order_relaxed);
+ }
+ }
+ snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
if (snapshot) {
android_log_event_int_t buffer;
@@ -243,7 +280,8 @@
ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
- atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
+ atomic_fetch_add_explicit(&dropped, snapshot,
+ memory_order_relaxed);
}
}
}
@@ -315,6 +353,10 @@
ret -= sizeof(header);
} else if (ret == -EAGAIN) {
atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
+ if (log_id == LOG_ID_SECURITY) {
+ atomic_fetch_add_explicit(&dropped_security, 1,
+ memory_order_relaxed);
+ }
}
#endif
@@ -328,6 +370,7 @@
[LOG_ID_EVENTS] = "events",
[LOG_ID_SYSTEM] = "system",
[LOG_ID_CRASH] = "crash",
+ [LOG_ID_SECURITY] = "security",
[LOG_ID_KERNEL] = "kernel",
};
@@ -483,6 +526,18 @@
return write_to_log(LOG_ID_EVENTS, vec, 2);
}
+int __android_log_security_bwrite(int32_t tag, const void *payload, size_t len)
+{
+ struct iovec vec[2];
+
+ vec[0].iov_base = &tag;
+ vec[0].iov_len = sizeof(tag);
+ vec[1].iov_base = (void*)payload;
+ vec[1].iov_len = len;
+
+ return write_to_log(LOG_ID_SECURITY, vec, 2);
+}
+
/*
* Like __android_log_bwrite, but takes the type as well. Doesn't work
* for the general case where we're generating lists of stuff, but very
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 40e13f4..746eb8a 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -32,6 +32,7 @@
#include <cutils/list.h>
#include <log/logd.h>
#include <log/logprint.h>
+#include <private/android_filesystem_config.h>
#define MS_PER_NSEC 1000000
#define US_PER_NSEC 1000
@@ -56,6 +57,7 @@
bool zone_output;
bool epoch_output;
bool monotonic_output;
+ bool uid_output;
};
/*
@@ -204,6 +206,7 @@
p_ret->zone_output = false;
p_ret->epoch_output = false;
p_ret->monotonic_output = android_log_clockid() == CLOCK_MONOTONIC;
+ p_ret->uid_output = false;
return p_ret;
}
@@ -258,6 +261,9 @@
case FORMAT_MODIFIER_MONOTONIC:
p_format->monotonic_output = true;
return 0;
+ case FORMAT_MODIFIER_UID:
+ p_format->uid_output = true;
+ return 0;
default:
break;
}
@@ -290,6 +296,7 @@
else if (strcmp(formatString, "zone") == 0) format = FORMAT_MODIFIER_ZONE;
else if (strcmp(formatString, "epoch") == 0) format = FORMAT_MODIFIER_EPOCH;
else if (strcmp(formatString, "monotonic") == 0) format = FORMAT_MODIFIER_MONOTONIC;
+ else if (strcmp(formatString, "uid") == 0) format = FORMAT_MODIFIER_UID;
else {
extern char *tzname[2];
static const char gmt[] = "GMT";
@@ -451,6 +458,7 @@
{
entry->tv_sec = buf->sec;
entry->tv_nsec = buf->nsec;
+ entry->uid = -1;
entry->pid = buf->pid;
entry->tid = buf->tid;
@@ -482,6 +490,9 @@
struct logger_entry_v2 *buf2 = (struct logger_entry_v2 *)buf;
if (buf2->hdr_size) {
msg = ((char *)buf2) + buf2->hdr_size;
+ if (buf2->hdr_size >= sizeof(struct logger_entry_v4)) {
+ entry->uid = ((struct logger_entry_v4 *)buf)->uid;
+ }
}
for (i = 1; i < buf->len; i++) {
if (msg[i] == '\0') {
@@ -734,6 +745,7 @@
entry->tv_sec = buf->sec;
entry->tv_nsec = buf->nsec;
entry->priority = ANDROID_LOG_INFO;
+ entry->uid = -1;
entry->pid = buf->pid;
entry->tid = buf->tid;
@@ -744,6 +756,9 @@
struct logger_entry_v2 *buf2 = (struct logger_entry_v2 *)buf;
if (buf2->hdr_size) {
eventData = ((unsigned char *)buf2) + buf2->hdr_size;
+ if (buf2->hdr_size >= sizeof(struct logger_entry_v4)) {
+ entry->uid = ((struct logger_entry_v4 *)buf)->uid;
+ }
}
inCount = buf->len;
if (inCount < 4)
@@ -1238,7 +1253,7 @@
char prefixBuf[128], suffixBuf[128];
char priChar;
int prefixSuffixIsHeaderFooter = 0;
- char *ret = NULL;
+ char *ret;
time_t now;
unsigned long nsec;
@@ -1310,6 +1325,30 @@
suffixLen = MIN(suffixLen, sizeof(suffixBuf));
}
+ char uid[16];
+ uid[0] = '\0';
+ if (p_format->uid_output) {
+ if (entry->uid >= 0) {
+ const struct android_id_info *info = android_ids;
+ size_t i;
+
+ for (i = 0; i < android_id_count; ++i) {
+ if (info->aid == (unsigned int)entry->uid) {
+ break;
+ }
+ ++info;
+ }
+ if ((i < android_id_count) && (strlen(info->name) <= 5)) {
+ snprintf(uid, sizeof(uid), "%5s:", info->name);
+ } else {
+ // Not worth parsing package list, names all longer than 5
+ snprintf(uid, sizeof(uid), "%5d:", entry->uid);
+ }
+ } else {
+ snprintf(uid, sizeof(uid), " ");
+ }
+ }
+
switch (p_format->format) {
case FORMAT_TAG:
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
@@ -1322,11 +1361,11 @@
" (%s)\n", entry->tag);
suffixLen += MIN(len, sizeof(suffixBuf) - suffixLen);
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%c(%5d) ", priChar, entry->pid);
+ "%c(%s%5d) ", priChar, uid, entry->pid);
break;
case FORMAT_THREAD:
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%c(%5d:%5d) ", priChar, entry->pid, entry->tid);
+ "%c(%s%5d:%5d) ", priChar, uid, entry->pid, entry->tid);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
@@ -1338,21 +1377,26 @@
break;
case FORMAT_TIME:
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%s %c/%-8s(%5d): ", timeBuf, priChar, entry->tag, entry->pid);
+ "%s %c/%-8s(%s%5d): ", timeBuf, priChar, entry->tag,
+ uid, entry->pid);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
case FORMAT_THREADTIME:
+ ret = strchr(uid, ':');
+ if (ret) {
+ *ret = ' ';
+ }
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%s %5d %5d %c %-8s: ", timeBuf,
- entry->pid, entry->tid, priChar, entry->tag);
+ "%s %s%5d %5d %c %-8s: ", timeBuf,
+ uid, entry->pid, entry->tid, priChar, entry->tag);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
case FORMAT_LONG:
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "[ %s %5d:%5d %c/%-8s ]\n",
- timeBuf, entry->pid, entry->tid, priChar, entry->tag);
+ "[ %s %s%5d:%5d %c/%-8s ]\n",
+ timeBuf, uid, entry->pid, entry->tid, priChar, entry->tag);
strcpy(suffixBuf + suffixLen, "\n\n");
suffixLen += 2;
prefixSuffixIsHeaderFooter = 1;
@@ -1360,7 +1404,7 @@
case FORMAT_BRIEF:
default:
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%c/%-8s(%5d): ", priChar, entry->tag, entry->pid);
+ "%c/%-8s(%s%5d): ", priChar, entry->tag, uid, entry->pid);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 597d8f6..621101c 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -25,6 +25,7 @@
#include <log/logger.h>
#include <log/log_read.h>
#include <log/logprint.h>
+#include <private/android_logger.h>
// enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
// non-syscall libs. Since we are only using this in the emergency of
@@ -201,6 +202,96 @@
property_set(persist_key, persist);
}
+TEST(liblog, __security_buffer) {
+ struct logger_list *logger_list;
+ android_event_long_t buffer;
+
+ static const char persist_key[] = "persist.logd.security";
+ char persist[PROP_VALUE_MAX];
+ bool set_persist = false;
+ bool allow_security = false;
+
+ if (__android_log_security()) {
+ allow_security = true;
+ } else {
+ property_get(persist_key, persist, "");
+ if (strcasecmp(persist, "true")) {
+ property_set(persist_key, "TRUE");
+ if (__android_log_security()) {
+ allow_security = true;
+ set_persist = true;
+ } else {
+ property_set(persist_key, persist);
+ }
+ }
+ }
+
+ if (!allow_security) {
+ fprintf(stderr, "WARNING: "
+ "security buffer disabled, bypassing end-to-end test\n");
+
+ log_time ts(CLOCK_MONOTONIC);
+
+ buffer.type = EVENT_TYPE_LONG;
+ buffer.data = *(static_cast<uint64_t *>((void *)&ts));
+
+ // expect failure!
+ ASSERT_GE(0, __android_log_security_bwrite(0, &buffer, sizeof(buffer)));
+
+ return;
+ }
+
+ pid_t pid = getpid();
+
+ ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
+ LOG_ID_SECURITY, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
+ 1000, pid)));
+
+ log_time ts(CLOCK_MONOTONIC);
+
+ buffer.type = EVENT_TYPE_LONG;
+ buffer.data = *(static_cast<uint64_t *>((void *)&ts));
+
+ ASSERT_LT(0, __android_log_security_bwrite(0, &buffer, sizeof(buffer)));
+ usleep(1000000);
+
+ int count = 0;
+
+ for (;;) {
+ log_msg log_msg;
+ if (android_logger_list_read(logger_list, &log_msg) <= 0) {
+ break;
+ }
+
+ ASSERT_EQ(log_msg.entry.pid, pid);
+
+ if ((log_msg.entry.len != (4 + 1 + 8))
+ || (log_msg.id() != LOG_ID_SECURITY)) {
+ continue;
+ }
+
+ char *eventData = log_msg.msg();
+
+ if (eventData[4] != EVENT_TYPE_LONG) {
+ continue;
+ }
+
+ log_time tx(eventData + 4 + 1);
+ if (ts == tx) {
+ ++count;
+ }
+ }
+
+ if (set_persist) {
+ property_set(persist_key, persist);
+ }
+
+ android_logger_list_close(logger_list);
+
+ EXPECT_EQ(1, count);
+
+}
+
static unsigned signaled;
log_time signal_time;
@@ -342,8 +433,9 @@
}
static const char max_payload_tag[] = "TEST_max_payload_XXXX";
-static const char max_payload_buf[LOGGER_ENTRY_MAX_PAYLOAD
- - sizeof(max_payload_tag) - 1] = "LEONATO\n\
+#define SIZEOF_MAX_PAYLOAD_BUF (LOGGER_ENTRY_MAX_PAYLOAD - \
+ sizeof(max_payload_tag) - 1)
+static const char max_payload_buf[] = "LEONATO\n\
I learn in this letter that Don Peter of Arragon\n\
comes this night to Messina\n\
MESSENGER\n\
@@ -469,7 +561,7 @@
trouble: the fashion of the world is to avoid\n\
cost, and you encounter it\n\
LEONATO\n\
-Never came trouble to my house in the likeness";
+Never came trouble to my house in the likeness of your grace";
TEST(liblog, max_payload) {
pid_t pid = getpid();
@@ -528,7 +620,7 @@
EXPECT_EQ(true, matches);
- EXPECT_LE(sizeof(max_payload_buf), static_cast<size_t>(max_len));
+ EXPECT_LE(SIZEOF_MAX_PAYLOAD_BUF, static_cast<size_t>(max_len));
}
TEST(liblog, too_big_payload) {
@@ -650,7 +742,8 @@
EXPECT_EQ(id, android_logger_get_id(logger));
EXPECT_LT(0, android_logger_get_log_size(logger));
/* crash buffer is allowed to be empty, that is actually healthy! */
- if (android_logger_get_log_readable_size(logger) || strcmp("crash", name)) {
+ if (android_logger_get_log_readable_size(logger) ||
+ (strcmp("crash", name) && strcmp("security", name))) {
EXPECT_LT(0, android_logger_get_log_readable_size(logger));
}
EXPECT_LT(0, android_logger_get_log_version(logger));
@@ -1005,7 +1098,7 @@
const int TAG = 123456782;
const char SUBTAG[] = "test-subtag";
const int UID = -1;
- const int DATA_LEN = sizeof(max_payload_buf);
+ const int DATA_LEN = SIZEOF_MAX_PAYLOAD_BUF;
struct logger_list *logger_list;
pid_t pid = getpid();
@@ -1076,8 +1169,8 @@
}
eventData += dataLen;
- // 4 bytes for the tag, and 512 bytes for the log since the max_payload_buf should be
- // truncated.
+ // 4 bytes for the tag, and 512 bytes for the log since the
+ // max_payload_buf should be truncated.
ASSERT_EQ(4 + 512, eventData - original);
++count;
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 654bcb8..cef2d75 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -55,10 +55,18 @@
public:
LibraryNamespaces() : initialized_(false) { }
- android_namespace_t* GetOrCreate(JNIEnv* env, jobject class_loader, jstring library_path) {
- ScopedUtfChars libraryPath(env, library_path);
+ android_namespace_t* GetOrCreate(JNIEnv* env, jobject class_loader,
+ jstring java_library_path,
+ jstring java_permitted_path) {
+ ScopedUtfChars library_path(env, java_library_path);
- if (!initialized_ && !InitPublicNamespace(libraryPath.c_str())) {
+ std::string permitted_path;
+ if (java_permitted_path != nullptr) {
+ ScopedUtfChars path(env, java_permitted_path);
+ permitted_path = path.c_str();
+ }
+
+ if (!initialized_ && !InitPublicNamespace(library_path.c_str())) {
return nullptr;
}
@@ -73,8 +81,11 @@
android_namespace_t* ns =
android_create_namespace("classloader-namespace",
nullptr,
- libraryPath.c_str(),
- true);
+ library_path.c_str(),
+ true,
+ java_permitted_path != nullptr ?
+ permitted_path.c_str() :
+ nullptr);
namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), ns));
@@ -118,13 +129,16 @@
void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
- jobject class_loader, jstring library_path) {
+ jobject class_loader, jstring java_library_path,
+ jstring java_permitted_path) {
#if defined(__ANDROID__)
if (target_sdk_version == 0 || class_loader == nullptr) {
return dlopen(path, RTLD_NOW);
}
- android_namespace_t* ns = g_namespaces->GetOrCreate(env, class_loader, library_path);
+ android_namespace_t* ns =
+ g_namespaces->GetOrCreate(env, class_loader, java_library_path,
+ java_permitted_path);
if (ns == nullptr) {
return nullptr;
@@ -136,7 +150,8 @@
return android_dlopen_ext(path, RTLD_NOW, &extinfo);
#else
- UNUSED(env, target_sdk_version, class_loader, library_path);
+ UNUSED(env, target_sdk_version, class_loader,
+ java_library_path, java_permitted_path);
return dlopen(path, RTLD_NOW);
#endif
}
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 059916e..ddc91ca 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -265,7 +265,7 @@
" -v <format> Sets the log print format, where <format> is:\n"
" --format=<format>\n"
" brief color epoch long monotonic printable process raw\n"
- " tag thread threadtime time usec UTC year zone\n\n"
+ " tag thread threadtime time uid usec UTC year zone\n\n"
" -D print dividers between each log buffer\n"
" --dividers\n"
" -c clear (flush) the entire log and exit\n"
@@ -283,10 +283,12 @@
" --buffer_size=<size>\n"
" -L dump logs from prior to last reboot\n"
" --last\n"
+ // Leave security (Device Owner only installations) and
+ // kernel (userdebug and eng) buffers undocumented.
" -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',\n"
- " --buffer=<buffer> 'events', 'crash' or 'all'. Multiple -b parameters are\n"
- " allowed and results are interleaved. The default is\n"
- " -b main -b system -b crash.\n"
+ " --buffer=<buffer> 'events', 'crash', 'default' or 'all'. Multiple -b\n"
+ " parameters are allowed and results are interleaved. The\n"
+ " default is -b main -b system -b crash.\n"
" -B output the log in binary.\n"
" --binary\n"
" -S output statistics.\n"
@@ -696,16 +698,20 @@
break;
case 'b': {
- if (strcmp(optarg, "all") == 0) {
- while (devices) {
- dev = devices;
- devices = dev->next;
- delete dev;
- }
+ if (strcmp(optarg, "default") == 0) {
+ for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
+ switch (i) {
+ case LOG_ID_SECURITY:
+ case LOG_ID_EVENTS:
+ continue;
+ case LOG_ID_MAIN:
+ case LOG_ID_SYSTEM:
+ case LOG_ID_CRASH:
+ break;
+ default:
+ continue;
+ }
- devices = dev = NULL;
- g_devCount = 0;
- for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
const char *name = android_log_id_to_name((log_id_t)i);
log_id_t log_id = android_name_to_log_id(name);
@@ -713,7 +719,58 @@
continue;
}
- bool binary = strcmp(name, "events") == 0;
+ bool found = false;
+ for (dev = devices; dev; dev = dev->next) {
+ if (!strcmp(optarg, dev->device)) {
+ found = true;
+ break;
+ }
+ if (!dev->next) {
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+
+ log_device_t* d = new log_device_t(name, false);
+
+ if (dev) {
+ dev->next = d;
+ dev = d;
+ } else {
+ devices = dev = d;
+ }
+ g_devCount++;
+ }
+ break;
+ }
+
+ if (strcmp(optarg, "all") == 0) {
+ for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
+ const char *name = android_log_id_to_name((log_id_t)i);
+ log_id_t log_id = android_name_to_log_id(name);
+
+ if (log_id != (log_id_t)i) {
+ continue;
+ }
+
+ bool found = false;
+ for (dev = devices; dev; dev = dev->next) {
+ if (!strcmp(optarg, dev->device)) {
+ found = true;
+ break;
+ }
+ if (!dev->next) {
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+
+ bool binary = !strcmp(name, "events") ||
+ !strcmp(name, "security");
log_device_t* d = new log_device_t(name, binary);
if (dev) {
@@ -727,14 +784,21 @@
break;
}
- bool binary = strcmp(optarg, "events") == 0;
+ bool binary = !(strcmp(optarg, "events") &&
+ strcmp(optarg, "security"));
if (devices) {
dev = devices;
while (dev->next) {
+ if (!strcmp(optarg, dev->device)) {
+ dev = NULL;
+ break;
+ }
dev = dev->next;
}
- dev->next = new log_device_t(optarg, binary);
+ if (dev) {
+ dev->next = new log_device_t(optarg, binary);
+ }
} else {
devices = new log_device_t(optarg, binary);
}
@@ -1004,7 +1068,7 @@
size_t len = 8192;
char *buf;
- for(int retry = 32;
+ for (int retry = 32;
(retry >= 0) && ((buf = new char [len]));
delete [] buf, buf = NULL, --retry) {
if (getPruneList) {
@@ -1094,7 +1158,7 @@
logcat_panic(false, "logcat read failure");
}
- for(d = devices; d; d = d->next) {
+ for (d = devices; d; d = d->next) {
if (android_name_to_log_id(d->device) == log_msg.id()) {
break;
}
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
index c45111a..e103359 100644
--- a/logd/CommandListener.cpp
+++ b/logd/CommandListener.cpp
@@ -34,6 +34,7 @@
#include "CommandListener.h"
#include "LogCommand.h"
+#include "LogUtils.h"
CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/,
LogListener * /*swl*/) :
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index bf650cd..cb3d1c2 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -21,6 +21,7 @@
#include "LogCommand.h"
#include "LogReader.h"
#include "LogTimes.h"
+#include "LogUtils.h"
FlushCommand::FlushCommand(LogReader &reader,
bool nonBlock,
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 6770bb7..1e4f3b0 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -199,22 +199,24 @@
LogBufferElement *elem = new LogBufferElement(log_id, realtime,
uid, pid, tid, msg, len);
- int prio = ANDROID_LOG_INFO;
- const char *tag = NULL;
- if (log_id == LOG_ID_EVENTS) {
- tag = android::tagToName(elem->getTag());
- } else {
- prio = *msg;
- tag = msg + 1;
- }
- if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
- // Log traffic received to total
- pthread_mutex_lock(&mLogElementsLock);
- stats.add(elem);
- stats.subtract(elem);
- pthread_mutex_unlock(&mLogElementsLock);
- delete elem;
- return -EACCES;
+ if (log_id != LOG_ID_SECURITY) {
+ int prio = ANDROID_LOG_INFO;
+ const char *tag = NULL;
+ if (log_id == LOG_ID_EVENTS) {
+ tag = android::tagToName(elem->getTag());
+ } else {
+ prio = *msg;
+ tag = msg + 1;
+ }
+ if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
+ // Log traffic received to total
+ pthread_mutex_lock(&mLogElementsLock);
+ stats.add(elem);
+ stats.subtract(elem);
+ pthread_mutex_unlock(&mLogElementsLock);
+ delete elem;
+ return -EACCES;
+ }
}
pthread_mutex_lock(&mLogElementsLock);
@@ -484,7 +486,7 @@
}
// prune by worst offender by uid
- bool hasBlacklist = mPrune.naughty();
+ bool hasBlacklist = (id != LOG_ID_SECURITY) && mPrune.naughty();
while (!clearAll && (pruneRows > 0)) {
// recalculate the worst offender on every batched pass
uid_t worst = (uid_t) -1;
@@ -654,7 +656,7 @@
}
bool whitelist = false;
- bool hasWhitelist = mPrune.nice() && !clearAll;
+ bool hasWhitelist = (id != LOG_ID_SECURITY) && mPrune.nice() && !clearAll;
it = mLogElements.begin();
while((pruneRows > 0) && (it != mLogElements.end())) {
LogBufferElement *e = *it;
@@ -846,7 +848,7 @@
pthread_mutex_unlock(&mLogElementsLock);
// range locking in LastLogTimes looks after us
- max = element->flushTo(reader, this);
+ max = element->flushTo(reader, this, privileged);
if (max == element->FLUSH_ERROR) {
return max;
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index c4c302b..fde9ad7 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -51,7 +51,8 @@
}
uint32_t LogBufferElement::getTag() const {
- if ((mLogId != LOG_ID_EVENTS) || !mMsg || (mMsgLen < sizeof(uint32_t))) {
+ if (((mLogId != LOG_ID_EVENTS) && (mLogId != LOG_ID_SECURITY)) ||
+ !mMsg || (mMsgLen < sizeof(uint32_t))) {
return 0;
}
return le32toh(reinterpret_cast<android_event_header_t *>(mMsg)->tag);
@@ -158,7 +159,9 @@
mDropped, (mDropped > 1) ? "s" : "");
size_t hdrLen;
- if (mLogId == LOG_ID_EVENTS) {
+ // LOG_ID_SECURITY not strictly needed since spam filter not activated,
+ // but required for accuracy.
+ if ((mLogId == LOG_ID_EVENTS) || (mLogId == LOG_ID_SECURITY)) {
hdrLen = sizeof(android_log_event_string_t);
} else {
hdrLen = 1 + sizeof(tag);
@@ -172,7 +175,7 @@
}
size_t retval = hdrLen + len;
- if (mLogId == LOG_ID_EVENTS) {
+ if ((mLogId == LOG_ID_EVENTS) || (mLogId == LOG_ID_SECURITY)) {
android_log_event_string_t *event =
reinterpret_cast<android_log_event_string_t *>(buffer);
@@ -194,21 +197,25 @@
return retval;
}
-uint64_t LogBufferElement::flushTo(SocketClient *reader, LogBuffer *parent) {
- struct logger_entry_v3 entry;
+uint64_t LogBufferElement::flushTo(SocketClient *reader, LogBuffer *parent,
+ bool privileged) {
+ struct logger_entry_v4 entry;
- memset(&entry, 0, sizeof(struct logger_entry_v3));
+ memset(&entry, 0, sizeof(struct logger_entry_v4));
- entry.hdr_size = sizeof(struct logger_entry_v3);
+ entry.hdr_size = privileged ?
+ sizeof(struct logger_entry_v4) :
+ sizeof(struct logger_entry_v3);
entry.lid = mLogId;
entry.pid = mPid;
entry.tid = mTid;
+ entry.uid = mUid;
entry.sec = mRealTime.tv_sec;
entry.nsec = mRealTime.tv_nsec;
struct iovec iovec[2];
iovec[0].iov_base = &entry;
- iovec[0].iov_len = sizeof(struct logger_entry_v3);
+ iovec[0].iov_len = entry.hdr_size;
char *buffer = NULL;
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index 09987ea..e7f88b9 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -80,7 +80,7 @@
uint32_t getTag(void) const;
static const uint64_t FLUSH_ERROR;
- uint64_t flushTo(SocketClient *writer, LogBuffer *parent);
+ uint64_t flushTo(SocketClient *writer, LogBuffer *parent, bool privileged);
};
#endif
diff --git a/logd/LogCommand.cpp b/logd/LogCommand.cpp
index 6d0e92e..3b17576 100644
--- a/logd/LogCommand.cpp
+++ b/logd/LogCommand.cpp
@@ -22,6 +22,7 @@
#include <private/android_filesystem_config.h>
#include "LogCommand.h"
+#include "LogUtils.h"
LogCommand::LogCommand(const char *cmd) : FrameworkCommand(cmd) {
}
@@ -56,20 +57,18 @@
return false;
}
-bool clientHasLogCredentials(SocketClient * cli) {
- uid_t uid = cli->getUid();
- if (uid == AID_ROOT) {
+bool clientHasLogCredentials(uid_t uid, gid_t gid, pid_t pid) {
+ if ((uid == AID_ROOT) || (uid == AID_SYSTEM) || (uid == AID_LOG)) {
return true;
}
- gid_t gid = cli->getGid();
if ((gid == AID_ROOT) || (gid == AID_SYSTEM) || (gid == AID_LOG)) {
return true;
}
// FYI We will typically be here for 'adb logcat'
char filename[256];
- snprintf(filename, sizeof(filename), "/proc/%u/status", cli->getPid());
+ snprintf(filename, sizeof(filename), "/proc/%u/status", pid);
bool ret;
bool foundLog = false;
@@ -145,3 +144,7 @@
return ret;
}
+
+bool clientHasLogCredentials(SocketClient *cli) {
+ return clientHasLogCredentials(cli->getUid(), cli->getGid(), cli->getPid());
+}
diff --git a/logd/LogCommand.h b/logd/LogCommand.h
index e3b96a2..c944478 100644
--- a/logd/LogCommand.h
+++ b/logd/LogCommand.h
@@ -26,6 +26,4 @@
virtual ~LogCommand() {}
};
-bool clientHasLogCredentials(SocketClient * cli);
-
#endif
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index 2a3f52f..db7e682 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -778,6 +778,31 @@
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
+ static uint32_t vote_time[3];
+ vote_time[2] = vote_time[1];
+ vote_time[1] = vote_time[0];
+ vote_time[0] = now.tv_sec;
+
+ if (vote_time[1] && vote_time[2]) {
+ static const unsigned near_seconds = 10;
+ static const unsigned timezones_seconds = 900;
+ int diff0 = (vote_time[0] - vote_time[1]) / near_seconds;
+ unsigned abs0 = (diff0 < 0) ? -diff0 : diff0;
+ int diff1 = (vote_time[1] - vote_time[2]) / near_seconds;
+ unsigned abs1 = (diff1 < 0) ? -diff1 : diff1;
+ if ((abs1 <= 1) && // last two were in agreement on timezone
+ ((abs0 + 1) % (timezones_seconds / near_seconds)) <= 2) {
+ abs0 = (abs0 + 1) / (timezones_seconds / near_seconds) *
+ timezones_seconds;
+ now.tv_sec -= (diff0 < 0) ? -abs0 : abs0;
+ }
+ }
+ }
+
// Log message
int rc = logbuf->log(LOG_ID_KERNEL, now, uid, pid, tid, newstr,
(unsigned short) n);
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index b29f5ab..9bbf9e8 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -27,6 +27,7 @@
#include <private/android_logger.h>
#include "LogListener.h"
+#include "LogUtils.h"
LogListener::LogListener(LogBuffer *buf, LogReader *reader) :
SocketListener(getLogSocket(), false),
@@ -92,6 +93,12 @@
return false;
}
+ if ((header->id == LOG_ID_SECURITY) &&
+ (!__android_log_security() ||
+ !clientHasLogCredentials(cred->uid, cred->gid, cred->pid))) {
+ return false;
+ }
+
char *msg = ((char *)buffer) + sizeof(android_log_header_t);
n -= sizeof(android_log_header_t);
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 416edd8..bf0e30b 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -85,7 +85,11 @@
uint32_t tag = element->getTag();
if (tag) {
- tagTable.add(tag, element);
+ if (log_id == LOG_ID_SECURITY) {
+ securityTagTable.add(tag, element);
+ } else {
+ tagTable.add(tag, element);
+ }
}
}
@@ -113,7 +117,11 @@
uint32_t tag = element->getTag();
if (tag) {
- tagTable.subtract(tag, element);
+ if (log_id == LOG_ID_SECURITY) {
+ securityTagTable.subtract(tag, element);
+ } else {
+ tagTable.subtract(tag, element);
+ }
}
}
@@ -468,6 +476,11 @@
output += tagTable.format(*this, uid, name, LOG_ID_EVENTS);
}
+ if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
+ name = "Chattiest security log buffer TAGs:";
+ output += securityTagTable.format(*this, uid, name, LOG_ID_SECURITY);
+ }
+
return output;
}
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 28810d9..8558b06 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -397,6 +397,9 @@
typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
tagTable_t tagTable;
+ // security tag list
+ tagTable_t securityTagTable;
+
public:
LogStatistics();
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index 533eb1c..b591f28 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include <log/log.h>
+#include <sysutils/SocketClient.h>
// Hijack this header as a common include file used by most all sources
// to report some utilities defined here and there.
@@ -38,8 +39,12 @@
}
+// Furnished in LogCommand.cpp
+bool clientHasLogCredentials(uid_t uid, gid_t gid, pid_t pid);
+bool clientHasLogCredentials(SocketClient *cli);
+
static inline bool worstUidEnabledForLogid(log_id_t id) {
- return (id != LOG_ID_CRASH) && (id != LOG_ID_KERNEL) && (id != LOG_ID_EVENTS);
+ return (id == LOG_ID_MAIN) || (id == LOG_ID_SYSTEM) || (id == LOG_ID_RADIO);
}
template <int (*cmp)(const char *l, const char *r, const size_t s)>
diff --git a/logd/main.cpp b/logd/main.cpp
index 8e75b37..0f55d60 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -349,7 +349,7 @@
memset(&p, 0, sizeof(p));
p.fd = sock;
p.events = POLLIN;
- ret = TEMP_FAILURE_RETRY(poll(&p, 1, 100));
+ ret = TEMP_FAILURE_RETRY(poll(&p, 1, 1000));
if (ret < 0) {
return -errno;
}
diff --git a/metricsd/Android.mk b/metricsd/Android.mk
index 839ab65..2149a4b 100644
--- a/metricsd/Android.mk
+++ b/metricsd/Android.mk
@@ -28,6 +28,7 @@
collectors/cpu_usage_collector.cc \
collectors/disk_usage_collector.cc \
metrics_collector.cc \
+ metrics_collector_service_trampoline.cc \
persistent_integer.cc
metricsd_common := \
@@ -69,6 +70,7 @@
$(LOCAL_PATH)/include
libmetrics_shared_libraries := libchrome libbinder libbrillo libutils
metrics_collector_shared_libraries := $(libmetrics_shared_libraries) \
+ libbrillo-binder \
libbrillo-dbus \
libbrillo-http \
libchrome-dbus \
@@ -77,6 +79,8 @@
librootdev \
libweaved
+metrics_collector_static_libraries := libmetricscollectorservice
+
metricsd_shared_libraries := \
libbinder \
libbrillo \
@@ -86,7 +90,7 @@
libupdate_engine_client \
libutils
-# Static proxy library for the binder interface.
+# Static proxy library for the metricsd binder interface.
# ========================================================
include $(CLEAR_VARS)
LOCAL_MODULE := metricsd_binder_proxy
@@ -94,6 +98,21 @@
LOCAL_SRC_FILES := aidl/android/brillo/metrics/IMetricsd.aidl
include $(BUILD_STATIC_LIBRARY)
+# Static library for the metrics_collector binder interface.
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libmetricscollectorservice
+LOCAL_SHARED_LIBRARIES := libbinder libbrillo-binder libchrome libutils
+LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_SRC_FILES := \
+ aidl/android/brillo/metrics/IMetricsCollectorService.aidl \
+ metrics_collector_service_impl.cc \
+ metrics_collector_service_client.cc
+LOCAL_RTTI_FLAG := -fno-rtti
+include $(BUILD_STATIC_LIBRARY)
+
# Shared library for metrics.
# ========================================================
include $(CLEAR_VARS)
@@ -146,14 +165,13 @@
LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
LOCAL_INIT_RC := metrics_collector.rc
-LOCAL_REQUIRED_MODULES := \
- metrics.json \
- metrics.schema.json
+LOCAL_REQUIRED_MODULES := metrics.json
LOCAL_RTTI_FLAG := -frtti
LOCAL_SHARED_LIBRARIES := $(metrics_collector_shared_libraries)
LOCAL_SRC_FILES := $(metrics_collector_common) \
metrics_collector_main.cc
-LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy
+LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy \
+ $(metrics_collector_static_libraries)
include $(BUILD_EXECUTABLE)
# metricsd daemon.
@@ -199,7 +217,8 @@
LOCAL_SHARED_LIBRARIES := $(metrics_collector_shared_libraries)
LOCAL_SRC_FILES := $(metrics_collector_tests_sources) \
$(metrics_collector_common)
-LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_binder_proxy
+LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_binder_proxy \
+ $(metrics_collector_static_libraries)
include $(BUILD_NATIVE_TEST)
# Weave schema files
@@ -207,13 +226,6 @@
include $(CLEAR_VARS)
LOCAL_MODULE := metrics.json
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/weaved/commands
-LOCAL_SRC_FILES := etc/weaved/commands/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := metrics.schema.json
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/weaved/states
-LOCAL_SRC_FILES := etc/weaved/states/$(LOCAL_MODULE)
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/weaved/traits
+LOCAL_SRC_FILES := etc/weaved/traits/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
diff --git a/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl b/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl
new file mode 100644
index 0000000..49f484f
--- /dev/null
+++ b/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+package android.brillo.metrics;
+
+interface IMetricsCollectorService {
+ oneway void notifyUserCrash();
+}
diff --git a/metricsd/etc/weaved/commands/metrics.json b/metricsd/etc/weaved/commands/metrics.json
deleted file mode 100644
index b7f32d5..0000000
--- a/metricsd/etc/weaved/commands/metrics.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "_metrics": {
- "_enableAnalyticsReporting": {
- "minimalRole": "manager"
- },
- "_disableAnalyticsReporting": {
- "minimalRole": "manager"
- }
- }
-}
diff --git a/metricsd/etc/weaved/states/metrics.schema.json b/metricsd/etc/weaved/states/metrics.schema.json
deleted file mode 100644
index 130ac46..0000000
--- a/metricsd/etc/weaved/states/metrics.schema.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "_metrics": {
- "_AnalyticsReportingState": {
- "enum": ["enabled", "disabled"],
- "default": "disabled"
- }
- }
-}
diff --git a/metricsd/etc/weaved/traits/metrics.json b/metricsd/etc/weaved/traits/metrics.json
new file mode 100644
index 0000000..7d17c77
--- /dev/null
+++ b/metricsd/etc/weaved/traits/metrics.json
@@ -0,0 +1,18 @@
+{
+ "_metrics": {
+ "commands": {
+ "_enableAnalyticsReporting": {
+ "minimalRole": "manager"
+ },
+ "_disableAnalyticsReporting": {
+ "minimalRole": "manager"
+ }
+ },
+ "state": {
+ "_AnalyticsReportingState": {
+ "type": "string",
+ "enum": [ "enabled", "disabled" ]
+ }
+ }
+ }
+}
diff --git a/metricsd/include/metrics/metrics_collector_service_client.h b/metricsd/include/metrics/metrics_collector_service_client.h
new file mode 100644
index 0000000..c800eae
--- /dev/null
+++ b/metricsd/include/metrics/metrics_collector_service_client.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+// Client interface to IMetricsCollectorService.
+
+#ifndef METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
+#define METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
+
+#include "android/brillo/metrics/IMetricsCollectorService.h"
+
+class MetricsCollectorServiceClient {
+ public:
+ MetricsCollectorServiceClient() = default;
+ ~MetricsCollectorServiceClient() = default;
+
+ // Initialize. Returns true if OK, or false if IMetricsCollectorService
+ // is not registered.
+ bool Init();
+
+ // Called by crash_reporter to report a userspace crash event. Returns
+ // true if successfully called the IMetricsCollectorService method of the
+ // same name, or false if the service was not registered at Init() time.
+ bool notifyUserCrash();
+
+ private:
+ // IMetricsCollectorService binder proxy
+ android::sp<android::brillo::metrics::IMetricsCollectorService>
+ metrics_collector_service_;
+};
+
+#endif // METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
diff --git a/metricsd/metrics_collector.cc b/metricsd/metrics_collector.cc
index 28f9ad3..b5c2289 100644
--- a/metricsd/metrics_collector.cc
+++ b/metricsd/metrics_collector.cc
@@ -33,6 +33,7 @@
#include <dbus/message.h>
#include "constants.h"
+#include "metrics_collector_service_trampoline.h"
using base::FilePath;
using base::StringPrintf;
@@ -40,19 +41,12 @@
using base::TimeDelta;
using base::TimeTicks;
using chromeos_metrics::PersistentInteger;
-using com::android::Weave::CommandProxy;
-using com::android::Weave::ManagerProxy;
using std::map;
using std::string;
using std::vector;
namespace {
-const char kCrashReporterInterface[] = "org.chromium.CrashReporter";
-const char kCrashReporterUserCrashSignal[] = "UserCrash";
-const char kCrashReporterMatchRule[] =
- "type='signal',interface='%s',path='/',member='%s'";
-
const int kSecondsPerMinute = 60;
const int kMinutesPerHour = 60;
const int kHoursPerDay = 24;
@@ -73,6 +67,8 @@
const char kMeminfoFileName[] = "/proc/meminfo";
const char kVmStatFileName[] = "/proc/vmstat";
+const char kWeaveComponent[] = "metrics";
+
} // namespace
// Zram sysfs entries.
@@ -130,6 +126,10 @@
version_cumulative_cpu_use_->Set(0);
}
+ // Start metricscollectorservice via trampoline
+ MetricsCollectorServiceTrampoline metricscollectorservice_trampoline(this);
+ metricscollectorservice_trampoline.Run();
+
return brillo::DBusDaemon::Run();
}
@@ -223,35 +223,16 @@
bus_->AssertOnDBusThread();
CHECK(bus_->SetUpAsyncOperations());
- if (bus_->is_connected()) {
- const std::string match_rule =
- base::StringPrintf(kCrashReporterMatchRule,
- kCrashReporterInterface,
- kCrashReporterUserCrashSignal);
-
- bus_->AddFilterFunction(&MetricsCollector::MessageFilter, this);
-
- DBusError error;
- dbus_error_init(&error);
- bus_->AddMatch(match_rule, &error);
-
- if (dbus_error_is_set(&error)) {
- LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got "
- << error.name << ": " << error.message;
- return EX_SOFTWARE;
- }
- } else {
- LOG(ERROR) << "DBus isn't connected.";
- return EX_UNAVAILABLE;
- }
-
device_ = weaved::Device::CreateInstance(
bus_,
base::Bind(&MetricsCollector::UpdateWeaveState, base::Unretained(this)));
+ device_->AddComponent(kWeaveComponent, {"_metrics"});
device_->AddCommandHandler(
+ kWeaveComponent,
"_metrics._enableAnalyticsReporting",
base::Bind(&MetricsCollector::OnEnableMetrics, base::Unretained(this)));
device_->AddCommandHandler(
+ kWeaveComponent,
"_metrics._disableAnalyticsReporting",
base::Bind(&MetricsCollector::OnDisableMetrics, base::Unretained(this)));
@@ -265,23 +246,6 @@
}
void MetricsCollector::OnShutdown(int* return_code) {
- if (!testing_ && bus_->is_connected()) {
- const std::string match_rule =
- base::StringPrintf(kCrashReporterMatchRule,
- kCrashReporterInterface,
- kCrashReporterUserCrashSignal);
-
- bus_->RemoveFilterFunction(&MetricsCollector::MessageFilter, this);
-
- DBusError error;
- dbus_error_init(&error);
- bus_->RemoveMatch(match_rule, &error);
-
- if (dbus_error_is_set(&error)) {
- LOG(ERROR) << "Failed to remove match rule \"" << match_rule << "\". Got "
- << error.name << ": " << error.message;
- }
- }
brillo::DBusDaemon::OnShutdown(return_code);
}
@@ -326,46 +290,17 @@
if (!device_)
return;
- brillo::VariantDictionary state_change{
- { "_metrics._AnalyticsReportingState",
- metrics_lib_->AreMetricsEnabled() ? "enabled" : "disabled" }
- };
+ std::string enabled =
+ metrics_lib_->AreMetricsEnabled() ? "enabled" : "disabled";
- if (!device_->SetStateProperties(state_change, nullptr)) {
+ if (!device_->SetStateProperty(kWeaveComponent,
+ "_metrics._AnalyticsReportingState",
+ enabled,
+ nullptr)) {
LOG(ERROR) << "failed to update weave's state";
}
}
-// static
-DBusHandlerResult MetricsCollector::MessageFilter(DBusConnection* connection,
- DBusMessage* message,
- void* user_data) {
- int message_type = dbus_message_get_type(message);
- if (message_type != DBUS_MESSAGE_TYPE_SIGNAL) {
- DLOG(WARNING) << "unexpected message type " << message_type;
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
-
- // Signal messages always have interfaces.
- const std::string interface(dbus_message_get_interface(message));
- const std::string member(dbus_message_get_member(message));
- DLOG(INFO) << "Got " << interface << "." << member << " D-Bus signal";
-
- MetricsCollector* daemon = static_cast<MetricsCollector*>(user_data);
-
- DBusMessageIter iter;
- dbus_message_iter_init(message, &iter);
- if (interface == kCrashReporterInterface) {
- CHECK_EQ(member, kCrashReporterUserCrashSignal);
- daemon->ProcessUserCrash();
- } else {
- // Ignore messages from the bus itself.
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
void MetricsCollector::ProcessUserCrash() {
// Counts the active time up to now.
UpdateStats(TimeTicks::Now(), Time::Now());
diff --git a/metricsd/metrics_collector.h b/metricsd/metrics_collector.h
index 69747d0..422ed7c 100644
--- a/metricsd/metrics_collector.h
+++ b/metricsd/metrics_collector.h
@@ -63,6 +63,10 @@
// Returns the active time since boot (uptime minus sleep time) in seconds.
static double GetActiveTime();
+ // Updates the active use time and logs time between user-space
+ // process crashes. Called via MetricsCollectorServiceTrampoline.
+ void ProcessUserCrash();
+
protected:
// Used also by the unit tests.
static const char kComprDataSizeName[];
@@ -108,11 +112,6 @@
int value; // value from /proc/meminfo
};
- // D-Bus filter callback.
- static DBusHandlerResult MessageFilter(DBusConnection* connection,
- DBusMessage* message,
- void* user_data);
-
// Enables metrics reporting.
void OnEnableMetrics(const std::weak_ptr<weaved::Command>& cmd);
@@ -122,10 +121,6 @@
// Updates the weave device state.
void UpdateWeaveState();
- // Updates the active use time and logs time between user-space
- // process crashes.
- void ProcessUserCrash();
-
// Updates the active use time and logs time between kernel crashes.
void ProcessKernelCrash();
diff --git a/metricsd/metrics_collector_service_client.cc b/metricsd/metrics_collector_service_client.cc
new file mode 100644
index 0000000..08aaa4a
--- /dev/null
+++ b/metricsd/metrics_collector_service_client.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+// Client interface to IMetricsCollectorService.
+
+#include "metrics/metrics_collector_service_client.h"
+
+#include <base/logging.h>
+#include <binder/IServiceManager.h>
+#include <utils/String16.h>
+
+#include "android/brillo/metrics/IMetricsCollectorService.h"
+
+namespace {
+const char kMetricsCollectorServiceName[] =
+ "android.brillo.metrics.IMetricsCollectorService";
+}
+
+bool MetricsCollectorServiceClient::Init() {
+ const android::String16 name(kMetricsCollectorServiceName);
+ metrics_collector_service_ = android::interface_cast<
+ android::brillo::metrics::IMetricsCollectorService>(
+ android::defaultServiceManager()->checkService(name));
+
+ if (metrics_collector_service_ == nullptr)
+ LOG(ERROR) << "Unable to lookup service " << kMetricsCollectorServiceName;
+
+ return metrics_collector_service_ != nullptr;
+}
+
+bool MetricsCollectorServiceClient::notifyUserCrash() {
+ if (metrics_collector_service_ == nullptr)
+ return false;
+
+ metrics_collector_service_->notifyUserCrash();
+ return true;
+}
diff --git a/metricsd/metrics_collector_service_impl.cc b/metricsd/metrics_collector_service_impl.cc
new file mode 100644
index 0000000..dbb0578
--- /dev/null
+++ b/metricsd/metrics_collector_service_impl.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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 "metrics_collector_service_impl.h"
+
+#include <binder/IServiceManager.h>
+#include <binder/Status.h>
+#include <brillo/binder_watcher.h>
+#include <utils/Errors.h>
+
+#include "metrics_collector_service_trampoline.h"
+
+using namespace android;
+
+BnMetricsCollectorServiceImpl::BnMetricsCollectorServiceImpl(
+ MetricsCollectorServiceTrampoline* metrics_collector_service_trampoline) {
+ metrics_collector_service_trampoline_ = metrics_collector_service_trampoline;
+}
+
+void BnMetricsCollectorServiceImpl::Run() {
+ status_t status =
+ defaultServiceManager()->addService(getInterfaceDescriptor(), this);
+ CHECK(status == OK) << "libmetricscollectorservice: failed to add service";
+ binder_watcher_.reset(new ::brillo::BinderWatcher);
+ CHECK(binder_watcher_->Init()) << "Binder FD watcher init failed";
+}
+
+android::binder::Status BnMetricsCollectorServiceImpl::notifyUserCrash() {
+ metrics_collector_service_trampoline_->ProcessUserCrash();
+ return android::binder::Status::ok();
+}
diff --git a/metricsd/metrics_collector_service_impl.h b/metricsd/metrics_collector_service_impl.h
new file mode 100644
index 0000000..bdcab50
--- /dev/null
+++ b/metricsd/metrics_collector_service_impl.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
+#define METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
+
+// metrics_collector binder service implementation. Constructed by
+// MetricsCollectorServiceTrampoline, which we use to call back into
+// MetricsCollector. The trampoline isolates us from the -frtti code of
+// metrics_collector / libbrillo.
+
+#include "android/brillo/metrics/BnMetricsCollectorService.h"
+
+#include <memory>
+
+#include <binder/Status.h>
+#include <brillo/binder_watcher.h>
+
+class MetricsCollectorServiceTrampoline;
+
+//#include "metrics_collector_service_trampoline.h"
+
+class BnMetricsCollectorServiceImpl
+ : public android::brillo::metrics::BnMetricsCollectorService {
+ public:
+ // Passed a this pointer from the MetricsCollectorServiceTrampoline
+ // object that constructs us.
+ explicit BnMetricsCollectorServiceImpl(
+ MetricsCollectorServiceTrampoline* metrics_collector_service_trampoline);
+
+ virtual ~BnMetricsCollectorServiceImpl() = default;
+
+ // Starts the binder main loop.
+ void Run();
+
+ // Called by crash_reporter to report a userspace crash event. We relay
+ // this to MetricsCollector using the trampoline.
+ android::binder::Status notifyUserCrash();
+
+ private:
+ // Trampoline object that constructs us, we use this to call MetricsCollector
+ // methods via the trampoline.
+ MetricsCollectorServiceTrampoline* metrics_collector_service_trampoline_;
+
+ // BinderWatcher object we construct for handling Binder traffic
+ std::unique_ptr<brillo::BinderWatcher> binder_watcher_;
+};
+
+#endif // METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
diff --git a/metricsd/metrics_collector_service_trampoline.cc b/metricsd/metrics_collector_service_trampoline.cc
new file mode 100644
index 0000000..12b80a1
--- /dev/null
+++ b/metricsd/metrics_collector_service_trampoline.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 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 "metrics_collector_service_trampoline.h"
+#include "metrics_collector.h"
+#include "metrics_collector_service_impl.h"
+
+MetricsCollectorServiceTrampoline::MetricsCollectorServiceTrampoline(
+ MetricsCollector* metrics_collector) {
+ metrics_collector_ = metrics_collector;
+}
+
+void MetricsCollectorServiceTrampoline::Run() {
+ // Start metricscollectorservice binder service
+ metrics_collector_service.reset(new BnMetricsCollectorServiceImpl(this));
+ metrics_collector_service->Run();
+}
+
+void MetricsCollectorServiceTrampoline::ProcessUserCrash() {
+ metrics_collector_->ProcessUserCrash();
+}
diff --git a/metricsd/metrics_collector_service_trampoline.h b/metricsd/metrics_collector_service_trampoline.h
new file mode 100644
index 0000000..5da9fa5
--- /dev/null
+++ b/metricsd/metrics_collector_service_trampoline.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef METRICSD_METRICS_COLLECTOR_SERVICE_TRAMPOLINE_H_
+#define METRICSD_METRICS_COLLECTOR_SERVICE_TRAMPOLINE_H_
+
+// Trampoline between the -fno-rtti compile of libmetricsservice and the
+// -frtti compile of metrics_collector. MetricsCollectorServiceTrampoline
+// is called from MetricsCollector to run the IMetricsCollectorService
+// server, and acts as a go-between for calls from server back to
+// MetricsCollector.
+
+#include <memory>
+
+#include "metrics_collector_service_impl.h"
+
+// Forward declaration of MetricsCollector. Don't include the header file
+// for the class here, as it pulls in -frtti stuff.
+class MetricsCollector;
+
+class MetricsCollectorServiceTrampoline {
+ public:
+ // Constructor take a this pointer from the MetricsCollector class that
+ // constructs these objects.
+ explicit MetricsCollectorServiceTrampoline(
+ MetricsCollector* metrics_collector);
+
+ // Initialize and run the IMetricsCollectorService
+ void Run();
+
+ // Called from IMetricsCollectorService to trampoline into the
+ // MetricsCollector method of the same name.
+ void ProcessUserCrash();
+
+ private:
+ // The MetricsCollector object that constructs us, for which we act as
+ // the go-between for MetricsCollectorServiceImpl use.
+ MetricsCollector* metrics_collector_;
+
+ // The IMetricsCollectorService implementation we construct.
+ std::unique_ptr<BnMetricsCollectorServiceImpl> metrics_collector_service;
+};
+
+#endif // METRICSD_METRICS_COLLECTOR_SERVICE_TRAMPOLINE_H_
diff --git a/metricsd/metrics_collector_test.cc b/metricsd/metrics_collector_test.cc
index 956e56b..5fb3ac8 100644
--- a/metricsd/metrics_collector_test.cc
+++ b/metricsd/metrics_collector_test.cc
@@ -115,37 +115,6 @@
StrictMock<MetricsLibraryMock> metrics_lib_;
};
-TEST_F(MetricsCollectorTest, MessageFilter) {
- // Ignore calls to SendToUMA.
- EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _)).Times(AnyNumber());
-
- DBusMessage* msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
- DBusHandlerResult res =
- MetricsCollector::MessageFilter(/* connection */ nullptr, msg, &daemon_);
- EXPECT_EQ(DBUS_HANDLER_RESULT_NOT_YET_HANDLED, res);
- DeleteDBusMessage(msg);
-
- vector<string> signal_args;
- msg = NewDBusSignalString("/",
- "org.chromium.CrashReporter",
- "UserCrash",
- signal_args);
- res = MetricsCollector::MessageFilter(/* connection */ nullptr, msg, &daemon_);
- EXPECT_EQ(DBUS_HANDLER_RESULT_HANDLED, res);
- DeleteDBusMessage(msg);
-
- signal_args.clear();
- signal_args.push_back("randomstate");
- signal_args.push_back("bob"); // arbitrary username
- msg = NewDBusSignalString("/",
- "org.chromium.UnknownService.Manager",
- "StateChanged",
- signal_args);
- res = MetricsCollector::MessageFilter(/* connection */ nullptr, msg, &daemon_);
- EXPECT_EQ(DBUS_HANDLER_RESULT_NOT_YET_HANDLED, res);
- DeleteDBusMessage(msg);
-}
-
TEST_F(MetricsCollectorTest, SendSample) {
ExpectSample("Dummy.Metric", 3);
daemon_.SendSample("Dummy.Metric", /* sample */ 3,
diff --git a/metricsd/uploader/bn_metricsd_impl.cc b/metricsd/uploader/bn_metricsd_impl.cc
index 113a705..2cbc2da 100644
--- a/metricsd/uploader/bn_metricsd_impl.cc
+++ b/metricsd/uploader/bn_metricsd_impl.cc
@@ -21,6 +21,7 @@
#include <base/metrics/statistics_recorder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <utils/Errors.h>
#include <utils/String16.h>
#include <utils/String8.h>
@@ -33,11 +34,14 @@
BnMetricsdImpl::BnMetricsdImpl(const std::shared_ptr<CrashCounters>& counters)
: counters_(counters) {
- CHECK(counters_);
+ CHECK(counters_) << "Invalid counters argument to constructor";
}
void BnMetricsdImpl::Run() {
- android::defaultServiceManager()->addService(getInterfaceDescriptor(), this);
+ android::status_t status =
+ android::defaultServiceManager()->addService(getInterfaceDescriptor(),
+ this);
+ CHECK(status == android::OK) << "Metricsd service registration failed";
android::ProcessState::self()->setThreadPoolMaxThreadCount(0);
android::IPCThreadState::self()->disableBackgroundScheduling(true);
android::IPCThreadState::self()->joinThreadPool();
diff --git a/rootdir/init.rc b/rootdir/init.rc
index b40b9ba..011defb 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -493,6 +493,8 @@
class_start core
on nonencrypted
+ # A/B update verifier that marks a successful boot.
+ exec - root -- /system/bin/update_verifier nonencrypted
class_start main
class_start late_start
@@ -521,9 +523,13 @@
trigger post-fs-data
on property:vold.decrypt=trigger_restart_min_framework
+ # A/B update verifier that marks a successful boot.
+ exec - root -- /system/bin/update_verifier trigger_restart_min_framework
class_start main
on property:vold.decrypt=trigger_restart_framework
+ # A/B update verifier that marks a successful boot.
+ exec - root -- /system/bin/update_verifier trigger_restart_framework
class_start main
class_start late_start