Merge "Expand a little on the time_t situation."
diff --git a/apex/Android.bp b/apex/Android.bp
index f6820d1..8c8853f 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -37,3 +37,28 @@
key: "com.android.runtime.key",
certificate: ":com.android.runtime.certificate",
}
+
+sdk {
+ name: "runtime-module-sdk",
+ defaults: ["linux_bionic_supported"],
+
+ native_header_libs: [
+ "bionic_libc_platform_headers",
+ "libc_headers",
+ ],
+ native_shared_libs: [
+ "libc",
+ "libdl",
+ "libdl_android",
+ "libm",
+ ],
+ native_static_libs: [
+ "libasync_safe",
+ ],
+ native_objects: [
+ "crtbegin_dynamic",
+ "crtbegin_so",
+ "crtend_android",
+ "crtend_so",
+ ],
+}
diff --git a/libc/Android.bp b/libc/Android.bp
index 7614784..ff3b3b1 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -2387,6 +2387,7 @@
"SECCOMP_WHITELIST_COMMON.TXT",
"SECCOMP_WHITELIST_APP.TXT",
"SECCOMP_BLACKLIST_COMMON.TXT",
+ "SECCOMP_PRIORITY.TXT",
":generate_app_zygote_blacklist",
":libseccomp_gen_syscall_nrs_arm",
":libseccomp_gen_syscall_nrs_arm64",
@@ -2415,6 +2416,7 @@
"SECCOMP_WHITELIST_APP.TXT",
"SECCOMP_BLACKLIST_COMMON.TXT",
"SECCOMP_BLACKLIST_APP.TXT",
+ "SECCOMP_PRIORITY.TXT",
":libseccomp_gen_syscall_nrs_arm",
":libseccomp_gen_syscall_nrs_arm64",
":libseccomp_gen_syscall_nrs_x86",
@@ -2441,6 +2443,7 @@
"SECCOMP_WHITELIST_COMMON.TXT",
"SECCOMP_WHITELIST_SYSTEM.TXT",
"SECCOMP_BLACKLIST_COMMON.TXT",
+ "SECCOMP_PRIORITY.TXT",
":libseccomp_gen_syscall_nrs_arm",
":libseccomp_gen_syscall_nrs_arm64",
":libseccomp_gen_syscall_nrs_x86",
@@ -2548,7 +2551,7 @@
"//apex_available:platform",
"com.android.media.swcodec",
],
- min_sdk_version: "29",
+ min_sdk_version: "apex_inherit",
}
subdirs = [
diff --git a/libc/SECCOMP_PRIORITY.TXT b/libc/SECCOMP_PRIORITY.TXT
new file mode 100644
index 0000000..fb5ad4a
--- /dev/null
+++ b/libc/SECCOMP_PRIORITY.TXT
@@ -0,0 +1,10 @@
+# This file is used to populate seccomp's whitelist policy in combination with SYSCALLS.TXT.
+# Note that the resultant policy is applied only to zygote spawned processes.
+#
+# This file is processed by a python script named genseccomp.py.
+#
+# The syscalls below are prioritized above other syscalls when checking seccomp policy, in
+# the order of appearance in this file.
+
+futex
+ioctl
\ No newline at end of file
diff --git a/libc/tools/genseccomp.py b/libc/tools/genseccomp.py
index cc0ff99..ba7e2ca 100755
--- a/libc/tools/genseccomp.py
+++ b/libc/tools/genseccomp.py
@@ -12,6 +12,7 @@
BPF_JGE = "BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, {0}, {1}, {2})"
+BPF_JEQ = "BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, {0}, {1}, {2})"
BPF_ALLOW = "BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW)"
@@ -37,6 +38,24 @@
return set([x["name"] for x in parser.syscalls if x.get(architecture)])
+def load_syscall_priorities_from_file(file_path):
+ format_re = re.compile(r'^\s*([A-Za-z_][A-Za-z0-9_]+)\s*$')
+ priorities = []
+ with open(file_path) as f:
+ for line in f:
+ m = format_re.match(line)
+ if not m:
+ continue
+ try:
+ name = m.group(1)
+ priorities.append(name)
+ except:
+ logging.debug('Failed to parse %s from %s', (line, file_path))
+ pass
+
+ return priorities
+
+
def merge_names(base_names, whitelist_names, blacklist_names):
if bool(blacklist_names - base_names):
raise RuntimeError("Blacklist item not in bionic - aborting " + str(
@@ -45,6 +64,20 @@
return (base_names - blacklist_names) | whitelist_names
+def extract_priority_syscalls(syscalls, priorities):
+ # Extract syscalls that are not in the priority list
+ other_syscalls = \
+ [syscall for syscall in syscalls if syscall[0] not in priorities]
+ # For prioritized syscalls, keep the order in which they appear in th
+ # priority list
+ syscall_dict = {syscall[0]: syscall[1] for syscall in syscalls}
+ priority_syscalls = []
+ for name in priorities:
+ if name in syscall_dict.keys():
+ priority_syscalls.append((name, syscall_dict[name]))
+ return priority_syscalls, other_syscalls
+
+
def parse_syscall_NRs(names_path):
# The input is now the preprocessed source file. This will contain a lot
# of junk from the preprocessor, but our lines will be in the format:
@@ -123,8 +156,21 @@
return jump + first + second
-def convert_ranges_to_bpf(ranges):
- bpf = convert_to_intermediate_bpf(ranges)
+# Converts the prioritized syscalls to a bpf list that is prepended to the
+# tree generated by convert_to_intermediate_bpf(). If we hit one of these
+# syscalls, shortcut to the allow statement at the bottom of the tree
+# immediately
+def convert_priority_to_intermediate_bpf(priority_syscalls):
+ result = []
+ for i, syscall in enumerate(priority_syscalls):
+ result.append(BPF_JEQ.format(syscall[1], "{allow}", 0) +
+ ", //" + syscall[0])
+ return result
+
+
+def convert_ranges_to_bpf(ranges, priority_syscalls):
+ bpf = convert_priority_to_intermediate_bpf(priority_syscalls) + \
+ convert_to_intermediate_bpf(ranges)
# Now we know the size of the tree, we can substitute the {fail} and {allow}
# placeholders
@@ -135,9 +181,8 @@
# With bpfs jmp 0 means the next statement, so the distance to the end is
# len(bpf) - i - 1, which is where we will put the kill statement, and
# then the statement after that is the allow statement
- if "{fail}" in statement and "{allow}" in statement:
- bpf[i] = statement.format(fail=str(len(bpf) - i),
- allow=str(len(bpf) - i - 1))
+ bpf[i] = statement.format(fail=str(len(bpf) - i),
+ allow=str(len(bpf) - i - 1))
# Add the allow calls at the end. If the syscall is not matched, we will
# continue. This allows the user to choose to match further syscalls, and
@@ -174,13 +219,15 @@
return header + "\n".join(bpf) + footer
-def construct_bpf(syscalls, architecture, name_modifier):
- ranges = convert_NRs_to_ranges(syscalls)
- bpf = convert_ranges_to_bpf(ranges)
+def construct_bpf(syscalls, architecture, name_modifier, priorities):
+ priority_syscalls, other_syscalls = \
+ extract_priority_syscalls(syscalls, priorities)
+ ranges = convert_NRs_to_ranges(other_syscalls)
+ bpf = convert_ranges_to_bpf(ranges, priority_syscalls)
return convert_bpf_to_output(bpf, architecture, name_modifier)
-def gen_policy(name_modifier, out_dir, base_syscall_file, syscall_files, syscall_NRs):
+def gen_policy(name_modifier, out_dir, base_syscall_file, syscall_files, syscall_NRs, priority_file):
for arch in SupportedArchitectures:
base_names = load_syscall_names_from_file(base_syscall_file, arch)
whitelist_names = set()
@@ -190,6 +237,9 @@
blacklist_names |= load_syscall_names_from_file(f, arch)
else:
whitelist_names |= load_syscall_names_from_file(f, arch)
+ priorities = []
+ if priority_file:
+ priorities = load_syscall_priorities_from_file(priority_file)
allowed_syscalls = []
for name in merge_names(base_names, whitelist_names, blacklist_names):
@@ -198,7 +248,7 @@
except:
logging.exception("Failed to find %s in %s", name, arch)
raise
- output = construct_bpf(allowed_syscalls, arch, name_modifier)
+ output = construct_bpf(allowed_syscalls, arch, name_modifier, priorities)
# And output policy
existing = ""
@@ -226,6 +276,7 @@
"following files: \n"
"* /blacklist.*\.txt$/ syscall blacklist.\n"
"* /whitelist.*\.txt$/ syscall whitelist.\n"
+ "* /priority.txt$/ priorities for bpf rules.\n"
"* otherwise, syscall name-number mapping.\n"))
args = parser.parse_args()
@@ -235,17 +286,21 @@
logging.basicConfig(level=logging.INFO)
syscall_files = []
+ priority_file = None
syscall_NRs = {}
for filename in args.files:
if filename.lower().endswith('.txt'):
- syscall_files.append(filename)
+ if filename.lower().endswith('priority.txt'):
+ priority_file = filename
+ else:
+ syscall_files.append(filename)
else:
m = re.search(r"libseccomp_gen_syscall_nrs_([^/]+)", filename)
syscall_NRs[m.group(1)] = parse_syscall_NRs(filename)
gen_policy(name_modifier=args.name_modifier, out_dir=args.out_dir,
syscall_NRs=syscall_NRs, base_syscall_file=args.base_file,
- syscall_files=args.files)
+ syscall_files=syscall_files, priority_file=priority_file)
if __name__ == "__main__":
diff --git a/linker/Android.bp b/linker/Android.bp
index 1792c74..08b2c7b 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -318,6 +318,10 @@
"linker_version_script_overlay",
],
+ srcs: [
+ "linker_translate_path.cpp",
+ ],
+
symlinks: ["linker_asan"],
multilib: {
lib64: {
diff --git a/linker/linker.cpp b/linker/linker.cpp
index b368e96..edf0329 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -65,6 +65,7 @@
#include "linker_phdr.h"
#include "linker_relocate.h"
#include "linker_tls.h"
+#include "linker_translate_path.h"
#include "linker_utils.h"
#include "private/bionic_call_ifunc_resolver.h"
@@ -103,7 +104,6 @@
static const char* const kAsanSystemLibDir = "/data/asan/system/lib64";
static const char* const kAsanOdmLibDir = "/data/asan/odm/lib64";
static const char* const kAsanVendorLibDir = "/data/asan/vendor/lib64";
-static const char* const kI18nApexLibDir = "/apex/com.android.i18n/lib64";
#else
static const char* const kSystemLibDir = "/system/lib";
static const char* const kOdmLibDir = "/odm/lib";
@@ -111,7 +111,6 @@
static const char* const kAsanSystemLibDir = "/data/asan/system/lib";
static const char* const kAsanOdmLibDir = "/data/asan/odm/lib";
static const char* const kAsanVendorLibDir = "/data/asan/vendor/lib";
-static const char* const kI18nApexLibDir = "/apex/com.android.i18n/lib";
#endif
static const char* const kAsanLibDirPrefix = "/data/asan";
@@ -235,44 +234,6 @@
}
// END OF WORKAROUND
-// Workaround for dlopen(/system/lib(64)/<soname>) when .so is in /apex. http://b/121248172
-/**
- * Translate /system path to /apex path if needed
- * The workaround should work only when targetSdkVersion < Q.
- *
- * param out_name_to_apex pointing to /apex path
- * return true if translation is needed
- */
-static bool translateSystemPathToApexPath(const char* name, std::string* out_name_to_apex) {
- static const char* const kSystemToArtApexLibs[] = {
- "libicuuc.so",
- "libicui18n.so",
- };
- // New mapping for new apex should be added below
-
- // Nothing to do if target sdk version is Q or above
- if (get_application_target_sdk_version() >= 29) {
- return false;
- }
-
- // If the path isn't /system/lib, there's nothing to do.
- if (name == nullptr || dirname(name) != kSystemLibDir) {
- return false;
- }
-
- const char* base_name = basename(name);
-
- for (const char* soname : kSystemToArtApexLibs) {
- if (strcmp(base_name, soname) == 0) {
- *out_name_to_apex = std::string(kI18nApexLibDir) + "/" + base_name;
- return true;
- }
- }
-
- return false;
-}
-// End Workaround for dlopen(/system/lib/<soname>) when .so is in /apex.
-
static std::vector<std::string> g_ld_preload_names;
static void notify_gdb_of_load(soinfo* info) {
diff --git a/linker/linker_translate_path.cpp b/linker/linker_translate_path.cpp
new file mode 100644
index 0000000..4f3fdfb
--- /dev/null
+++ b/linker/linker_translate_path.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker.h"
+#include "linker_translate_path.h"
+#include "linker_utils.h"
+
+#if defined(__LP64__)
+#define APEX_LIB(apex, name) \
+ { "/system/lib64/" name, "/apex/" apex "/lib64/" name }
+#else
+#define APEX_LIB(apex, name) \
+ { "/system/lib/" name, "/apex/" apex "/lib/" name }
+#endif
+
+
+// Workaround for dlopen(/system/lib(64)/<soname>) when .so is in /apex. http://b/121248172
+/**
+ * Translate /system path to /apex path if needed
+ * The workaround should work only when targetSdkVersion < Q.
+ *
+ * param out_name_to_apex pointing to /apex path
+ * return true if translation is needed
+ */
+bool translateSystemPathToApexPath(const char* name, std::string* out_name_to_apex) {
+ static constexpr const char* kPathTranslationQ[][2] = {
+ APEX_LIB("com.android.i18n", "libicui18n.so"),
+ APEX_LIB("com.android.i18n", "libicuuc.so")
+ };
+
+ if (name == nullptr) {
+ return false;
+ }
+
+ auto comparator = [name](auto p) { return strcmp(name, p[0]) == 0; };
+
+ if (get_application_target_sdk_version() < __ANDROID_API_Q__) {
+ if (auto it =
+ std::find_if(std::begin(kPathTranslationQ), std::end(kPathTranslationQ), comparator);
+ it != std::end(kPathTranslationQ)) {
+ *out_name_to_apex = (*it)[1];
+ return true;
+ }
+ }
+
+ return false;
+}
+// End Workaround for dlopen(/system/lib/<soname>) when .so is in /apex.
diff --git a/linker/linker_translate_path.h b/linker/linker_translate_path.h
new file mode 100644
index 0000000..86a3ec1
--- /dev/null
+++ b/linker/linker_translate_path.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <string>
+
+bool translateSystemPathToApexPath(const char* name, std::string* out_name_to_apex);
diff --git a/tests/gtest_globals_cts.cpp b/tests/gtest_globals_cts.cpp
index 8e67f29..78bb3ca 100644
--- a/tests/gtest_globals_cts.cpp
+++ b/tests/gtest_globals_cts.cpp
@@ -16,17 +16,6 @@
#include "gtest_globals.h"
-#include <string>
-#include <vector>
-
-// Use the normal gtest format so that cts can parse the results.
-extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
- static const char* initial_args[] = {"--gtest_format"};
- *args = initial_args;
- *num_args = 1;
- return true;
-}
-
std::string GetTestlibRoot() {
return "/data/local/tmp/lib/bionic-loader-test-libs";
}