Merge "crash_dump: don't abort if we fail to attach a sibling."
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/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 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/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/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..998e064 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