Merge "Adjust for small changes in the native keystore interface"
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..831150b 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -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) {
+static bool ptrace_attach_thread(pid_t pid, pid_t tid, std::string* error) {
if (ptrace(PTRACE_ATTACH, tid, 0, 0) != 0) {
+ *error = StringPrintf("failed to attach to thread %d: %s", tid, strerror(errno));
return false;
}
@@ -67,7 +68,7 @@
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;
}
return true;
@@ -244,9 +245,9 @@
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_attach_thread(target, main_tid, &attach_error)) {
+ LOG(FATAL) << attach_error;
}
check_process(target_proc_fd, target);
@@ -268,10 +269,6 @@
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
@@ -307,6 +304,7 @@
bool fatal_signal = signo != DEBUGGER_SIGNAL;
int resume_signal = fatal_signal ? signo : 0;
std::set<pid_t> siblings;
+ std::set<pid_t> attached_siblings;
if (resume_signal == 0) {
if (!android::procinfo::GetProcessTids(target, &siblings)) {
PLOG(FATAL) << "failed to get process siblings";
@@ -314,8 +312,10 @@
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_attach_thread(target, sibling_tid, &attach_error)) {
+ LOG(WARNING) << attach_error;
+ } else {
+ attached_siblings.insert(sibling_tid);
}
}
}
@@ -328,14 +328,14 @@
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);
}
bool wait_for_gdb = android::base::GetBoolProperty("debug.debuggerd.wait_for_gdb", false);
@@ -357,7 +357,7 @@
}
}
- for (pid_t tid : siblings) {
+ for (pid_t tid : attached_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";
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 3c1dcaf..63e3dbd 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -110,7 +110,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..eaae9c4 100644
--- a/debuggerd/tombstoned/tombstoned.rc
+++ b/debuggerd/tombstoned/tombstoned.rc
@@ -1,6 +1,4 @@
service tombstoned /system/bin/tombstoned
- class core
-
user tombstoned
group system
diff --git a/include/cutils/multiuser.h b/include/cutils/multiuser.h
index 4f23776..5bd9c7b 100644
--- a/include/cutils/multiuser.h
+++ b/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/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/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..ddc707f 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
@@ -811,6 +846,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..d9f2f79
--- /dev/null
+++ b/init/seccomp.cpp
@@ -0,0 +1,213 @@
+/*
+ * 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);
+
+ // 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
+
+ // 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/fs_config.c b/libcutils/fs_config.c
index 18c0020..a7c2dce 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -202,7 +202,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/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/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..8a390f6 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -27,6 +27,7 @@
#include <memory>
#include <string>
+#include <android-base/file.h>
#include <gtest/gtest.h>
#include <log/log.h>
#include <log/log_event_list.h>
@@ -1412,3 +1413,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 50788c1..1ae43fb 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
@@ -357,14 +356,13 @@
# 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
+ # start tombstoned to record early-boot crashes.
+ start tombstoned
+
# Start bootcharting as soon as possible after the data partition is
# mounted to collect more data.
mkdir /data/bootchart 0755 shell shell