aboutsummaryrefslogtreecommitdiffstats
path: root/executor/common_linux.h
diff options
context:
space:
mode:
authormspectorgoogle <mspector@google.com>2020-03-11 03:21:36 -0700
committerGitHub <noreply@github.com>2020-03-11 11:21:36 +0100
commite103bc9e1bb4453045c4795f9a10a671e72b1aba (patch)
tree868db5bf000ed6e50ae36970f92abd4a6aebbd2e /executor/common_linux.h
parent35f53e457420e79fa28e3260cdbbf9f37b9f97e4 (diff)
executor: add seccomp support for Android
This adds support for the seccomp filters that are part of Android into the sandbox. A process running as untrusted_app in Android has a restricted set of syscalls that it is allow to run. This is accomplished by setting seccomp filters in the zygote process prior to forking into the application process. The seccomp filter list comes directly from the Android source, it cannot be dynamically loaded from an Android phone because libseccomp_policy.so does not exist as a library on the system partition.
Diffstat (limited to 'executor/common_linux.h')
-rw-r--r--executor/common_linux.h82
1 files changed, 62 insertions, 20 deletions
diff --git a/executor/common_linux.h b/executor/common_linux.h
index 148ca0c33..64dff5a15 100644
--- a/executor/common_linux.h
+++ b/executor/common_linux.h
@@ -2620,7 +2620,7 @@ int wait_for_loop(int pid)
}
#endif
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_NAMESPACE
+#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID
#include <linux/capability.h>
static void drop_caps(void)
@@ -2857,6 +2857,20 @@ static int do_sandbox_namespace(void)
#endif
#if SYZ_EXECUTOR || SYZ_SANDBOX_ANDROID
+// seccomp only supported for Arm, Arm64, X86, and X86_64 archs
+#if GOARCH_arm || GOARCH_arm64 || GOARCH_386 || GOARCH_amd64
+#include <assert.h>
+#include <errno.h>
+#include <linux/audit.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+
+#include "android/android_seccomp.h"
+#endif
#include <fcntl.h> // open(2)
#include <grp.h> // setgroups
#include <sys/xattr.h> // setxattr, getxattr
@@ -2969,6 +2983,20 @@ static int do_sandbox_android(void)
{
setup_common();
sandbox_common();
+ drop_caps();
+
+#if SYZ_EXECUTOR || SYZ_NET_DEVICES
+ initialize_netdevices_init();
+#endif
+#if SYZ_EXECUTOR || SYZ_DEVLINK_PCI
+ initialize_devlink_pci();
+#endif
+#if SYZ_EXECUTOR || SYZ_NET_INJECTION
+ initialize_tun();
+#endif
+#if SYZ_EXECUTOR || SYZ_NET_DEVICES
+ initialize_netdevices();
+#endif
if (chown(".", UNTRUSTED_APP_UID, UNTRUSTED_APP_UID) != 0)
fail("chmod failed");
@@ -2979,21 +3007,19 @@ static int do_sandbox_android(void)
if (setresgid(UNTRUSTED_APP_GID, UNTRUSTED_APP_GID, UNTRUSTED_APP_GID) != 0)
fail("setresgid failed");
+#if GOARCH_arm || GOARCH_arm64 || GOARCH_386 || GOARCH_amd64
+ // Will fail() if anything fails.
+ // Must be called when the new process still has CAP_SYS_ADMIN, in this case,
+ // before changing uid from 0, which clears capabilities.
+ set_app_seccomp_filter();
+#endif
+
if (setresuid(UNTRUSTED_APP_UID, UNTRUSTED_APP_UID, UNTRUSTED_APP_UID) != 0)
fail("setresuid failed");
syz_setfilecon(".", SELINUX_LABEL_APP_DATA_FILE);
syz_setcon(SELINUX_CONTEXT_UNTRUSTED_APP);
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
- initialize_tun();
-#endif
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES
- // Note: sandbox_android does not unshare net namespace.
- initialize_netdevices_init();
- initialize_netdevices();
-#endif
-
loop();
doexit(1);
}
@@ -3019,9 +3045,13 @@ static void remove_dir(const char* dir)
struct dirent* ep;
int iter = 0;
retry:
- while (umount2(dir, MNT_DETACH) == 0) {
- debug("umount(%s)\n", dir);
+#if not SYZ_SANDBOX_ANDROID
+ if (!flag_sandbox_android) {
+ while (umount2(dir, MNT_DETACH) == 0) {
+ debug("umount(%s)\n", dir);
+ }
}
+#endif
dp = opendir(dir);
if (dp == NULL) {
if (errno == EMFILE) {
@@ -3039,9 +3069,13 @@ retry:
snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
// If it's 9p mount with broken transport, lstat will fail.
// So try to umount first.
- while (umount2(filename, MNT_DETACH) == 0) {
- debug("umount(%s)\n", filename);
+#if not SYZ_SANDBOX_ANDROID
+ if (!flag_sandbox_android) {
+ while (umount2(filename, MNT_DETACH) == 0) {
+ debug("umount(%s)\n", filename);
+ }
}
+#endif
struct stat st;
if (lstat(filename, &st))
exitf("lstat(%s) failed", filename);
@@ -3071,9 +3105,13 @@ retry:
}
if (errno != EBUSY || i > 100)
exitf("unlink(%s) failed", filename);
- debug("umount(%s)\n", filename);
- if (umount2(filename, MNT_DETACH))
- exitf("umount(%s) failed", filename);
+#if not SYZ_SANDBOX_ANDROID
+ if (!flag_sandbox_android) {
+ debug("umount(%s)\n", filename);
+ if (umount2(filename, MNT_DETACH))
+ exitf("umount(%s) failed", filename);
+ }
+#endif
}
}
closedir(dp);
@@ -3099,9 +3137,13 @@ retry:
break;
}
if (errno == EBUSY) {
- debug("umount(%s)\n", dir);
- if (umount2(dir, MNT_DETACH))
- exitf("umount(%s) failed", dir);
+#if not SYZ_SANDBOX_ANDROID
+ if (!flag_sandbox_android) {
+ debug("umount(%s)\n", dir);
+ if (umount2(dir, MNT_DETACH))
+ exitf("umount(%s) failed", dir);
+ }
+#endif
continue;
}
if (errno == ENOTEMPTY) {