Merge "Bionic malloc debug: add a new option "abort_on_error""
diff --git a/libc/Android.bp b/libc/Android.bp
index 36a0507..6f2e347 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -2212,6 +2212,91 @@
},
}
+python_binary_host {
+ name: "genfunctosyscallnrs",
+ main: "tools/genfunctosyscallnrs.py",
+
+ srcs: [
+ "tools/genseccomp.py",
+ "tools/genfunctosyscallnrs.py",
+ "tools/gensyscalls.py",
+ ],
+
+ data: [
+ "kernel/uapi/**/*.h",
+ ],
+
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: false,
+ },
+ },
+}
+
+cc_genrule {
+ name: "func_to_syscall_nrs",
+ recovery_available: true,
+ cmd: "$(location genfunctosyscallnrs) --out-dir=$(genDir) $(in)",
+
+ tools: [ "genfunctosyscallnrs" ],
+
+ srcs: [
+ "SYSCALLS.TXT",
+ ":libseccomp_gen_syscall_nrs_arm",
+ ":libseccomp_gen_syscall_nrs_arm64",
+ ":libseccomp_gen_syscall_nrs_mips",
+ ":libseccomp_gen_syscall_nrs_mips64",
+ ":libseccomp_gen_syscall_nrs_x86",
+ ":libseccomp_gen_syscall_nrs_x86_64",
+ ],
+
+ out: [
+ "func_to_syscall_nrs.h",
+ ],
+}
+
+// SECCOMP_BLACKLIST_APP_ZYGOTE.TXT = SECCOMP_BLACKLIST_APP.txt - setresgid*
+genrule {
+ name: "generate_app_zygote_blacklist",
+ out: ["SECCOMP_BLACKLIST_APP_ZYGOTE.TXT"],
+ srcs: ["SECCOMP_BLACKLIST_APP.TXT"],
+ cmd: "grep -v '^int[ \t]*setresgid' $(in) > $(out)",
+}
+
+cc_genrule {
+ name: "libseccomp_policy_app_zygote_sources",
+ recovery_available: true,
+ cmd: "$(location genseccomp) --out-dir=$(genDir) --name-modifier=app_zygote $(in)",
+
+ tools: [ "genseccomp" ],
+
+ srcs: [
+ "SYSCALLS.TXT",
+ "SECCOMP_WHITELIST_COMMON.TXT",
+ "SECCOMP_WHITELIST_APP.TXT",
+ "SECCOMP_BLACKLIST_COMMON.TXT",
+ ":generate_app_zygote_blacklist",
+ ":libseccomp_gen_syscall_nrs_arm",
+ ":libseccomp_gen_syscall_nrs_arm64",
+ ":libseccomp_gen_syscall_nrs_mips",
+ ":libseccomp_gen_syscall_nrs_mips64",
+ ":libseccomp_gen_syscall_nrs_x86",
+ ":libseccomp_gen_syscall_nrs_x86_64",
+ ],
+
+ out: [
+ "arm64_app_zygote_policy.cpp",
+ "arm_app_zygote_policy.cpp",
+ "mips64_app_zygote_policy.cpp",
+ "mips_app_zygote_policy.cpp",
+ "x86_64_app_zygote_policy.cpp",
+ "x86_app_zygote_policy.cpp",
+ ],
+}
+
cc_genrule {
name: "libseccomp_policy_app_sources",
recovery_available: true,
@@ -2308,8 +2393,10 @@
cc_library {
name: "libseccomp_policy",
recovery_available: true,
+ generated_headers: ["func_to_syscall_nrs"],
generated_sources: [
"libseccomp_policy_app_sources",
+ "libseccomp_policy_app_zygote_sources",
"libseccomp_policy_global_sources",
"libseccomp_policy_system_sources",
],
diff --git a/libc/seccomp/include/seccomp_policy.h b/libc/seccomp/include/seccomp_policy.h
index 49280f4..fd0fb60 100644
--- a/libc/seccomp/include/seccomp_policy.h
+++ b/libc/seccomp/include/seccomp_policy.h
@@ -17,8 +17,14 @@
#pragma once
#include <stddef.h>
+#include <stdint.h>
#include <linux/filter.h>
bool set_app_seccomp_filter();
+bool set_app_zygote_seccomp_filter();
bool set_system_seccomp_filter();
bool set_global_seccomp_filter();
+
+// Installs a filter that limits setresuid/setresgid to a range of
+// [uid_gid_min..uid_gid_max] (for the real-, effective- and super-ids).
+bool install_setuidgid_seccomp_filter(uint32_t uid_gid_min, uint32_t uid_gid_max);
diff --git a/libc/seccomp/seccomp_bpfs.h b/libc/seccomp/seccomp_bpfs.h
index 797dfc5..d9e8047 100644
--- a/libc/seccomp/seccomp_bpfs.h
+++ b/libc/seccomp/seccomp_bpfs.h
@@ -21,6 +21,8 @@
extern const struct sock_filter arm_app_filter[];
extern const size_t arm_app_filter_size;
+extern const struct sock_filter arm_app_zygote_filter[];
+extern const size_t arm_app_zygote_filter_size;
extern const struct sock_filter arm_system_filter[];
extern const size_t arm_system_filter_size;
extern const struct sock_filter arm_global_filter[];
@@ -28,6 +30,8 @@
extern const struct sock_filter arm64_app_filter[];
extern const size_t arm64_app_filter_size;
+extern const struct sock_filter arm64_app_zygote_filter[];
+extern const size_t arm64_app_zygote_filter_size;
extern const struct sock_filter arm64_system_filter[];
extern const size_t arm64_system_filter_size;
extern const struct sock_filter arm64_global_filter[];
@@ -35,6 +39,8 @@
extern const struct sock_filter x86_app_filter[];
extern const size_t x86_app_filter_size;
+extern const struct sock_filter x86_app_zygote_filter[];
+extern const size_t x86_app_zygote_filter_size;
extern const struct sock_filter x86_system_filter[];
extern const size_t x86_system_filter_size;
extern const struct sock_filter x86_global_filter[];
@@ -42,6 +48,8 @@
extern const struct sock_filter x86_64_app_filter[];
extern const size_t x86_64_app_filter_size;
+extern const struct sock_filter x86_64_app_zygote_filter[];
+extern const size_t x86_64_app_zygote_filter_size;
extern const struct sock_filter x86_64_system_filter[];
extern const size_t x86_64_system_filter_size;
extern const struct sock_filter x86_64_global_filter[];
@@ -49,6 +57,8 @@
extern const struct sock_filter mips_app_filter[];
extern const size_t mips_app_filter_size;
+extern const struct sock_filter mips_app_zygote_filter[];
+extern const size_t mips_app_zygote_filter_size;
extern const struct sock_filter mips_system_filter[];
extern const size_t mips_system_filter_size;
extern const struct sock_filter mips_global_filter[];
@@ -56,6 +66,8 @@
extern const struct sock_filter mips64_app_filter[];
extern const size_t mips64_app_filter_size;
+extern const struct sock_filter mips64_app_zygote_filter[];
+extern const size_t mips64_app_zygote_filter_size;
extern const struct sock_filter mips64_system_filter[];
extern const size_t mips64_system_filter_size;
extern const struct sock_filter mips64_global_filter[];
diff --git a/libc/seccomp/seccomp_policy.cpp b/libc/seccomp/seccomp_policy.cpp
index 3d617be..222a2c8 100644
--- a/libc/seccomp/seccomp_policy.cpp
+++ b/libc/seccomp/seccomp_policy.cpp
@@ -20,78 +20,111 @@
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <sys/prctl.h>
+#include <sys/syscall.h>
#include <vector>
#include <android-base/logging.h>
+#include "func_to_syscall_nrs.h"
#include "seccomp_bpfs.h"
-
#if defined __arm__ || defined __aarch64__
#define DUAL_ARCH
#define PRIMARY_ARCH AUDIT_ARCH_AARCH64
static const struct sock_filter* primary_app_filter = arm64_app_filter;
static const size_t primary_app_filter_size = arm64_app_filter_size;
+static const struct sock_filter* primary_app_zygote_filter = arm64_app_zygote_filter;
+static const size_t primary_app_zygote_filter_size = arm64_app_zygote_filter_size;
static const struct sock_filter* primary_system_filter = arm64_system_filter;
static const size_t primary_system_filter_size = arm64_system_filter_size;
static const struct sock_filter* primary_global_filter = arm64_global_filter;
static const size_t primary_global_filter_size = arm64_global_filter_size;
+
+static const long primary_setresgid = __arm64_setresgid;
+static const long primary_setresuid = __arm64_setresuid;
#define SECONDARY_ARCH AUDIT_ARCH_ARM
static const struct sock_filter* secondary_app_filter = arm_app_filter;
static const size_t secondary_app_filter_size = arm_app_filter_size;
+static const struct sock_filter* secondary_app_zygote_filter = arm_app_zygote_filter;
+static const size_t secondary_app_zygote_filter_size = arm_app_zygote_filter_size;
static const struct sock_filter* secondary_system_filter = arm_system_filter;
static const size_t secondary_system_filter_size = arm_system_filter_size;
static const struct sock_filter* secondary_global_filter = arm_global_filter;
static const size_t secondary_global_filter_size = arm_global_filter_size;
+static const long secondary_setresgid = __arm_setresgid;
+static const long secondary_setresuid = __arm_setresuid;
#elif defined __i386__ || defined __x86_64__
#define DUAL_ARCH
#define PRIMARY_ARCH AUDIT_ARCH_X86_64
static const struct sock_filter* primary_app_filter = x86_64_app_filter;
static const size_t primary_app_filter_size = x86_64_app_filter_size;
+static const struct sock_filter* primary_app_zygote_filter = x86_64_app_zygote_filter;
+static const size_t primary_app_zygote_filter_size = x86_64_app_zygote_filter_size;
static const struct sock_filter* primary_system_filter = x86_64_system_filter;
static const size_t primary_system_filter_size = x86_64_system_filter_size;
static const struct sock_filter* primary_global_filter = x86_64_global_filter;
static const size_t primary_global_filter_size = x86_64_global_filter_size;
+
+static const long primary_setresgid = __x86_64_setresgid;
+static const long primary_setresuid = __x86_64_setresuid;
#define SECONDARY_ARCH AUDIT_ARCH_I386
static const struct sock_filter* secondary_app_filter = x86_app_filter;
static const size_t secondary_app_filter_size = x86_app_filter_size;
+static const struct sock_filter* secondary_app_zygote_filter = x86_app_zygote_filter;
+static const size_t secondary_app_zygote_filter_size = x86_app_zygote_filter_size;
static const struct sock_filter* secondary_system_filter = x86_system_filter;
static const size_t secondary_system_filter_size = x86_system_filter_size;
static const struct sock_filter* secondary_global_filter = x86_global_filter;
static const size_t secondary_global_filter_size = x86_global_filter_size;
+static const long secondary_setresgid = __x86_setresgid;
+static const long secondary_setresuid = __x86_setresuid;
#elif defined __mips__ || defined __mips64__
#define DUAL_ARCH
#define PRIMARY_ARCH AUDIT_ARCH_MIPSEL64
static const struct sock_filter* primary_app_filter = mips64_app_filter;
static const size_t primary_app_filter_size = mips64_app_filter_size;
+static const struct sock_filter* primary_app_zygote_filter = mips64_app_zygote_filter;
+static const size_t primary_app_zygote_filter_size = mips64_app_zygote_filter_size;
static const struct sock_filter* primary_system_filter = mips64_system_filter;
static const size_t primary_system_filter_size = mips64_system_filter_size;
static const struct sock_filter* primary_global_filter = mips64_global_filter;
static const size_t primary_global_filter_size = mips64_global_filter_size;
+
+static const long primary_setresgid = __mips64_setresgid;
+static const long primary_setresuid = __mips64_setresuid;
#define SECONDARY_ARCH AUDIT_ARCH_MIPSEL
static const struct sock_filter* secondary_app_filter = mips_app_filter;
static const size_t secondary_app_filter_size = mips_app_filter_size;
+static const struct sock_filter* secondary_app_zygote_filter = mips_app_zygote_filter;
+static const size_t secondary_app_zygote_filter_size = mips_app_zygote_filter_size;
static const struct sock_filter* secondary_system_filter = mips_system_filter;
static const size_t secondary_system_filter_size = mips_system_filter_size;
static const struct sock_filter* secondary_global_filter = mips_global_filter;
static const size_t secondary_global_filter_size = mips_global_filter_size;
+static const long secondary_setresgid = __mips_setresgid;
+static const long secondary_setresuid = __mips_setresuid;
#else
#error No architecture was defined!
#endif
#define syscall_nr (offsetof(struct seccomp_data, nr))
+#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
#define arch_nr (offsetof(struct seccomp_data, arch))
typedef std::vector<sock_filter> filter;
+inline void Allow(filter& f) {
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW));
+}
+
inline void Disallow(filter& f) {
f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP));
}
@@ -128,6 +161,49 @@
}
#endif
+static void ValidateSyscallArgInRange(filter& f, __u32 arg_num, __u32 range_min, __u32 range_max) {
+ const __u32 syscall_arg = syscall_arg(arg_num);
+
+ if (range_max == UINT32_MAX) {
+ LOG(FATAL) << "range_max exceeds maximum argument range.";
+ return;
+ }
+
+ f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg));
+ f.push_back(BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, range_min, 0, 1));
+ f.push_back(BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, range_max + 1, 0, 1));
+ Disallow(f);
+}
+
+// This filter is meant to be installed in addition to a regular whitelist filter.
+// Therefore, it's default action has to be Allow, except when the evaluated
+// system call matches setresuid/setresgid and the arguments don't fall within the
+// passed in range.
+//
+// The regular whitelist only allows setresuid/setresgid for UID/GID changes, so
+// that's the only system call we need to check here. A CTS test ensures the other
+// calls will remain blocked.
+static void ValidateSetUidGid(filter& f, uint32_t uid_gid_min, uint32_t uid_gid_max, bool primary) {
+ // Check setresuid(ruid, euid, sguid) fall within range
+ ExamineSyscall(f);
+ __u32 setresuid_nr = primary ? primary_setresuid : secondary_setresuid;
+ f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, setresuid_nr, 0, 12));
+ for (int arg = 0; arg < 3; arg++) {
+ ValidateSyscallArgInRange(f, arg, uid_gid_min, uid_gid_max);
+ }
+
+ // Check setresgid(rgid, egid, sgid) fall within range
+ ExamineSyscall(f);
+ __u32 setresgid_nr = primary ? primary_setresgid : secondary_setresgid;
+ f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, setresgid_nr, 0, 12));
+ for (int arg = 0; arg < 3; arg++) {
+ ValidateSyscallArgInRange(f, arg, uid_gid_min, uid_gid_max);
+ }
+
+ // Default is to allow; other filters may still reject this call.
+ Allow(f);
+}
+
static bool install_filter(filter const& f) {
struct sock_fprog prog = {
static_cast<unsigned short>(f.size()),
@@ -141,8 +217,33 @@
return true;
}
+bool _install_setuidgid_filter(uint32_t uid_gid_min, uint32_t uid_gid_max) {
+ filter f;
+#ifdef DUAL_ARCH
+ // 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
+ auto offset_to_secondary_filter = ValidateArchitectureAndJumpIfNeeded(f);
+#else
+ ValidateArchitecture(f);
+#endif
+
+ ValidateSetUidGid(f, uid_gid_min, uid_gid_max, true /* primary */);
+
+#ifdef DUAL_ARCH
+ if (!SetValidateArchitectureJumpTarget(offset_to_secondary_filter, f)) {
+ return false;
+ }
+
+ ValidateSetUidGid(f, uid_gid_min, uid_gid_max, false /* primary */);
+#endif
+
+ return install_filter(f);
+}
+
enum FilterType {
APP,
+ APP_ZYGOTE,
SYSTEM,
GLOBAL
};
@@ -159,6 +260,12 @@
s = secondary_app_filter;
s_size = secondary_app_filter_size;
break;
+ case APP_ZYGOTE:
+ p = primary_app_zygote_filter;
+ p_size = primary_app_zygote_filter_size;
+ s = secondary_app_zygote_filter;
+ s_size = secondary_app_zygote_filter_size;
+ break;
case SYSTEM:
p = primary_system_filter;
p_size = primary_system_filter_size;
@@ -210,6 +317,10 @@
return _set_seccomp_filter(FilterType::APP);
}
+bool set_app_zygote_seccomp_filter() {
+ return _set_seccomp_filter(FilterType::APP_ZYGOTE);
+}
+
bool set_system_seccomp_filter() {
return _set_seccomp_filter(FilterType::SYSTEM);
}
@@ -217,3 +328,7 @@
bool set_global_seccomp_filter() {
return _set_seccomp_filter(FilterType::GLOBAL);
}
+
+bool install_setuidgid_seccomp_filter(uint32_t uid_gid_min, uint32_t uid_gid_max) {
+ return _install_setuidgid_filter(uid_gid_min, uid_gid_max);
+}
diff --git a/libc/tools/genfunctosyscallnrs.py b/libc/tools/genfunctosyscallnrs.py
new file mode 100755
index 0000000..6a456f2
--- /dev/null
+++ b/libc/tools/genfunctosyscallnrs.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+
+import argparse
+import collections
+import logging
+import os
+import re
+import subprocess
+import textwrap
+
+from gensyscalls import SysCallsTxtParser
+from genseccomp import parse_syscall_NRs
+
+def load_syscall_names_from_file(file_path, architecture):
+ parser = SysCallsTxtParser()
+ parser.parse_open_file(open(file_path))
+ arch_map = {}
+ for syscall in parser.syscalls:
+ if syscall.get(architecture):
+ arch_map[syscall["func"]] = syscall["name"];
+
+ return arch_map
+
+def gen_syscall_nrs(out_file, base_syscall_file, syscall_NRs):
+ for arch in ('arm', 'arm64', 'mips', 'mips64', 'x86', 'x86_64'):
+ base_names = load_syscall_names_from_file(base_syscall_file, arch)
+
+ for func,syscall in base_names.iteritems():
+ out_file.write("#define __" + arch + "_" + func + " " + str(syscall_NRs[arch][syscall]) + ";\n")
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Generates a mapping of bionic functions to system call numbers per architecture.")
+ parser.add_argument("--verbose", "-v", help="Enables verbose logging.")
+ parser.add_argument("--out-dir",
+ help="The output directory for the output files")
+ parser.add_argument("base_file", metavar="base-file", type=str,
+ help="The path of the base syscall list (SYSCALLS.TXT).")
+ parser.add_argument("files", metavar="FILE", type=str, nargs="+",
+ help=("A syscall name-number mapping file for an architecture.\n"))
+ args = parser.parse_args()
+
+ if args.verbose:
+ logging.basicConfig(level=logging.DEBUG)
+ else:
+ logging.basicConfig(level=logging.INFO)
+
+ syscall_files = []
+ syscall_NRs = {}
+ for filename in args.files:
+ m = re.search(r"libseccomp_gen_syscall_nrs_([^/]+)", filename)
+ syscall_NRs[m.group(1)] = parse_syscall_NRs(filename)
+
+ output_path = os.path.join(args.out_dir, "func_to_syscall_nrs.h")
+ with open(output_path, "w") as output_file:
+ gen_syscall_nrs(out_file=output_file,
+ syscall_NRs=syscall_NRs, base_syscall_file=args.base_file)
+
+if __name__ == "__main__":
+ main()