Merge "softfail on older kernels that lack seccomp support"
diff --git a/Android.mk b/Android.mk
index 702c04b..d3568f4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -27,6 +27,13 @@
 minijailCommonCFlags := -Wall -Werror
 minijailCommonLibraries := libcap
 
+# Android devices running kernel version < 3.8 are not required to
+# support seccomp. Brillo devices must support seccomp regardless of
+# kernel version.
+# TODO: remove when no longer supporting kernel versions < 3.8.
+ifndef BRILLO
+minijailCommonCFlags += -DUSE_SECCOMP_SOFTFAIL
+endif
 
 # Static library for generated code.
 # ========================================================
diff --git a/libminijail.c b/libminijail.c
index d492522..15ac5f7 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -31,6 +31,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/user.h>
+#include <sys/utsname.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
@@ -172,6 +173,34 @@
 	/* Note, |pids| will already have been used before this call. */
 }
 
+/* Return true if kernel version is less than 3.8. */
+static int seccomp_kernel_support_not_required()
+{
+	int major, minor;
+	struct utsname uts;
+	return (uname(&uts) != -1 &&
+			sscanf(uts.release, "%d.%d", &major, &minor) == 2 &&
+			((major < 3) || ((major == 3) && (minor < 8))));
+}
+
+/*
+ * Allow softfail on Android devices with kernel version < 3.8.
+ */
+static int can_softfail()
+{
+#if SECCOMP_SOFTFAIL
+	if (is_android()) {
+		if (seccomp_kernel_support_not_required())
+			return 1;
+		else
+			return 0;
+	} else {
+		return 1;
+	}
+#endif
+	return 0;
+}
+
 /* Minijail API. */
 
 struct minijail API *minijail_new(void)
@@ -562,10 +591,14 @@
 void API minijail_parse_seccomp_filters(struct minijail *j, const char *path)
 {
 	if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL)) {
-		if ((errno == ENOSYS) && SECCOMP_SOFTFAIL) {
+		if ((errno == EINVAL) && can_softfail()) {
 			warn("not loading seccomp filter,"
 			     " seccomp not supported");
-			return;
+			j->flags.seccomp_filter = 0;
+			j->flags.log_seccomp_filter = 0;
+			j->filter_len = 0;
+			j->filter_prog = NULL;
+			j->flags.no_new_privs = 0;
 		}
 	}
 	FILE *file = fopen(path, "r");
@@ -1187,7 +1220,7 @@
 	if (j->flags.seccomp_filter) {
 		if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER,
 			  j->filter_prog)) {
-			if ((errno == ENOSYS) && SECCOMP_SOFTFAIL) {
+			if ((errno == EINVAL) && can_softfail()) {
 				warn("seccomp not supported");
 				return;
 			}
@@ -1310,7 +1343,7 @@
 	 * privilege-dropping syscalls :)
 	 */
 	if (j->flags.seccomp && prctl(PR_SET_SECCOMP, 1)) {
-		if ((errno == ENOSYS) && SECCOMP_SOFTFAIL) {
+		if ((errno == EINVAL) && can_softfail()) {
 			warn("seccomp not supported");
 			return;
 		}