summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOrion Hodson <oth@google.com>2018-09-07 03:30:35 -0700
committerandroid-build-merger <android-build-merger@google.com>2018-09-07 03:30:35 -0700
commitbf7dac3f3d7910a7192e1612e03f527cb1565bf9 (patch)
treeb33f282a3ea237f280967c90dac3dfbc4fb81a29
parent94e787b83b04425f7af59621120445071bf89762 (diff)
parent3a1bae5cd84bcb8d655568aa9799dd5151791f51 (diff)
Merge "libc: Add membarrier to common seccomp allowed list" am: dca7d3fae5
am: 3a1bae5cd8 Change-Id: I5272122714ee2b5a9e57c14bb7c29bce0400b536
-rw-r--r--libc/SECCOMP_WHITELIST_COMMON.TXT3
-rw-r--r--tests/Android.bp1
-rw-r--r--tests/membarrier_test.cpp102
3 files changed, 106 insertions, 0 deletions
diff --git a/libc/SECCOMP_WHITELIST_COMMON.TXT b/libc/SECCOMP_WHITELIST_COMMON.TXT
index 60568e66d7..f6e9539600 100644
--- a/libc/SECCOMP_WHITELIST_COMMON.TXT
+++ b/libc/SECCOMP_WHITELIST_COMMON.TXT
@@ -59,6 +59,9 @@ int sigreturn:sigreturn(unsigned long __unused) arm,x86,mips
# already allowed.
ssize_t readlink:readlink(const char *path, char *buf, size_t bufsiz) arm,x86,x86_64,mips
+# Probed for and conditionally used by ART.
+int membarrier(int cmd, int flags) all
+
# Useful new syscalls which we don't yet use in bionic.
int sched_getattr(pid_t pid, struct sched_attr* attr, unsigned int flags) all
int sched_setattr(pid_t pid, struct sched_attr* attr, unsigned int size, unsigned int flags) all
diff --git a/tests/Android.bp b/tests/Android.bp
index fa66f93b00..ffa6b2a28a 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -104,6 +104,7 @@ cc_test_library {
"malloc_test.cpp",
"math_test.cpp",
"math_force_long_double_test.cpp",
+ "membarrier_test.cpp",
"mntent_test.cpp",
"netdb_test.cpp",
"net_if_test.cpp",
diff --git a/tests/membarrier_test.cpp b/tests/membarrier_test.cpp
new file mode 100644
index 0000000000..4c58d308ee
--- /dev/null
+++ b/tests/membarrier_test.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2018 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 <gtest/gtest.h>
+
+// membarrier(2) is only supported for bionic builds (b/111199492).
+#if defined(__BIONIC__)
+
+#include <linux/membarrier.h>
+#include <sys/syscall.h>
+
+class ScopedErrnoCleaner {
+ public:
+ ScopedErrnoCleaner() { errno = 0; }
+ ~ScopedErrnoCleaner() { errno = 0; }
+};
+
+bool HasMembarrier() {
+ ScopedErrnoCleaner errno_cleaner;
+ bool present = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0) > 0;
+ return present;
+}
+
+TEST(membarrier, query) {
+ ScopedErrnoCleaner errno_cleaner;
+ int supported = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
+ if (errno == 0) {
+ ASSERT_TRUE(supported >= 0);
+ } else {
+ ASSERT_TRUE(errno == ENOSYS && supported == -1);
+ }
+}
+
+TEST(membarrier, global_barrier) {
+ if (!HasMembarrier()) {
+ return;
+ }
+
+ ScopedErrnoCleaner errno_cleaner;
+ int supported = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
+ ASSERT_LE(0, supported);
+
+ if ((supported & MEMBARRIER_CMD_GLOBAL) != 0) {
+ ASSERT_EQ(0, syscall(__NR_membarrier, MEMBARRIER_CMD_GLOBAL, 0));
+ }
+}
+
+static void TestRegisterAndBarrierCommands(int membarrier_cmd_register,
+ int membarrier_cmd_barrier) {
+ if (!HasMembarrier()) {
+ return;
+ }
+
+ ScopedErrnoCleaner errno_cleaner;
+
+ // Check barrier use without prior registration.
+ if (membarrier_cmd_register == MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED) {
+ // Global barrier use is always okay.
+ ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
+ } else {
+ // Private barrier should fail.
+ ASSERT_EQ(-1, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
+ ASSERT_EQ(EPERM, errno);
+ errno = 0;
+ }
+
+ // Check registration for barrier succeeds.
+ ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_register, 0));
+
+ // Check barrier use after registration succeeds.
+ ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
+}
+
+TEST(membarrier, global_expedited) {
+ TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED,
+ MEMBARRIER_CMD_GLOBAL_EXPEDITED);
+}
+
+TEST(membarrier, private_expedited) {
+ TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED,
+ MEMBARRIER_CMD_PRIVATE_EXPEDITED);
+}
+
+TEST(membarrier, private_expedited_sync_core) {
+ TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE,
+ MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE);
+}
+
+#endif // __BIONIC__