Require seccomp if we're running a 3.8 or greater kernel.
We'll be doing future work on seccomp, and third party applications,
such as Chrome on Android, need seccomp for sandboxing.
Seccomp can be enabled in the kernel by setting CONFIG_SECCOMP_FILTER=y
For kernels prior to 3.8, we don't require seccomp, as it would
require backporting work for kernel developers.
Bug: 16409560
Change-Id: I44b77510a46b2855a34e37b12ad56248d2f89657
diff --git a/tests/jni/android_os_cts_OSFeatures.cpp b/tests/jni/android_os_cts_OSFeatures.cpp
index 4ee8454..5f3ee4e 100644
--- a/tests/jni/android_os_cts_OSFeatures.cpp
+++ b/tests/jni/android_os_cts_OSFeatures.cpp
@@ -16,6 +16,17 @@
*/
#include <jni.h>
#include <sys/prctl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/wait.h>
jint android_os_cts_OSFeatures_getNoNewPrivs(JNIEnv* env, jobject thiz)
{
@@ -27,11 +38,82 @@
return prctl(PR_CAPBSET_READ, i, 0, 0, 0);
}
+#define DENY BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
+
+static void test_seccomp() {
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
+ _exit(0);
+ }
+
+ struct sock_filter filter[] = { DENY };
+ struct sock_fprog prog;
+ memset(&prog, 0, sizeof(prog));
+ prog.len = sizeof(filter) / sizeof(filter[0]);
+ prog.filter = filter;
+
+ if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) {
+ _exit(0);
+ }
+
+ while(1) {
+ _exit(0); // should crash with SIGSYS
+ }
+}
+
+jboolean android_os_cts_OSFeatures_hasSeccompSupport(JNIEnv* env, jobject)
+{
+ pid_t pid = fork();
+ if (pid == -1) {
+ jclass cls = env->FindClass("java/lang/RuntimeException");
+ env->ThrowNew(cls, "fork failed");
+ return false;
+ }
+ if (pid == 0) {
+ // child
+ test_seccomp();
+ _exit(0);
+ }
+
+ int status;
+ TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
+ return WIFSIGNALED(status) && (WTERMSIG(status) == SIGSYS);
+}
+
+jboolean android_os_cts_OSFeatures_needsSeccompSupport(JNIEnv*, jobject)
+{
+#if !defined(__arm__) && !defined(__i386__) && !defined(__x86_64__)
+ // Seccomp support is only available for ARM, x86, x86_64.
+ return false;
+#endif
+
+ int major;
+ int minor;
+ struct utsname uts;
+ if (uname(&uts) == -1) {
+ return false;
+ }
+
+ if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
+ return false;
+ }
+
+ // Kernels before 3.8 don't have seccomp
+ if ((major < 3) || ((major == 3) && (minor < 8))) {
+ return false;
+ }
+
+ return true;
+}
+
static JNINativeMethod gMethods[] = {
{ "getNoNewPrivs", "()I",
(void *) android_os_cts_OSFeatures_getNoNewPrivs },
{ "prctlCapBsetRead", "(I)I",
(void *) android_os_cts_OSFeatures_prctlCapBsetRead },
+ { "hasSeccompSupport", "()Z",
+ (void *) android_os_cts_OSFeatures_hasSeccompSupport },
+ { "needsSeccompSupport", "()Z",
+ (void *) android_os_cts_OSFeatures_needsSeccompSupport }
};
int register_android_os_cts_OSFeatures(JNIEnv* env)
diff --git a/tests/src/android/os/cts/OSFeatures.java b/tests/src/android/os/cts/OSFeatures.java
index fd30f58..59556db 100644
--- a/tests/src/android/os/cts/OSFeatures.java
+++ b/tests/src/android/os/cts/OSFeatures.java
@@ -23,4 +23,6 @@
public static native int getNoNewPrivs();
public static native int prctlCapBsetRead(int i);
+ public static native boolean hasSeccompSupport();
+ public static native boolean needsSeccompSupport();
}
diff --git a/tests/tests/os/src/android/os/cts/SeccompTest.java b/tests/tests/os/src/android/os/cts/SeccompTest.java
new file mode 100644
index 0000000..e2ddcc2
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/SeccompTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package android.os.cts;
+
+import junit.framework.TestCase;
+
+public class SeccompTest extends TestCase {
+
+ public void testSeccomp() {
+ if (CpuFeatures.isArm64Cpu()) {
+ return; // seccomp not supported on arm64
+ }
+ if (OSFeatures.needsSeccompSupport()) {
+ assertTrue("Please enable seccomp support "
+ + "in your kernel (CONFIG_SECCOMP_FILTER=y)",
+ OSFeatures.hasSeccompSupport());
+ }
+ }
+}