Merge "healthd: Track the API change of minui/minui.h."
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index ec9b1c3..c3f1fe0 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -388,7 +388,13 @@
static void adb_auth_inotify_init(const std::set<std::string>& paths) {
LOG(INFO) << "adb_auth_inotify_init...";
+
int infd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
+ if (infd < 0) {
+ PLOG(ERROR) << "failed to create inotify fd";
+ return;
+ }
+
for (const std::string& path : paths) {
int wd = inotify_add_watch(infd, path.c_str(), IN_CREATE | IN_MOVED_TO);
if (wd < 0) {
diff --git a/bootstat/boot_event_record_store.cpp b/bootstat/boot_event_record_store.cpp
index 78be944..f902af3 100644
--- a/bootstat/boot_event_record_store.cpp
+++ b/bootstat/boot_event_record_store.cpp
@@ -46,24 +46,6 @@
*uptime = file_stat.st_mtime;
- // The following code (till function exit) is a debug test to ensure the
- // validity of the file mtime value, i.e., to check that the record file
- // mtime values are not changed once set.
- // TODO(jhawkins): Remove this code.
- std::string content;
- if (!android::base::ReadFileToString(path, &content)) {
- PLOG(ERROR) << "Failed to read " << path;
- return false;
- }
-
- // Ignore existing bootstat records (which do not contain file content).
- if (!content.empty()) {
- int32_t value;
- if (android::base::ParseInt(content, &value)) {
- bootstat::LogHistogram("bootstat_mtime_matches_content", value == *uptime);
- }
- }
-
return true;
}
@@ -89,16 +71,6 @@
return;
}
- // Writing the value as content in the record file is a debug measure to
- // ensure the validity of the file mtime value, i.e., to check that the record
- // file mtime values are not changed once set.
- // TODO(jhawkins): Remove this block.
- if (!android::base::WriteStringToFd(std::to_string(value), record_fd)) {
- PLOG(ERROR) << "Failed to write value to " << record_path;
- close(record_fd);
- return;
- }
-
// Fill out the stat structure for |record_path| in order to get the atime to
// set in the utime() call.
struct stat file_stat;
diff --git a/bootstat/boot_event_record_store_test.cpp b/bootstat/boot_event_record_store_test.cpp
index 01c2cc1..90f6513 100644
--- a/bootstat/boot_event_record_store_test.cpp
+++ b/bootstat/boot_event_record_store_test.cpp
@@ -45,14 +45,6 @@
return false;
}
- // Writing the value as content in the record file is a debug measure to
- // ensure the validity of the file mtime value, i.e., to check that the record
- // file mtime values are not changed once set.
- // TODO(jhawkins): Remove this block.
- if (!android::base::WriteStringToFd(std::to_string(value), record_fd)) {
- return false;
- }
-
// Set the |mtime| of the file to store the value of the boot event while
// preserving the |atime|.
struct timeval atime = {/* tv_sec */ 0, /* tv_usec */ 0};
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index b9dfedb..e4f88b0 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -36,7 +36,7 @@
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
-#include <log/logger.h>
+#include <log/log.h>
#include <procinfo/process.h>
#include <selinux/selinux.h>
@@ -57,8 +57,9 @@
}
// Attach to a thread, and verify that it's still a member of the given process
-static bool ptrace_attach_thread(pid_t pid, pid_t tid) {
- if (ptrace(PTRACE_ATTACH, tid, 0, 0) != 0) {
+static bool ptrace_seize_thread(pid_t pid, pid_t tid, std::string* error) {
+ if (ptrace(PTRACE_SEIZE, tid, 0, 0) != 0) {
+ *error = StringPrintf("failed to attach to thread %d: %s", tid, strerror(errno));
return false;
}
@@ -67,9 +68,15 @@
if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
PLOG(FATAL) << "failed to detach from thread " << tid;
}
- errno = ECHILD;
+ *error = StringPrintf("thread %d is not in process %d", tid, pid);
return false;
}
+
+ // Put the task into ptrace-stop state.
+ if (ptrace(PTRACE_INTERRUPT, tid, 0, 0) != 0) {
+ PLOG(FATAL) << "failed to interrupt thread " << tid;
+ }
+
return true;
}
@@ -159,11 +166,15 @@
return true;
}
+static void signal_handler(int) {
+ // We can't log easily, because the heap might be corrupt.
+ // Just die and let the surrounding log context explain things.
+ _exit(1);
+}
+
static void abort_handler(pid_t target, const bool& tombstoned_connected,
unique_fd& tombstoned_socket, unique_fd& output_fd,
const char* abort_msg) {
- LOG(ERROR) << abort_msg;
-
// If we abort before we get an output fd, contact tombstoned to let any
// potential listeners know that we failed.
if (!tombstoned_connected) {
@@ -176,7 +187,6 @@
dprintf(output_fd.get(), "crash_dump failed to dump process %d: %s\n", target, abort_msg);
- // Don't dump ourselves.
_exit(1);
}
@@ -202,6 +212,11 @@
abort_handler(target, tombstoned_connected, tombstoned_socket, output_fd, abort_msg);
});
+ // Don't try to dump ourselves.
+ struct sigaction action = {};
+ action.sa_handler = signal_handler;
+ debuggerd_register_handlers(&action);
+
if (argc != 2) {
return 1;
}
@@ -242,11 +257,14 @@
exit(0);
}
+ // Die if we take too long.
+ alarm(20);
+
check_process(target_proc_fd, target);
- int attach_error = 0;
- if (!ptrace_attach_thread(target, main_tid)) {
- PLOG(FATAL) << "failed to attach to thread " << main_tid << " in process " << target;
+ std::string attach_error;
+ if (!ptrace_seize_thread(target, main_tid, &attach_error)) {
+ LOG(FATAL) << attach_error;
}
check_process(target_proc_fd, target);
@@ -268,15 +286,11 @@
TEMP_FAILURE_RETRY(dup2(devnull.get(), STDOUT_FILENO));
}
- if (attach_error != 0) {
- PLOG(FATAL) << "failed to attach to thread " << main_tid << " in process " << target;
- }
-
LOG(INFO) << "performing dump of process " << target << " (target tid = " << main_tid << ")";
- // At this point, the thread that made the request has been PTRACE_ATTACHed
- // and has the signal that triggered things queued. Send PTRACE_CONT, and
- // then wait for the signal.
+ // At this point, the thread that made the request has been attached and is
+ // in ptrace-stopped state. After resumption, the triggering signal that has
+ // been queued will be delivered.
if (ptrace(PTRACE_CONT, main_tid, 0, 0) != 0) {
PLOG(ERROR) << "PTRACE_CONT(" << main_tid << ") failed";
exit(1);
@@ -305,17 +319,19 @@
// Now that we have the signal that kicked things off, attach all of the
// sibling threads, and then proceed.
bool fatal_signal = signo != DEBUGGER_SIGNAL;
- int resume_signal = fatal_signal ? signo : 0;
std::set<pid_t> siblings;
- if (resume_signal == 0) {
+ std::set<pid_t> attached_siblings;
+ if (fatal_signal) {
if (!android::procinfo::GetProcessTids(target, &siblings)) {
PLOG(FATAL) << "failed to get process siblings";
}
siblings.erase(main_tid);
for (pid_t sibling_tid : siblings) {
- if (!ptrace_attach_thread(target, sibling_tid)) {
- PLOG(FATAL) << "failed to attach to thread " << main_tid << " in process " << target;
+ if (!ptrace_seize_thread(target, sibling_tid, &attach_error)) {
+ LOG(WARNING) << attach_error;
+ } else {
+ attached_siblings.insert(sibling_tid);
}
}
}
@@ -328,50 +344,49 @@
std::string amfd_data;
if (backtrace) {
- dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, siblings, 0);
+ dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, attached_siblings, 0);
} else {
// Collect the list of open files.
OpenFilesList open_files;
populate_open_files_list(target, &open_files);
- engrave_tombstone(output_fd.get(), backtrace_map.get(), open_files, target, main_tid, siblings,
- abort_address, fatal_signal ? &amfd_data : nullptr);
+ engrave_tombstone(output_fd.get(), backtrace_map.get(), open_files, target, main_tid,
+ attached_siblings, abort_address, fatal_signal ? &amfd_data : nullptr);
}
+ // We don't actually need to PTRACE_DETACH, as long as our tracees aren't in
+ // group-stop state, which is true as long as no stopping signals are sent.
+
bool wait_for_gdb = android::base::GetBoolProperty("debug.debuggerd.wait_for_gdb", false);
- if (wait_for_gdb) {
+ if (!fatal_signal || siginfo.si_code == SI_USER) {
// Don't wait_for_gdb when the process didn't actually crash.
- if (!fatal_signal) {
- wait_for_gdb = false;
- } else {
- // Use ALOGI to line up with output from engrave_tombstone.
- ALOGI(
- "***********************************************************\n"
- "* Process %d has been suspended while crashing.\n"
- "* To attach gdbserver and start gdb, run this on the host:\n"
- "*\n"
- "* gdbclient.py -p %d\n"
- "*\n"
- "***********************************************************",
- target, main_tid);
- }
+ wait_for_gdb = false;
}
- for (pid_t tid : siblings) {
- // Don't send the signal to sibling threads.
- if (ptrace(PTRACE_DETACH, tid, 0, wait_for_gdb ? SIGSTOP : 0) != 0) {
- PLOG(ERROR) << "ptrace detach from " << tid << " failed";
+ // If the process crashed or we need to send it SIGSTOP for wait_for_gdb,
+ // get it in a state where it can receive signals, and then send the relevant
+ // signal.
+ if (wait_for_gdb || fatal_signal) {
+ if (ptrace(PTRACE_INTERRUPT, main_tid, 0, 0) != 0) {
+ PLOG(ERROR) << "failed to use PTRACE_INTERRUPT on " << main_tid;
}
- }
- if (ptrace(PTRACE_DETACH, main_tid, 0, wait_for_gdb ? SIGSTOP : resume_signal)) {
- PLOG(ERROR) << "ptrace detach from main thread " << main_tid << " failed";
+ if (tgkill(target, main_tid, wait_for_gdb ? SIGSTOP : signo) != 0) {
+ PLOG(ERROR) << "failed to resend signal " << signo << " to " << main_tid;
+ }
}
if (wait_for_gdb) {
- if (tgkill(target, main_tid, resume_signal) != 0) {
- PLOG(ERROR) << "failed to resend signal to process " << target;
- }
+ // Use ALOGI to line up with output from engrave_tombstone.
+ ALOGI(
+ "***********************************************************\n"
+ "* Process %d has been suspended while crashing.\n"
+ "* To attach gdbserver and start gdb, run this on the host:\n"
+ "*\n"
+ "* gdbclient.py -p %d\n"
+ "*\n"
+ "***********************************************************",
+ target, main_tid);
}
if (fatal_signal) {
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index f51b5f2..e7503e9 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -17,6 +17,7 @@
#include <err.h>
#include <fcntl.h>
#include <unistd.h>
+#include <sys/prctl.h>
#include <sys/types.h>
#include <chrono>
@@ -90,6 +91,7 @@
// Returns -1 if we fail to read a response from tombstoned, otherwise the received return code.
void FinishIntercept(int* result);
+ void StartProcess(std::function<void()> function);
void StartCrasher(const std::string& crash_type);
void FinishCrasher();
void AssertDeath(int signo);
@@ -166,9 +168,8 @@
}
}
-void CrasherTest::StartCrasher(const std::string& crash_type) {
- std::string type = "wait-" + crash_type;
-
+void CrasherTest::StartProcess(std::function<void()> function) {
+ unique_fd read_pipe;
unique_fd crasher_read_pipe;
if (!Pipe(&crasher_read_pipe, &crasher_pipe)) {
FAIL() << "failed to create pipe: " << strerror(errno);
@@ -182,9 +183,17 @@
dup2(crasher_read_pipe.get(), STDIN_FILENO);
dup2(devnull.get(), STDOUT_FILENO);
dup2(devnull.get(), STDERR_FILENO);
+ function();
+ _exit(0);
+ }
+}
+
+void CrasherTest::StartCrasher(const std::string& crash_type) {
+ std::string type = "wait-" + crash_type;
+ StartProcess([type]() {
execl(CRASHER_PATH, CRASHER_PATH, type.c_str(), nullptr);
err(1, "exec failed");
- }
+ });
}
void CrasherTest::FinishCrasher() {
@@ -340,24 +349,15 @@
AssertDeath(SIGABRT);
}
+// wait_for_gdb shouldn't trigger on manually sent signals.
TEST_F(CrasherTest, wait_for_gdb_signal) {
if (!android::base::SetProperty(kWaitForGdbKey, "1")) {
FAIL() << "failed to enable wait_for_gdb";
}
StartCrasher("abort");
- ASSERT_EQ(0, kill(crasher_pid, SIGABRT)) << strerror(errno);
-
- std::this_thread::sleep_for(500ms);
-
- int status;
- ASSERT_EQ(crasher_pid, (TIMEOUT(1, waitpid(crasher_pid, &status, WUNTRACED))));
- ASSERT_TRUE(WIFSTOPPED(status));
- ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
-
- ASSERT_EQ(0, kill(crasher_pid, SIGCONT)) << strerror(errno);
-
- AssertDeath(SIGABRT);
+ ASSERT_EQ(0, kill(crasher_pid, SIGSEGV)) << strerror(errno);
+ AssertDeath(SIGSEGV);
}
TEST_F(CrasherTest, backtrace) {
@@ -388,3 +388,20 @@
ConsumeFd(std::move(output_fd), &result);
ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)");
}
+
+TEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) {
+ StartProcess([]() {
+ prctl(PR_SET_DUMPABLE, 0);
+ volatile char* null = static_cast<char*>(nullptr);
+ *null = '\0';
+ });
+ AssertDeath(SIGSEGV);
+}
+
+TEST_F(CrasherTest, PR_SET_DUMPABLE_0_raise) {
+ StartProcess([]() {
+ prctl(PR_SET_DUMPABLE, 0);
+ raise(SIGUSR1);
+ });
+ AssertDeath(SIGUSR1);
+}
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 6033a6b..8ea06c0 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -31,6 +31,7 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
+#include <linux/futex.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
@@ -46,6 +47,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include "private/bionic_futex.h"
#include "private/libc_logging.h"
// see man(2) prctl, specifically the section about PR_GET_NAME
@@ -61,6 +63,9 @@
static debuggerd_callbacks_t g_callbacks;
+// Mutex to ensure only one crashing thread dumps itself.
+static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
+
// Don't use __libc_fatal because it exits via abort, which might put us back into a signal handler.
#define fatal(...) \
do { \
@@ -151,8 +156,7 @@
}
struct debugger_thread_info {
- pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- bool crash_dump_started = false;
+ bool crash_dump_started;
pid_t crashing_tid;
pid_t pseudothread_tid;
int signal_number;
@@ -228,16 +232,41 @@
}
}
- pthread_mutex_unlock(&thread_info->mutex);
+ syscall(__NR_exit, 0);
return 0;
}
+static void resend_signal(siginfo_t* info) {
+ // Signals can either be fatal or nonfatal.
+ // For fatal signals, crash_dump will send us the signal we crashed with
+ // before resuming us, so that processes using waitpid on us will see that we
+ // exited with the correct exit status (e.g. so that sh will report
+ // "Segmentation fault" instead of "Killed"). For this to work, we need
+ // to deregister our signal handler for that signal before continuing.
+ if (info->si_signo != DEBUGGER_SIGNAL) {
+ signal(info->si_signo, SIG_DFL);
+ }
+
+ // We need to return from our signal handler so that crash_dump can see the
+ // signal via ptrace and dump the thread that crashed. However, returning
+ // does not guarantee that the signal will be thrown again, even for SIGSEGV
+ // and friends, since the signal could have been sent manually. We blocked
+ // all signals when registering the handler, so resending the signal (using
+ // rt_tgsigqueueinfo(2) to preserve SA_SIGINFO) will cause it to be delivered
+ // when our signal handler returns.
+ int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), info->si_signo, info);
+ if (rc != 0) {
+ fatal("failed to resend signal during crash: %s", strerror(errno));
+ }
+
+ if (info->si_signo == DEBUGGER_SIGNAL) {
+ pthread_mutex_unlock(&crash_mutex);
+ }
+}
+
// Handler that does crash dumping by forking and doing the processing in the child.
// Do this by ptracing the relevant thread, and then execing debuggerd to do the actual dump.
static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*) {
- // Mutex to prevent multiple crashing threads from trying to talk
- // to debuggerd at the same time.
- static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
int ret = pthread_mutex_lock(&crash_mutex);
if (ret != 0) {
__libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret));
@@ -250,59 +279,10 @@
info = nullptr;
}
- log_signal_summary(signal_number, info);
- if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
- // process has disabled core dumps and PTRACE_ATTACH, and does not want to be dumped.
- // Honor that intention by not connecting to debuggerd and asking it to dump our internal state.
- __libc_format_log(ANDROID_LOG_INFO, "libc",
- "Suppressing debuggerd output because prctl(PR_GET_DUMPABLE)==0");
-
- pthread_mutex_unlock(&crash_mutex);
- return;
- }
-
- void* abort_message = nullptr;
- if (g_callbacks.get_abort_message) {
- abort_message = g_callbacks.get_abort_message();
- }
-
- debugger_thread_info thread_info = {
- .crashing_tid = gettid(),
- .signal_number = signal_number,
- .info = info
- };
- pthread_mutex_lock(&thread_info.mutex);
-
- // Essentially pthread_create without CLONE_FILES (see debuggerd_dispatch_pseudothread).
- pid_t child_pid = clone(debuggerd_dispatch_pseudothread, pseudothread_stack,
- CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | CLONE_CHILD_SETTID,
- &thread_info, nullptr, nullptr, &thread_info.pseudothread_tid);
- if (child_pid == -1) {
- fatal("failed to spawn debuggerd dispatch thread: %s", strerror(errno));
- }
-
- // Wait for the child to finish and unlock the mutex.
- // This relies on bionic behavior that isn't guaranteed by the standard.
- pthread_mutex_lock(&thread_info.mutex);
-
- // Signals can either be fatal or nonfatal.
- // For fatal signals, crash_dump will PTRACE_CONT us with the signal we
- // crashed with, so that processes using waitpid on us will see that we
- // exited with the correct exit status (e.g. so that sh will report
- // "Segmentation fault" instead of "Killed"). For this to work, we need
- // to deregister our signal handler for that signal before continuing.
- if (signal_number != DEBUGGER_SIGNAL) {
- signal(signal_number, SIG_DFL);
- }
-
- // We need to return from the signal handler so that debuggerd can dump the
- // thread that crashed, but returning here does not guarantee that the signal
- // will be thrown again, even for SIGSEGV and friends, since the signal could
- // have been sent manually. Resend the signal with rt_tgsigqueueinfo(2) to
- // preserve the SA_SIGINFO contents.
- struct siginfo si;
+ struct siginfo si = {};
if (!info) {
memset(&si, 0, sizeof(si));
+ si.si_signo = signal_number;
si.si_code = SI_USER;
si.si_pid = getpid();
si.si_uid = getuid();
@@ -314,23 +294,59 @@
// check to allow all si_code values in calls coming from inside the house.
}
+ log_signal_summary(signal_number, info);
+ if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
+ // The process has disabled core dumps and PTRACE_ATTACH, and does not want to be dumped.
+ __libc_format_log(ANDROID_LOG_INFO, "libc",
+ "Suppressing debuggerd output because prctl(PR_GET_DUMPABLE)==0");
+
+ resend_signal(info);
+ return;
+ }
+
+ void* abort_message = nullptr;
+ if (g_callbacks.get_abort_message) {
+ abort_message = g_callbacks.get_abort_message();
+ }
// Populate si_value with the abort message address, if found.
if (abort_message) {
info->si_value.sival_ptr = abort_message;
}
- // Only resend the signal if we know that either crash_dump has ptraced us or
- // the signal was fatal.
- if (thread_info.crash_dump_started || signal_number != DEBUGGER_SIGNAL) {
- int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), signal_number, info);
- if (rc != 0) {
- fatal("failed to resend signal during crash: %s", strerror(errno));
- }
+ debugger_thread_info thread_info = {
+ .crash_dump_started = false,
+ .pseudothread_tid = -1,
+ .crashing_tid = gettid(),
+ .signal_number = signal_number,
+ .info = info
+ };
+
+ // Essentially pthread_create without CLONE_FILES (see debuggerd_dispatch_pseudothread).
+ pid_t child_pid =
+ clone(debuggerd_dispatch_pseudothread, pseudothread_stack,
+ CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID,
+ &thread_info, nullptr, nullptr, &thread_info.pseudothread_tid);
+ if (child_pid == -1) {
+ fatal("failed to spawn debuggerd dispatch thread: %s", strerror(errno));
}
- if (signal_number == DEBUGGER_SIGNAL) {
- pthread_mutex_unlock(&crash_mutex);
+ // Wait for the child to start...
+ __futex_wait(&thread_info.pseudothread_tid, -1, nullptr);
+
+ // and then wait for it to finish.
+ __futex_wait(&thread_info.pseudothread_tid, child_pid, nullptr);
+
+ // Signals can either be fatal or nonfatal.
+ // For fatal signals, crash_dump will PTRACE_CONT us with the signal we
+ // crashed with, so that processes using waitpid on us will see that we
+ // exited with the correct exit status (e.g. so that sh will report
+ // "Segmentation fault" instead of "Killed"). For this to work, we need
+ // to deregister our signal handler for that signal before continuing.
+ if (signal_number != DEBUGGER_SIGNAL) {
+ signal(signal_number, SIG_DFL);
}
+
+ resend_signal(info);
}
void debuggerd_init(debuggerd_callbacks_t* callbacks) {
@@ -363,15 +379,5 @@
// Use the alternate signal stack if available so we can catch stack overflows.
action.sa_flags |= SA_ONSTACK;
-
- sigaction(SIGABRT, &action, nullptr);
- sigaction(SIGBUS, &action, nullptr);
- sigaction(SIGFPE, &action, nullptr);
- sigaction(SIGILL, &action, nullptr);
- sigaction(SIGSEGV, &action, nullptr);
-#if defined(SIGSTKFLT)
- sigaction(SIGSTKFLT, &action, nullptr);
-#endif
- sigaction(SIGTRAP, &action, nullptr);
- sigaction(DEBUGGER_SIGNAL, &action, nullptr);
+ debuggerd_register_handlers(&action);
}
diff --git a/debuggerd/include/debuggerd/handler.h b/debuggerd/include/debuggerd/handler.h
index 302f4c2..7196e0a 100644
--- a/debuggerd/include/debuggerd/handler.h
+++ b/debuggerd/include/debuggerd/handler.h
@@ -39,4 +39,18 @@
// to the log.
#define DEBUGGER_SIGNAL (__SIGRTMIN + 3)
+static void __attribute__((__unused__)) debuggerd_register_handlers(struct sigaction* action) {
+ sigaction(SIGABRT, action, nullptr);
+ sigaction(SIGBUS, action, nullptr);
+ sigaction(SIGFPE, action, nullptr);
+ sigaction(SIGILL, action, nullptr);
+ sigaction(SIGSEGV, action, nullptr);
+#if defined(SIGSTKFLT)
+ sigaction(SIGSTKFLT, action, nullptr);
+#endif
+ sigaction(SIGSYS, action, nullptr);
+ sigaction(SIGTRAP, action, nullptr);
+ sigaction(DEBUGGER_SIGNAL, action, nullptr);
+}
+
__END_DECLS
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 3c1dcaf..8705ece 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -85,7 +85,13 @@
std::string path = android::base::StringPrintf("%stombstone_%02zu", kTombstoneDirectory, i);
struct stat st;
if (stat(path.c_str(), &st) != 0) {
- PLOG(ERROR) << "failed to stat " << path;
+ if (errno == ENOENT) {
+ oldest_tombstone = i;
+ break;
+ } else {
+ PLOG(ERROR) << "failed to stat " << path;
+ continue;
+ }
}
if (st.st_mtime < oldest_time) {
@@ -110,7 +116,7 @@
}
result.reset(
- openat(tombstone_directory_fd, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND, O_CLOEXEC, 0700));
+ openat(tombstone_directory_fd, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0700));
if (result == -1) {
PLOG(FATAL) << "failed to create tombstone at " << kTombstoneDirectory << buf;
}
diff --git a/debuggerd/tombstoned/tombstoned.rc b/debuggerd/tombstoned/tombstoned.rc
index 3aacf33..b8345ca 100644
--- a/debuggerd/tombstoned/tombstoned.rc
+++ b/debuggerd/tombstoned/tombstoned.rc
@@ -1,9 +1,10 @@
service tombstoned /system/bin/tombstoned
- class core
-
user tombstoned
group system
+ # Don't start tombstoned until after the real /data is mounted.
+ class late_start
+
socket tombstoned_crash seqpacket 0666 system system
socket tombstoned_intercept seqpacket 0666 system system
writepid /dev/cpuset/system-background/tasks
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 9a53d62..e699b71 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -407,7 +407,7 @@
return ret;
}
-static int fs_match(char *in1, char *in2)
+static int fs_match(const char *in1, const char *in2)
{
char *n1;
char *n2;
@@ -837,7 +837,7 @@
* If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
* in turn, and stop on 1st success, or no more match.
*/
-int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
+int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
char *tmp_mount_point)
{
int i = 0;
diff --git a/fs_mgr/fs_mgr_main.c b/fs_mgr/fs_mgr_main.c
index 33a7496..4bfe202 100644
--- a/fs_mgr/fs_mgr_main.c
+++ b/fs_mgr/fs_mgr_main.c
@@ -14,12 +14,17 @@
* limitations under the License.
*/
+#define _GNU_SOURCE
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <libgen.h>
#include "fs_mgr_priv.h"
+#ifdef _LIBGEN_H
+#warning "libgen.h must not be included"
+#endif
+
char *me = "";
static void usage(void)
@@ -32,10 +37,10 @@
* and exit the program, do not return to the caller.
* Return the number of argv[] entries consumed.
*/
-static void parse_options(int argc, char *argv[], int *a_flag, int *u_flag, int *n_flag,
- char **n_name, char **n_blk_dev)
+static void parse_options(int argc, char * const argv[], int *a_flag, int *u_flag, int *n_flag,
+ const char **n_name, const char **n_blk_dev)
{
- me = basename(strdup(argv[0]));
+ me = basename(argv[0]);
if (argc <= 1) {
usage();
@@ -75,14 +80,14 @@
return;
}
-int main(int argc, char *argv[])
+int main(int argc, char * const argv[])
{
int a_flag=0;
int u_flag=0;
int n_flag=0;
- char *n_name=NULL;
- char *n_blk_dev=NULL;
- char *fstab_file=NULL;
+ const char *n_name=NULL;
+ const char *n_blk_dev=NULL;
+ const char *fstab_file=NULL;
struct fstab *fstab=NULL;
klog_set_level(6);
@@ -97,7 +102,7 @@
if (a_flag) {
return fs_mgr_mount_all(fstab, MOUNT_MODE_DEFAULT);
} else if (n_flag) {
- return fs_mgr_do_mount(fstab, n_name, n_blk_dev, 0);
+ return fs_mgr_do_mount(fstab, n_name, (char *)n_blk_dev, 0);
} else if (u_flag) {
return fs_mgr_unmount_all(fstab);
} else {
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index e7a0a1d..ef7fdd3 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -99,7 +99,7 @@
#define FS_MGR_DOMNT_FAILED (-1)
#define FS_MGR_DOMNT_BUSY (-2)
-int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
+int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
char *tmp_mount_point);
int fs_mgr_do_tmpfs_mount(char *n_name);
int fs_mgr_unmount_all(struct fstab *fstab);
diff --git a/include/cutils b/include/cutils
new file mode 120000
index 0000000..ac2ed40
--- /dev/null
+++ b/include/cutils
@@ -0,0 +1 @@
+../libcutils/include/cutils/
\ No newline at end of file
diff --git a/include/log b/include/log
new file mode 120000
index 0000000..714065f
--- /dev/null
+++ b/include/log
@@ -0,0 +1 @@
+../liblog/include/log
\ No newline at end of file
diff --git a/include/log/logd.h b/include/log/logd.h
deleted file mode 100644
index 0e0248e..0000000
--- a/include/log/logd.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <log/log.h>
diff --git a/include/log/logger.h b/include/log/logger.h
deleted file mode 100644
index 0e0248e..0000000
--- a/include/log/logger.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <log/log.h>
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 7db28d8..8e2bc1c 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -127,6 +127,7 @@
#define AID_MEDIA_VIDEO 1056 /* GID for video files on internal media storage */
#define AID_MEDIA_IMAGE 1057 /* GID for image files on internal media storage */
#define AID_TOMBSTONED 1058 /* tombstoned user */
+#define AID_MEDIA_OBB 1059 /* GID for OBB files on internal media storage */
/* Changes to this file must be made in AOSP, *not* in internal branches. */
#define AID_SHELL 2000 /* adb and debug shell user */
@@ -165,6 +166,9 @@
#define AID_CACHE_GID_START 20000 /* start of gids for apps to mark cached data */
#define AID_CACHE_GID_END 29999 /* end of gids for apps to mark cached data */
+#define AID_EXT_GID_START 30000 /* start of gids for apps to mark external data */
+#define AID_EXT_GID_END 39999 /* end of gids for apps to mark external data */
+
#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
#define AID_SHARED_GID_END 59999 /* end of gids for apps in each user to share */
diff --git a/include/private/android_logger.h b/include/private/android_logger.h
new file mode 120000
index 0000000..f187a6d
--- /dev/null
+++ b/include/private/android_logger.h
@@ -0,0 +1 @@
+../../liblog/include/private/android_logger.h
\ No newline at end of file
diff --git a/init/Android.mk b/init/Android.mk
index 6615692..35e6f4f 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -70,6 +70,7 @@
init.cpp \
keychords.cpp \
property_service.cpp \
+ seccomp.cpp \
signal_handler.cpp \
ueventd.cpp \
ueventd_parser.cpp \
@@ -96,6 +97,7 @@
libbase \
libc \
libselinux \
+ libseccomp_policy \
liblog \
libcrypto_utils \
libcrypto \
diff --git a/init/init.cpp b/init/init.cpp
index ee5add8..1ce3c35 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -62,6 +62,7 @@
#include "keychords.h"
#include "log.h"
#include "property_service.h"
+#include "seccomp.h"
#include "service.h"
#include "signal_handler.h"
#include "ueventd.h"
@@ -262,26 +263,18 @@
panic();
}
-#define MMAP_RND_PATH "/proc/sys/vm/mmap_rnd_bits"
-#define MMAP_RND_COMPAT_PATH "/proc/sys/vm/mmap_rnd_compat_bits"
-
-/* __attribute__((unused)) due to lack of mips support: see mips block
- * in set_mmap_rnd_bits_action */
-static bool __attribute__((unused)) set_mmap_rnd_bits_min(int start, int min, bool compat) {
- std::string path;
- if (compat) {
- path = MMAP_RND_COMPAT_PATH;
- } else {
- path = MMAP_RND_PATH;
- }
+static bool set_highest_available_option_value(std::string path, int min, int max)
+{
std::ifstream inf(path, std::fstream::in);
if (!inf) {
LOG(ERROR) << "Cannot open for reading: " << path;
return false;
}
- while (start >= min) {
+
+ int current = max;
+ while (current >= min) {
// try to write out new value
- std::string str_val = std::to_string(start);
+ std::string str_val = std::to_string(current);
std::ofstream of(path, std::fstream::out);
if (!of) {
LOG(ERROR) << "Cannot open for writing: " << path;
@@ -297,16 +290,33 @@
if (str_val.compare(str_rec) == 0) {
break;
}
- start--;
+ current--;
}
inf.close();
- if (start < min) {
- LOG(ERROR) << "Unable to set minimum required entropy " << min << " in " << path;
+
+ if (current < min) {
+ LOG(ERROR) << "Unable to set minimum option value " << min << " in " << path;
return false;
}
return true;
}
+#define MMAP_RND_PATH "/proc/sys/vm/mmap_rnd_bits"
+#define MMAP_RND_COMPAT_PATH "/proc/sys/vm/mmap_rnd_compat_bits"
+
+/* __attribute__((unused)) due to lack of mips support: see mips block
+ * in set_mmap_rnd_bits_action */
+static bool __attribute__((unused)) set_mmap_rnd_bits_min(int start, int min, bool compat) {
+ std::string path;
+ if (compat) {
+ path = MMAP_RND_COMPAT_PATH;
+ } else {
+ path = MMAP_RND_PATH;
+ }
+
+ return set_highest_available_option_value(path, min, start);
+}
+
/*
* Set /proc/sys/vm/mmap_rnd_bits and potentially
* /proc/sys/vm/mmap_rnd_compat_bits to the maximum supported values.
@@ -359,6 +369,25 @@
return ret;
}
+#define KPTR_RESTRICT_PATH "/proc/sys/kernel/kptr_restrict"
+#define KPTR_RESTRICT_MINVALUE 2
+#define KPTR_RESTRICT_MAXVALUE 4
+
+/* Set kptr_restrict to the highest available level.
+ *
+ * Aborts if unable to set this to an acceptable value.
+ */
+static int set_kptr_restrict_action(const std::vector<std::string>& args)
+{
+ std::string path = KPTR_RESTRICT_PATH;
+
+ if (!set_highest_available_option_value(path, KPTR_RESTRICT_MINVALUE, KPTR_RESTRICT_MAXVALUE)) {
+ LOG(ERROR) << "Unable to set adequate kptr_restrict value!";
+ security_failure();
+ }
+ return 0;
+}
+
static int keychord_init_action(const std::vector<std::string>& args)
{
keychord_init();
@@ -763,6 +792,12 @@
// Now set up SELinux for second stage.
selinux_initialize(false);
+
+ // Install system-wide seccomp filter
+ if (!set_seccomp_filter()) {
+ LOG(ERROR) << "Failed to set seccomp policy";
+ security_failure();
+ }
}
// These directories were necessarily created before initial policy load
@@ -800,7 +835,12 @@
parser.AddSectionParser("service",std::make_unique<ServiceParser>());
parser.AddSectionParser("on", std::make_unique<ActionParser>());
parser.AddSectionParser("import", std::make_unique<ImportParser>());
- parser.ParseConfig("/init.rc");
+ std::string bootscript = property_get("ro.boot.init_rc");
+ if (bootscript.empty()) {
+ parser.ParseConfig("/init.rc");
+ } else {
+ parser.ParseConfig(bootscript);
+ }
ActionManager& am = ActionManager::GetInstance();
@@ -811,6 +851,7 @@
// ... so that we can start queuing up actions that require stuff from /dev.
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
+ am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict");
am.QueueBuiltinAction(keychord_init_action, "keychord_init");
am.QueueBuiltinAction(console_init_action, "console_init");
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 498a5a1..72fcb5b 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -439,6 +439,8 @@
void property_load_boot_defaults() {
load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT, NULL);
+ load_properties_from_file(PROP_PATH_ODM_DEFAULT, NULL);
+ load_properties_from_file(PROP_PATH_VENDOR_DEFAULT, NULL);
}
static void load_override_properties() {
@@ -501,6 +503,7 @@
void load_system_props() {
load_properties_from_file(PROP_PATH_SYSTEM_BUILD, NULL);
+ load_properties_from_file(PROP_PATH_ODM_BUILD, NULL);
load_properties_from_file(PROP_PATH_VENDOR_BUILD, NULL);
load_properties_from_file(PROP_PATH_FACTORY, "ro.*");
load_recovery_id_prop();
diff --git a/init/seccomp.cpp b/init/seccomp.cpp
new file mode 100644
index 0000000..d632302
--- /dev/null
+++ b/init/seccomp.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2016 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 "seccomp.h"
+
+#include <vector>
+
+#include <sys/prctl.h>
+
+#include <linux/unistd.h>
+#include <linux/audit.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+
+#include "log.h"
+#include "seccomp_policy.h"
+
+#define syscall_nr (offsetof(struct seccomp_data, nr))
+#define arch_nr (offsetof(struct seccomp_data, arch))
+
+#if defined __arm__
+#define AUDIT_ARCH_NR AUDIT_ARCH_ARM
+#elif defined __aarch64__
+#define AUDIT_ARCH_NR AUDIT_ARCH_AARCH64
+#define AUDIT_ARCH_NR32 AUDIT_ARCH_ARM
+#elif defined __i386__
+#define AUDIT_ARCH_NR AUDIT_ARCH_I386
+#elif defined __x86_64__
+#define AUDIT_ARCH_NR AUDIT_ARCH_X86_64
+#define AUDIT_ARCH_NR32 AUDIT_ARCH_I386
+#elif defined __mips64__
+#define AUDIT_ARCH_NR AUDIT_ARCH_MIPS64
+#define AUDIT_ARCH_NR32 AUDIT_ARCH_MIPS
+#elif defined __mips__ && !defined __mips64__
+#define AUDIT_ARCH_NR AUDIT_ARCH_MIPS
+#else
+#error "Could not determine AUDIT_ARCH_NR for this architecture"
+#endif
+
+typedef std::vector<sock_filter> filter;
+
+// We want to keep the below inline functions for debugging and future
+// development even though they are not used currently.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+
+static inline void Kill(filter& f) {
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL));
+}
+
+static inline void Trap(filter& f) {
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP));
+}
+
+static inline void Error(filter& f, __u16 retcode) {
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO + retcode));
+}
+
+inline static void Trace(filter& f) {
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE));
+}
+
+inline static void Allow(filter& f) {
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW));
+}
+
+inline static void AllowSyscall(filter& f, __u32 num) {
+ f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, num, 0, 1));
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW));
+}
+
+inline static void ExamineSyscall(filter& f) {
+ f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_nr));
+}
+
+#ifdef AUDIT_ARCH_NR32
+inline static int SetValidateArchitectureJumpTarget(size_t offset, filter& f) {
+ auto jump_length = f.size() - offset - 1;
+ auto u8_jump_length = (__u8) jump_length;
+ if (u8_jump_length != jump_length) {
+ LOG(ERROR) << "Can't set jump greater than 255 - actual jump is " << jump_length;
+ return -1;
+ }
+ f[offset] = BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_NR32, u8_jump_length, 0);
+ return 0;
+}
+#endif
+
+inline static size_t ValidateArchitectureAndJumpIfNeeded(filter& f) {
+ f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, arch_nr));
+
+#ifdef AUDIT_ARCH_NR32
+ f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_NR, 2, 0));
+ f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_NR32, 1, 0));
+ Kill(f);
+ return f.size() - 2;
+#else
+ f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_NR, 1, 0));
+ Kill(f);
+ return 0;
+#endif
+}
+
+#pragma clang diagnostic pop
+
+static bool install_filter(filter const& f) {
+ struct sock_fprog prog = {
+ (unsigned short) f.size(),
+ (struct sock_filter*) &f[0],
+ };
+
+ if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) {
+ PLOG(ERROR) << "SECCOMP: Could not set seccomp filter";
+ return false;
+ }
+
+ LOG(INFO) << "SECCOMP: Global filter installed";
+ return true;
+}
+
+bool set_seccomp_filter() {
+ filter f;
+
+ // Note that for mixed 64/32 bit architectures, ValidateArchitecture inserts a
+ // jump that must be changed to point to the start of the 32-bit policy
+ // 32 bit syscalls will not hit the policy between here and the call to SetJump
+#ifdef AUDIT_ARCH_NR32
+ auto offset_to_32bit_filter =
+#endif
+ ValidateArchitectureAndJumpIfNeeded(f);
+
+ // Native filter
+ ExamineSyscall(f);
+
+#ifdef __aarch64__
+ // Syscalls needed to boot Android
+ AllowSyscall(f, __NR_pivot_root);
+ AllowSyscall(f, __NR_ioprio_get);
+ AllowSyscall(f, __NR_ioprio_set);
+ AllowSyscall(f, __NR_gettid);
+ AllowSyscall(f, __NR_futex);
+ AllowSyscall(f, __NR_clone);
+ AllowSyscall(f, __NR_rt_sigreturn);
+ AllowSyscall(f, __NR_rt_tgsigqueueinfo);
+ AllowSyscall(f, __NR_add_key);
+ AllowSyscall(f, __NR_request_key);
+ AllowSyscall(f, __NR_keyctl);
+ AllowSyscall(f, __NR_restart_syscall);
+ AllowSyscall(f, __NR_getrandom);
+
+ // Needed for performance tools
+ AllowSyscall(f, __NR_perf_event_open);
+
+ // Needed for treble
+ AllowSyscall(f, __NR_finit_module);
+
+ // Needed for trusty
+ AllowSyscall(f, __NR_syncfs);
+
+ // Needed for strace
+ AllowSyscall(f, __NR_tkill); // __NR_tkill
+
+ // Needed for kernel to restart syscalls
+ AllowSyscall(f, __NR_restart_syscall);
+
+ // arm64-only filter - autogenerated from bionic syscall usage
+ for (size_t i = 0; i < arm64_filter_size; ++i)
+ f.push_back(arm64_filter[i]);
+#else
+ // Generic policy
+ Allow(f);
+#endif
+
+#ifdef AUDIT_ARCH_NR32
+ if (SetValidateArchitectureJumpTarget(offset_to_32bit_filter, f) != 0)
+ return -1;
+
+ // 32-bit filter for 64-bit platforms
+ ExamineSyscall(f);
+
+#ifdef __aarch64__
+ // Syscalls needed to boot android
+ AllowSyscall(f, 120); // __NR_clone
+ AllowSyscall(f, 240); // __NR_futex
+ AllowSyscall(f, 119); // __NR_sigreturn
+ AllowSyscall(f, 173); // __NR_rt_sigreturn
+ AllowSyscall(f, 363); // __NR_rt_tgsigqueueinfo
+ AllowSyscall(f, 224); // __NR_gettid
+
+ // Syscalls needed to run Chrome
+ AllowSyscall(f, 383); // __NR_seccomp - needed to start Chrome
+ AllowSyscall(f, 384); // __NR_getrandom - needed to start Chrome
+
+ // Syscalls needed to run GFXBenchmark
+ AllowSyscall(f, 190); // __NR_vfork
+
+ // Needed for strace
+ AllowSyscall(f, 238); // __NR_tkill
+
+ // Needed for kernel to restart syscalls
+ AllowSyscall(f, 0); // __NR_restart_syscall
+
+ // arm32-on-arm64 only filter - autogenerated from bionic syscall usage
+ for (size_t i = 0; i < arm_filter_size; ++i)
+ f.push_back(arm_filter[i]);
+#else
+ // Generic policy
+ Allow(f);
+#endif
+#endif
+ return install_filter(f);
+}
diff --git a/init/seccomp.h b/init/seccomp.h
new file mode 100644
index 0000000..cda7a89
--- /dev/null
+++ b/init/seccomp.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 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 SECCOMP_H
+#define SECCOMP_H
+
+bool set_seccomp_filter();
+
+#endif
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index b96e3ae..f6c0f0e 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -30,6 +30,23 @@
"str_parms.c",
]
+cc_library_headers {
+ name: "libcutils_vndk_headers",
+ host_supported: true,
+ export_include_dirs: ["include_vndk"],
+}
+
+cc_library_headers {
+ name: "libcutils_headers",
+ host_supported: true,
+ export_include_dirs: ["include"],
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+}
+
cc_library {
name: "libcutils",
host_supported: true,
@@ -51,6 +68,7 @@
"threads.c",
],
+
target: {
host: {
srcs: ["dlmalloc_stubs.c"],
@@ -117,6 +135,9 @@
},
shared_libs: ["liblog"],
+ header_libs: ["libcutils_headers"],
+ export_header_lib_headers: ["libcutils_headers"],
+
product_variables: {
cpusets: {
cflags: ["-DUSE_CPUSETS"],
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 594b23d..b701bba 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -197,7 +197,10 @@
{ 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" },
{ 00600, AID_ROOT, AID_ROOT, 0, "system/build.prop" },
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/build.prop" },
+ { 00600, AID_ROOT, AID_ROOT, 0, "odm/build.prop" },
{ 00600, AID_ROOT, AID_ROOT, 0, "default.prop" },
+ { 00600, AID_ROOT, AID_ROOT, 0, "vendor/default.prop" },
+ { 00600, AID_ROOT, AID_ROOT, 0, "odm/default.prop" },
{ 00644, AID_ROOT, AID_ROOT, 0, 0 },
};
diff --git a/include/cutils/android_get_control_file.h b/libcutils/include/cutils/android_get_control_file.h
similarity index 100%
rename from include/cutils/android_get_control_file.h
rename to libcutils/include/cutils/android_get_control_file.h
diff --git a/include/cutils/android_reboot.h b/libcutils/include/cutils/android_reboot.h
similarity index 100%
rename from include/cutils/android_reboot.h
rename to libcutils/include/cutils/android_reboot.h
diff --git a/include/cutils/ashmem.h b/libcutils/include/cutils/ashmem.h
similarity index 100%
rename from include/cutils/ashmem.h
rename to libcutils/include/cutils/ashmem.h
diff --git a/include/cutils/atomic.h b/libcutils/include/cutils/atomic.h
similarity index 100%
rename from include/cutils/atomic.h
rename to libcutils/include/cutils/atomic.h
diff --git a/include/cutils/bitops.h b/libcutils/include/cutils/bitops.h
similarity index 100%
rename from include/cutils/bitops.h
rename to libcutils/include/cutils/bitops.h
diff --git a/include/cutils/compiler.h b/libcutils/include/cutils/compiler.h
similarity index 100%
rename from include/cutils/compiler.h
rename to libcutils/include/cutils/compiler.h
diff --git a/include/cutils/config_utils.h b/libcutils/include/cutils/config_utils.h
similarity index 100%
rename from include/cutils/config_utils.h
rename to libcutils/include/cutils/config_utils.h
diff --git a/include/cutils/fs.h b/libcutils/include/cutils/fs.h
similarity index 100%
rename from include/cutils/fs.h
rename to libcutils/include/cutils/fs.h
diff --git a/include/cutils/hashmap.h b/libcutils/include/cutils/hashmap.h
similarity index 100%
rename from include/cutils/hashmap.h
rename to libcutils/include/cutils/hashmap.h
diff --git a/include/cutils/iosched_policy.h b/libcutils/include/cutils/iosched_policy.h
similarity index 100%
rename from include/cutils/iosched_policy.h
rename to libcutils/include/cutils/iosched_policy.h
diff --git a/include/cutils/jstring.h b/libcutils/include/cutils/jstring.h
similarity index 100%
rename from include/cutils/jstring.h
rename to libcutils/include/cutils/jstring.h
diff --git a/include/cutils/klog.h b/libcutils/include/cutils/klog.h
similarity index 100%
rename from include/cutils/klog.h
rename to libcutils/include/cutils/klog.h
diff --git a/include/cutils/list.h b/libcutils/include/cutils/list.h
similarity index 100%
rename from include/cutils/list.h
rename to libcutils/include/cutils/list.h
diff --git a/include/cutils/log.h b/libcutils/include/cutils/log.h
similarity index 100%
rename from include/cutils/log.h
rename to libcutils/include/cutils/log.h
diff --git a/include/cutils/memory.h b/libcutils/include/cutils/memory.h
similarity index 100%
rename from include/cutils/memory.h
rename to libcutils/include/cutils/memory.h
diff --git a/include/cutils/misc.h b/libcutils/include/cutils/misc.h
similarity index 100%
rename from include/cutils/misc.h
rename to libcutils/include/cutils/misc.h
diff --git a/include/cutils/multiuser.h b/libcutils/include/cutils/multiuser.h
similarity index 94%
rename from include/cutils/multiuser.h
rename to libcutils/include/cutils/multiuser.h
index 4f23776..5bd9c7b 100644
--- a/include/cutils/multiuser.h
+++ b/libcutils/include/cutils/multiuser.h
@@ -32,6 +32,7 @@
extern uid_t multiuser_get_uid(userid_t user_id, appid_t app_id);
extern gid_t multiuser_get_cache_gid(userid_t user_id, appid_t app_id);
+extern gid_t multiuser_get_ext_gid(userid_t user_id, appid_t app_id);
extern gid_t multiuser_get_shared_gid(userid_t user_id, appid_t app_id);
/* TODO: switch callers over to multiuser_get_shared_gid() */
diff --git a/include/cutils/native_handle.h b/libcutils/include/cutils/native_handle.h
similarity index 100%
rename from include/cutils/native_handle.h
rename to libcutils/include/cutils/native_handle.h
diff --git a/include/cutils/open_memstream.h b/libcutils/include/cutils/open_memstream.h
similarity index 100%
rename from include/cutils/open_memstream.h
rename to libcutils/include/cutils/open_memstream.h
diff --git a/include/cutils/partition_utils.h b/libcutils/include/cutils/partition_utils.h
similarity index 100%
rename from include/cutils/partition_utils.h
rename to libcutils/include/cutils/partition_utils.h
diff --git a/include/cutils/properties.h b/libcutils/include/cutils/properties.h
similarity index 100%
rename from include/cutils/properties.h
rename to libcutils/include/cutils/properties.h
diff --git a/include/cutils/qtaguid.h b/libcutils/include/cutils/qtaguid.h
similarity index 100%
rename from include/cutils/qtaguid.h
rename to libcutils/include/cutils/qtaguid.h
diff --git a/include/cutils/record_stream.h b/libcutils/include/cutils/record_stream.h
similarity index 100%
rename from include/cutils/record_stream.h
rename to libcutils/include/cutils/record_stream.h
diff --git a/include/cutils/sched_policy.h b/libcutils/include/cutils/sched_policy.h
similarity index 100%
rename from include/cutils/sched_policy.h
rename to libcutils/include/cutils/sched_policy.h
diff --git a/include/cutils/sockets.h b/libcutils/include/cutils/sockets.h
similarity index 100%
rename from include/cutils/sockets.h
rename to libcutils/include/cutils/sockets.h
diff --git a/include/cutils/str_parms.h b/libcutils/include/cutils/str_parms.h
similarity index 100%
rename from include/cutils/str_parms.h
rename to libcutils/include/cutils/str_parms.h
diff --git a/include/cutils/threads.h b/libcutils/include/cutils/threads.h
similarity index 100%
rename from include/cutils/threads.h
rename to libcutils/include/cutils/threads.h
diff --git a/include/cutils/trace.h b/libcutils/include/cutils/trace.h
similarity index 100%
rename from include/cutils/trace.h
rename to libcutils/include/cutils/trace.h
diff --git a/include/cutils/uevent.h b/libcutils/include/cutils/uevent.h
similarity index 100%
rename from include/cutils/uevent.h
rename to libcutils/include/cutils/uevent.h
diff --git a/libcutils/include_vndk/cutils/android_get_control_file.h b/libcutils/include_vndk/cutils/android_get_control_file.h
new file mode 120000
index 0000000..70d6a3b
--- /dev/null
+++ b/libcutils/include_vndk/cutils/android_get_control_file.h
@@ -0,0 +1 @@
+../../include/cutils/android_get_control_file.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/android_reboot.h b/libcutils/include_vndk/cutils/android_reboot.h
new file mode 120000
index 0000000..9e1bf4c
--- /dev/null
+++ b/libcutils/include_vndk/cutils/android_reboot.h
@@ -0,0 +1 @@
+../../include/cutils/android_reboot.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/ashmem.h b/libcutils/include_vndk/cutils/ashmem.h
new file mode 120000
index 0000000..5c07beb
--- /dev/null
+++ b/libcutils/include_vndk/cutils/ashmem.h
@@ -0,0 +1 @@
+../../include/cutils/ashmem.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/atomic.h b/libcutils/include_vndk/cutils/atomic.h
new file mode 120000
index 0000000..f4f14fe
--- /dev/null
+++ b/libcutils/include_vndk/cutils/atomic.h
@@ -0,0 +1 @@
+../../include/cutils/atomic.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/bitops.h b/libcutils/include_vndk/cutils/bitops.h
new file mode 120000
index 0000000..edbd60c
--- /dev/null
+++ b/libcutils/include_vndk/cutils/bitops.h
@@ -0,0 +1 @@
+../../include/cutils/bitops.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/compiler.h b/libcutils/include_vndk/cutils/compiler.h
new file mode 120000
index 0000000..08ebc10
--- /dev/null
+++ b/libcutils/include_vndk/cutils/compiler.h
@@ -0,0 +1 @@
+../../include/cutils/compiler.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/config_utils.h b/libcutils/include_vndk/cutils/config_utils.h
new file mode 120000
index 0000000..e011738
--- /dev/null
+++ b/libcutils/include_vndk/cutils/config_utils.h
@@ -0,0 +1 @@
+../../include/cutils/config_utils.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/fs.h b/libcutils/include_vndk/cutils/fs.h
new file mode 120000
index 0000000..576bfa3
--- /dev/null
+++ b/libcutils/include_vndk/cutils/fs.h
@@ -0,0 +1 @@
+../../include/cutils/fs.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/hashmap.h b/libcutils/include_vndk/cutils/hashmap.h
new file mode 120000
index 0000000..6b18406
--- /dev/null
+++ b/libcutils/include_vndk/cutils/hashmap.h
@@ -0,0 +1 @@
+../../include/cutils/hashmap.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/iosched_policy.h b/libcutils/include_vndk/cutils/iosched_policy.h
new file mode 120000
index 0000000..26cf333
--- /dev/null
+++ b/libcutils/include_vndk/cutils/iosched_policy.h
@@ -0,0 +1 @@
+../../include/cutils/iosched_policy.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/jstring.h b/libcutils/include_vndk/cutils/jstring.h
new file mode 120000
index 0000000..f3fd546
--- /dev/null
+++ b/libcutils/include_vndk/cutils/jstring.h
@@ -0,0 +1 @@
+../../include/cutils/jstring.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/klog.h b/libcutils/include_vndk/cutils/klog.h
new file mode 120000
index 0000000..8ca85ff
--- /dev/null
+++ b/libcutils/include_vndk/cutils/klog.h
@@ -0,0 +1 @@
+../../include/cutils/klog.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/list.h b/libcutils/include_vndk/cutils/list.h
new file mode 120000
index 0000000..9fa4c90
--- /dev/null
+++ b/libcutils/include_vndk/cutils/list.h
@@ -0,0 +1 @@
+../../include/cutils/list.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/log.h b/libcutils/include_vndk/cutils/log.h
new file mode 100644
index 0000000..ae74024
--- /dev/null
+++ b/libcutils/include_vndk/cutils/log.h
@@ -0,0 +1,21 @@
+/*Special log.h file for VNDK linking modules*/
+/*
+ * Copyright (C) 2005-2017 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 _LIBS_CUTIL_LOG_H
+#define _LIBS_CUTIL_LOG_H
+#warning "Deprecated: don't include cutils/log.h, use either android/log.h or log/log.h"
+#include <log/log.h>
+#endif /* _LIBS_CUTIL_LOG_H */
diff --git a/libcutils/include_vndk/cutils/memory.h b/libcutils/include_vndk/cutils/memory.h
new file mode 120000
index 0000000..e0e7abc
--- /dev/null
+++ b/libcutils/include_vndk/cutils/memory.h
@@ -0,0 +1 @@
+../../include/cutils/memory.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/misc.h b/libcutils/include_vndk/cutils/misc.h
new file mode 120000
index 0000000..db09eb5
--- /dev/null
+++ b/libcutils/include_vndk/cutils/misc.h
@@ -0,0 +1 @@
+../../include/cutils/misc.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/multiuser.h b/libcutils/include_vndk/cutils/multiuser.h
new file mode 120000
index 0000000..524111f
--- /dev/null
+++ b/libcutils/include_vndk/cutils/multiuser.h
@@ -0,0 +1 @@
+../../include/cutils/multiuser.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/native_handle.h b/libcutils/include_vndk/cutils/native_handle.h
new file mode 120000
index 0000000..e324d4e
--- /dev/null
+++ b/libcutils/include_vndk/cutils/native_handle.h
@@ -0,0 +1 @@
+../../include/cutils/native_handle.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/open_memstream.h b/libcutils/include_vndk/cutils/open_memstream.h
new file mode 120000
index 0000000..c894084
--- /dev/null
+++ b/libcutils/include_vndk/cutils/open_memstream.h
@@ -0,0 +1 @@
+../../include/cutils/open_memstream.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/partition_utils.h b/libcutils/include_vndk/cutils/partition_utils.h
new file mode 120000
index 0000000..d9734c8
--- /dev/null
+++ b/libcutils/include_vndk/cutils/partition_utils.h
@@ -0,0 +1 @@
+../../include/cutils/partition_utils.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/properties.h b/libcutils/include_vndk/cutils/properties.h
new file mode 120000
index 0000000..d56118e
--- /dev/null
+++ b/libcutils/include_vndk/cutils/properties.h
@@ -0,0 +1 @@
+../../include/cutils/properties.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/qtaguid.h b/libcutils/include_vndk/cutils/qtaguid.h
new file mode 120000
index 0000000..bc02441
--- /dev/null
+++ b/libcutils/include_vndk/cutils/qtaguid.h
@@ -0,0 +1 @@
+../../include/cutils/qtaguid.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/record_stream.h b/libcutils/include_vndk/cutils/record_stream.h
new file mode 120000
index 0000000..8de6494
--- /dev/null
+++ b/libcutils/include_vndk/cutils/record_stream.h
@@ -0,0 +1 @@
+../../include/cutils/record_stream.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/sched_policy.h b/libcutils/include_vndk/cutils/sched_policy.h
new file mode 120000
index 0000000..ddebdd0
--- /dev/null
+++ b/libcutils/include_vndk/cutils/sched_policy.h
@@ -0,0 +1 @@
+../../include/cutils/sched_policy.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/sockets.h b/libcutils/include_vndk/cutils/sockets.h
new file mode 120000
index 0000000..585250c
--- /dev/null
+++ b/libcutils/include_vndk/cutils/sockets.h
@@ -0,0 +1 @@
+../../include/cutils/sockets.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/str_parms.h b/libcutils/include_vndk/cutils/str_parms.h
new file mode 120000
index 0000000..9c79a8f
--- /dev/null
+++ b/libcutils/include_vndk/cutils/str_parms.h
@@ -0,0 +1 @@
+../../include/cutils/str_parms.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/threads.h b/libcutils/include_vndk/cutils/threads.h
new file mode 120000
index 0000000..99330ff
--- /dev/null
+++ b/libcutils/include_vndk/cutils/threads.h
@@ -0,0 +1 @@
+../../include/cutils/threads.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/trace.h b/libcutils/include_vndk/cutils/trace.h
new file mode 120000
index 0000000..b12e140
--- /dev/null
+++ b/libcutils/include_vndk/cutils/trace.h
@@ -0,0 +1 @@
+../../include/cutils/trace.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/uevent.h b/libcutils/include_vndk/cutils/uevent.h
new file mode 120000
index 0000000..451283a
--- /dev/null
+++ b/libcutils/include_vndk/cutils/uevent.h
@@ -0,0 +1 @@
+../../include/cutils/uevent.h
\ No newline at end of file
diff --git a/libcutils/multiuser.c b/libcutils/multiuser.c
index 0ef337d..08d4d6c 100644
--- a/libcutils/multiuser.c
+++ b/libcutils/multiuser.c
@@ -37,6 +37,14 @@
}
}
+gid_t multiuser_get_ext_gid(userid_t user_id, appid_t app_id) {
+ if (app_id >= AID_APP_START && app_id <= AID_APP_END) {
+ return multiuser_get_uid(user_id, (app_id - AID_APP_START) + AID_EXT_GID_START);
+ } else {
+ return -1;
+ }
+}
+
gid_t multiuser_get_shared_gid(userid_t user_id, appid_t app_id) {
if (app_id >= AID_APP_START && app_id <= AID_APP_END) {
return multiuser_get_uid(user_id, (app_id - AID_APP_START) + AID_SHARED_GID_START);
diff --git a/libcutils/tests/multiuser_test.cpp b/libcutils/tests/multiuser_test.cpp
index 2307ea8..c5f58b4 100644
--- a/libcutils/tests/multiuser_test.cpp
+++ b/libcutils/tests/multiuser_test.cpp
@@ -58,6 +58,14 @@
EXPECT_EQ(1020000, multiuser_get_cache_gid(10, 10000));
}
+TEST(MultiuserTest, TestExt) {
+ EXPECT_EQ(-1, multiuser_get_ext_gid(0, 0));
+ EXPECT_EQ(-1, multiuser_get_ext_gid(0, 1000));
+ EXPECT_EQ(30000, multiuser_get_ext_gid(0, 10000));
+ EXPECT_EQ(-1, multiuser_get_ext_gid(0, 50000));
+ EXPECT_EQ(1030000, multiuser_get_ext_gid(10, 10000));
+}
+
TEST(MultiuserTest, TestShared) {
EXPECT_EQ(-1, multiuser_get_shared_gid(0, 0));
EXPECT_EQ(-1, multiuser_get_shared_gid(0, 1000));
diff --git a/liblog/Android.bp b/liblog/Android.bp
index bbe7d79..dce316d 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -57,7 +57,7 @@
srcs: liblog_target_sources,
// AddressSanitizer runtime library depends on liblog.
sanitize: {
- never: true,
+ address: false,
},
},
android_arm: {
@@ -79,6 +79,8 @@
},
},
+ export_include_dirs: ["include"],
+
cflags: [
"-Werror",
"-fvisibility=hidden",
@@ -111,6 +113,11 @@
license: "NOTICE",
}
+cc_library_headers {
+ name: "liblog_vndk_headers",
+ export_include_dirs: ["include_vndk"],
+}
+
ndk_library {
name: "liblog.ndk",
symbol_file: "liblog.map.txt",
diff --git a/include/log/event_tag_map.h b/liblog/include/log/event_tag_map.h
similarity index 100%
rename from include/log/event_tag_map.h
rename to liblog/include/log/event_tag_map.h
diff --git a/include/log/log.h b/liblog/include/log/log.h
similarity index 100%
rename from include/log/log.h
rename to liblog/include/log/log.h
diff --git a/include/log/log_event_list.h b/liblog/include/log/log_event_list.h
similarity index 100%
rename from include/log/log_event_list.h
rename to liblog/include/log/log_event_list.h
diff --git a/liblog/include/log/logd.h b/liblog/include/log/logd.h
new file mode 100644
index 0000000..77400ca
--- /dev/null
+++ b/liblog/include/log/logd.h
@@ -0,0 +1,5 @@
+#ifndef _LIBS_LOG_LOGD_H
+#define _LIBS_LOG_LOGD_H
+#include <log/log.h>
+#warning "Deprecated: do not include log/logd.h, use log/log.h instead"
+#endif /*_LIBS_LOG_LOGD_H*/
diff --git a/liblog/include/log/logger.h b/liblog/include/log/logger.h
new file mode 100644
index 0000000..1bf2d17
--- /dev/null
+++ b/liblog/include/log/logger.h
@@ -0,0 +1,5 @@
+#ifndef _LIBS_LOG_LOGGER_H
+#define _LIBS_LOG_LOGGER_H
+#include <log/log.h>
+#warning "Deprecated: do not include log/logger.h, use log/log.h instead"
+#endif /*_LIBS_LOG_LOGGER_H*/
diff --git a/include/log/logprint.h b/liblog/include/log/logprint.h
similarity index 100%
rename from include/log/logprint.h
rename to liblog/include/log/logprint.h
diff --git a/include/log/uio.h b/liblog/include/log/uio.h
similarity index 100%
rename from include/log/uio.h
rename to liblog/include/log/uio.h
diff --git a/include/private/android_logger.h b/liblog/include/private/android_logger.h
similarity index 100%
rename from include/private/android_logger.h
rename to liblog/include/private/android_logger.h
diff --git a/liblog/include_vndk/android b/liblog/include_vndk/android
new file mode 120000
index 0000000..69fbc09
--- /dev/null
+++ b/liblog/include_vndk/android
@@ -0,0 +1 @@
+../../include/android/
\ No newline at end of file
diff --git a/liblog/include_vndk/log/log.h b/liblog/include_vndk/log/log.h
new file mode 100644
index 0000000..f3eb3fe
--- /dev/null
+++ b/liblog/include_vndk/log/log.h
@@ -0,0 +1,22 @@
+/*Special log.h file for VNDK linking modules*/
+
+#ifndef _LIBS_LOG_LOG_H
+#define _LIBS_LOG_LOG_H
+
+#include <android/log.h>
+
+/*The following files will be included once they are available*/
+/*#include <log/log_id.h>*/
+/*#include <log/log_radio.h>*/
+
+/*
+ * LOG_TAG is the local tag used for the following simplified
+ * logging macros. You can change this preprocessor definition
+ * before using the other macros to change the tag.
+ */
+
+#ifndef LOG_TAG
+#define LOG_TAG NULL
+#endif
+
+#endif /*_LIBS_LOG_LOG_H*/
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index f19c3ab..1a2d506 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -262,6 +262,8 @@
}
#if defined(__ANDROID__)
+ clock_gettime(android_log_clockid(), &ts);
+
if (log_id == LOG_ID_SECURITY) {
if (vec[0].iov_len < 4) {
return -EINVAL;
@@ -351,8 +353,6 @@
return -EPERM;
}
}
-
- clock_gettime(android_log_clockid(), &ts);
#else
/* simulate clock_gettime(CLOCK_REALTIME, &ts); */
{
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index c204a16..d9935c3 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -581,24 +581,36 @@
} /* namespace android */
+void reportErrorName(const char **current,
+ const char* name,
+ bool blockSecurity) {
+ if (*current) {
+ return;
+ }
+ if (blockSecurity && (android_name_to_log_id(name) == LOG_ID_SECURITY)) {
+ return;
+ }
+ *current = name;
+}
int main(int argc, char **argv)
{
using namespace android;
int err;
int hasSetLogFormat = 0;
- int clearLog = 0;
- int getLogSize = 0;
+ bool clearLog = false;
+ bool allSelected = false;
+ bool getLogSize = false;
+ bool getPruneList = false;
+ bool printStatistics = false;
+ bool printDividers = false;
unsigned long setLogSize = 0;
- int getPruneList = 0;
char *setPruneList = NULL;
char *setId = NULL;
- int printStatistics = 0;
int mode = ANDROID_LOG_RDONLY;
const char *forceFilters = NULL;
log_device_t* devices = NULL;
log_device_t* dev;
- bool printDividers = false;
struct logger_list *logger_list;
size_t tail_lines = 0;
log_time tail_time(log_time::EPOCH);
@@ -710,7 +722,7 @@
break;
case 'c':
- clearLog = 1;
+ clearLog = true;
mode |= ANDROID_LOG_WRONLY;
break;
@@ -771,7 +783,7 @@
case 'g':
if (!optarg) {
- getLogSize = 1;
+ getLogSize = true;
break;
}
// FALLTHRU
@@ -813,7 +825,7 @@
case 'p':
if (!optarg) {
- getPruneList = 1;
+ getPruneList = true;
break;
}
// FALLTHRU
@@ -830,6 +842,7 @@
(1 << LOG_ID_SYSTEM) |
(1 << LOG_ID_CRASH);
} else if (strcmp(optarg, "all") == 0) {
+ allSelected = true;
idMask = (unsigned)-1;
} else {
log_id_t log_id = android_name_to_log_id(optarg);
@@ -839,6 +852,7 @@
logcat_panic(HELP_TRUE,
"unknown buffer %s\n", optarg);
}
+ if (log_id == LOG_ID_SECURITY) allSelected = false;
idMask |= (1 << log_id);
}
optarg = NULL;
@@ -992,7 +1006,7 @@
break;
case 'S':
- printStatistics = 1;
+ printStatistics = true;
break;
case ':':
@@ -1114,7 +1128,7 @@
dev->logger = android_logger_open(logger_list,
android_name_to_log_id(dev->device));
if (!dev->logger) {
- openDeviceFail = openDeviceFail ?: dev->device;
+ reportErrorName(&openDeviceFail, dev->device, allSelected);
dev = dev->next;
continue;
}
@@ -1136,7 +1150,7 @@
if (file.length() == 0) {
perror("while clearing log files");
- clearFail = clearFail ?: dev->device;
+ reportErrorName(&clearFail, dev->device, allSelected);
break;
}
@@ -1144,17 +1158,17 @@
if (err < 0 && errno != ENOENT && clearFail == NULL) {
perror("while clearing log files");
- clearFail = dev->device;
+ reportErrorName(&clearFail, dev->device, allSelected);
}
}
} else if (android_logger_clear(dev->logger)) {
- clearFail = clearFail ?: dev->device;
+ reportErrorName(&clearFail, dev->device, allSelected);
}
}
if (setLogSize) {
if (android_logger_set_log_size(dev->logger, setLogSize)) {
- setSizeFail = setSizeFail ?: dev->device;
+ reportErrorName(&setSizeFail, dev->device, allSelected);
}
}
@@ -1163,7 +1177,7 @@
long readable = android_logger_get_log_readable_size(dev->logger);
if ((size < 0) || (readable < 0)) {
- getSizeFail = getSizeFail ?: dev->device;
+ reportErrorName(&getSizeFail, dev->device, allSelected);
} else {
printf("%s: ring buffer is %ld%sb (%ld%sb consumed), "
"max entry is %db, max payload is %db\n", dev->device,
diff --git a/logcat/tests/Android.mk b/logcat/tests/Android.mk
index 99c2e0a..cb8b061 100644
--- a/logcat/tests/Android.mk
+++ b/logcat/tests/Android.mk
@@ -55,6 +55,6 @@
LOCAL_MODULE := $(test_module_prefix)unit-tests
LOCAL_MODULE_TAGS := $(test_tags)
LOCAL_CFLAGS += $(test_c_flags)
-LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SHARED_LIBRARIES := liblog libbase
LOCAL_SRC_FILES := $(test_src_files)
include $(BUILD_NATIVE_TEST)
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 725d76e..337861e 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -23,10 +23,12 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <unistd.h>
#include <memory>
#include <string>
+#include <android-base/file.h>
#include <gtest/gtest.h>
#include <log/log.h>
#include <log/log_event_list.h>
@@ -53,6 +55,11 @@
TEST(logcat, buckets) {
FILE *fp;
+#undef LOG_TAG
+#define LOG_TAG "inject"
+ RLOGE("logcat.buckets");
+ sleep(1);
+
ASSERT_TRUE(NULL != (fp = popen(
"logcat -b radio -b events -b system -b main -d 2>/dev/null",
"r")));
@@ -164,13 +171,39 @@
if (!ep) {
continue;
}
- ep -= 7;
+ static const size_t tag_field_width = 7;
+ ep -= tag_field_width;
*ep = '\0';
return cp;
}
return NULL;
}
+// If there is not enough background noise in the logs, then spam the logs to
+// permit tail checking so that the tests can progress.
+static size_t inject(ssize_t count) {
+ if (count <= 0) return 0;
+
+ static const size_t retry = 3;
+ size_t errors = retry;
+ size_t num = 0;
+ for(;;) {
+ log_time ts(CLOCK_MONOTONIC);
+ if (__android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)) >= 0) {
+ if (++num >= (size_t)count) {
+ sleep(1); // let data settle end-to-end
+ return num;
+ }
+ errors = retry;
+ usleep(50);
+ } else if (--errors <= 0) {
+ return num;
+ }
+ }
+ // NOTREACH
+ return num;
+}
+
TEST(logcat, tz) {
if (android_log_clockid() == CLOCK_MONOTONIC) {
@@ -200,7 +233,7 @@
pclose(fp);
- } while ((count < 3) && --tries && (sleep(1), true));
+ } while ((count < 3) && --tries && inject(3 - count));
ASSERT_EQ(3, count);
}
@@ -235,8 +268,7 @@
char buffer[BIG_BUFFER];
snprintf(buffer, sizeof(buffer),
- "logcat -v long -b radio -b events -b system -b main -t %d 2>/dev/null",
- num);
+ "logcat -v long -b all -t %d 2>/dev/null", num);
FILE *fp;
ASSERT_TRUE(NULL != (fp = popen(buffer, "r")));
@@ -249,7 +281,7 @@
pclose(fp);
- } while ((count < num) && --tries && (sleep(1), true));
+ } while ((count < num) && --tries && inject(num - count));
ASSERT_EQ(num, count);
}
@@ -272,26 +304,34 @@
TEST(logcat, tail_time) {
FILE *fp;
-
- ASSERT_TRUE(NULL != (fp = popen("logcat -v long -b all -t 10 2>&1", "r")));
-
+ int count;
char buffer[BIG_BUFFER];
char *last_timestamp = NULL;
char *first_timestamp = NULL;
- int count = 0;
-
char *cp;
- while ((cp = fgetLongTime(buffer, sizeof(buffer), fp))) {
- ++count;
- if (!first_timestamp) {
- first_timestamp = strdup(cp);
- }
- free(last_timestamp);
- last_timestamp = strdup(cp);
- }
- pclose(fp);
- EXPECT_EQ(10, count);
+ int tries = 3; // in case run too soon after system start or buffer clear
+
+ // Do not be tempted to use -v usec because that increases the
+ // chances of an occasional test failure by 1000 (see below).
+ do {
+ ASSERT_TRUE(NULL != (fp = popen("logcat -v long -b all -t 10 2>&1", "r")));
+
+ count = 0;
+
+ while ((cp = fgetLongTime(buffer, sizeof(buffer), fp))) {
+ ++count;
+ if (!first_timestamp) {
+ first_timestamp = strdup(cp);
+ }
+ free(last_timestamp);
+ last_timestamp = strdup(cp);
+ }
+ pclose(fp);
+
+ } while ((count < 10) && --tries && inject(10 - count));
+
+ EXPECT_EQ(10, count); // We want _some_ history, too small, falses below
EXPECT_TRUE(last_timestamp != NULL);
EXPECT_TRUE(first_timestamp != NULL);
@@ -1412,3 +1452,22 @@
EXPECT_TRUE(End_to_End(sync.tagStr, ""));
}
}
+
+static bool reportedSecurity(const char* command) {
+ FILE* fp = popen(command, "r");
+ if (!fp) return true;
+
+ std::string ret;
+ bool val = android::base::ReadFdToString(fileno(fp), &ret);
+ pclose(fp);
+
+ if (!val) return true;
+ return std::string::npos != ret.find("'security'");
+}
+
+TEST(logcat, security) {
+ EXPECT_FALSE(reportedSecurity("logcat -b all -g 2>&1"));
+ EXPECT_TRUE(reportedSecurity("logcat -b security -g 2>&1"));
+ EXPECT_TRUE(reportedSecurity("logcat -b security -c 2>&1"));
+ EXPECT_TRUE(reportedSecurity("logcat -b security -G 256K 2>&1"));
+}
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 703c0fb..13a7922 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -196,7 +196,9 @@
EXPECT_TRUE(NULL != main_logs);
char *radio_logs = strstr(cp, "\nChattiest UIDs in radio ");
- EXPECT_TRUE(NULL != radio_logs);
+ if (!radio_logs) GTEST_LOG_(INFO) << "Value of: NULL != radio_logs\n"
+ "Actual: false\n"
+ "Expected: false\n";
char *system_logs = strstr(cp, "\nChattiest UIDs in system ");
EXPECT_TRUE(NULL != system_logs);
@@ -942,8 +944,16 @@
return 0;
}
- // Requests dac_read_search, falls back to request dac_override
- rate /= 2;
+ // The key here is we are root, but we are in u:r:shell:s0,
+ // and the directory does not provide us DAC access
+ // (eg: 0700 system system) so we trigger the pair dac_override
+ // and dac_read_search on every try to get past the message
+ // de-duper. We will also rotate the file name in the directory
+ // as another measure.
+ static const char file[] = "/data/backup/cannot_access_directory_%u";
+ static const unsigned avc_requests_per_access = 2;
+
+ rate /= avc_requests_per_access;
useconds_t usec;
if (rate == 0) {
rate = 1;
@@ -951,15 +961,12 @@
} else {
usec = (1000000 + (rate / 2)) / rate;
}
- num = (num + 1) / 2;
+ num = (num + (avc_requests_per_access / 2)) / avc_requests_per_access;
if (usec < 2) usec = 2;
while (num > 0) {
- if (access(android::base::StringPrintf(
- "/data/misc/logd/cannot_access_directory_%u",
- num).c_str(),
- F_OK) == 0) {
+ if (access(android::base::StringPrintf(file, num).c_str(), F_OK) == 0) {
_exit(-1);
// NOTREACHED
return 0;
@@ -1002,7 +1009,7 @@
// int len = get4LE(eventData + 4 + 1);
log_msg.buf[LOGGER_ENTRY_MAX_LEN] = '\0';
- const char *cp = strstr(eventData + 4 + 1 + 4, "): avc: ");
+ const char *cp = strstr(eventData + 4 + 1 + 4, "): avc: denied");
if (!cp) continue;
++count;
@@ -1055,8 +1062,7 @@
// give logd another 3 seconds to react to the burst before checking
sepolicy_rate(rate, rate * 3);
// maximum period at double the maximum burst rate (spam filter kicked in)
- EXPECT_GE(((AUDIT_RATE_LIMIT_MAX * AUDIT_RATE_LIMIT_BURST_DURATION) * 130) /
- 100, // +30% margin
+ EXPECT_GE(threshold * 2,
count_avc(sepolicy_rate(rate,
rate * AUDIT_RATE_LIMIT_BURST_DURATION)));
// cool down, and check unspammy rate still works
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 791d67f..d6ae6f0 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -118,7 +118,6 @@
write /proc/sys/kernel/sched_child_runs_first 0
write /proc/sys/kernel/randomize_va_space 2
- write /proc/sys/kernel/kptr_restrict 2
write /proc/sys/vm/mmap_min_addr 32768
write /proc/sys/net/ipv4/ping_group_range "0 2147483647"
write /proc/sys/net/unix/max_dgram_qlen 600
@@ -356,10 +355,6 @@
# We restorecon /data in case the userdata partition has been reset.
restorecon /data
- # start debuggerd to make debugging early-boot crashes easier.
- start debuggerd
- start debuggerd64
-
# Make sure we have the device encryption key.
start vold
installkey /data