minijail: add seccomp softfail option

Minijail now softfails when seccomp is not implemented
by the OS. However if the USE_seccomp flag is defined,
minijail still hardfails.

BUG=chromium:368071
TEST=Manual: compiled with and without USE flag.
CQ-DEPEND=CL:212960

Change-Id: If2b58ddd5ce51a357bda325d32fe2b3dac6df11f
Reviewed-on: https://chromium-review.googlesource.com/212919
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Tested-by: Utkarsh Sanghi <usanghi@chromium.org>
Commit-Queue: Utkarsh Sanghi <usanghi@chromium.org>
diff --git a/Makefile b/Makefile
index d931df0..40d43bd 100644
--- a/Makefile
+++ b/Makefile
@@ -11,6 +11,9 @@
 ifneq ($(HAVE_SECUREBITS_H),no)
 CFLAGS += -DHAVE_SECUREBITS_H
 endif
+ifneq ($(USE_seccomp),yes)
+CFLAGS += -DUSE_SECCOMP_SOFTFAIL
+endif
 
 all : minijail0 libminijail.so libminijailpreload.so
 
diff --git a/libminijail.c b/libminijail.c
index 9fafc51..7a18831 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -61,6 +61,12 @@
 # define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
 #endif
 
+#ifdef USE_SECCOMP_SOFTFAIL
+# define SECCOMP_SOFTFAIL 1
+#else
+# define SECCOMP_SOFTFAIL 0
+#endif
+
 struct binding {
 	char *src;
 	char *dest;
@@ -355,6 +361,12 @@
 
 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) {
+			warn("not loading seccomp filter, seccomp not supported");
+			return;
+		}
+	}
 	FILE *file = fopen(path, "r");
 	if (!file) {
 		pdie("failed to open seccomp filter file '%s'", path);
@@ -754,8 +766,13 @@
 	 * Install the syscall filter.
 	 */
 	if (j->flags.seccomp_filter) {
-		if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, j->filter_prog))
+		if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, j->filter_prog)) {
+			if ((errno == ENOSYS) && SECCOMP_SOFTFAIL) {
+				warn("seccomp not supported");
+				return;
+			}
 			pdie("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER)");
+		}
 	}
 }
 
@@ -835,8 +852,13 @@
 	 * seccomp has to come last since it cuts off all the other
 	 * privilege-dropping syscalls :)
 	 */
-	if (j->flags.seccomp && prctl(PR_SET_SECCOMP, 1))
+	if (j->flags.seccomp && prctl(PR_SET_SECCOMP, 1)) {
+		if ((errno == ENOSYS) && SECCOMP_SOFTFAIL) {
+			warn("seccomp not supported");
+			return;
+		}
 		pdie("prctl(PR_SET_SECCOMP)");
+	}
 }
 
 /* TODO(wad) will visibility affect this variable? */