diff options
Diffstat (limited to 'pkg/csource')
| -rw-r--r-- | pkg/csource/common.go | 54 | ||||
| -rw-r--r-- | pkg/csource/generated.go | 121 | ||||
| -rw-r--r-- | pkg/csource/options.go | 4 | ||||
| -rw-r--r-- | pkg/csource/options_test.go | 22 |
4 files changed, 167 insertions, 34 deletions
diff --git a/pkg/csource/common.go b/pkg/csource/common.go index 99537b233..80ce02ef6 100644 --- a/pkg/csource/common.go +++ b/pkg/csource/common.go @@ -19,9 +19,10 @@ import ( const ( linux = "linux" - sandboxNone = "none" - sandboxSetuid = "setuid" - sandboxNamespace = "namespace" + sandboxNone = "none" + sandboxSetuid = "setuid" + sandboxNamespace = "namespace" + sandboxAndroidUntrustedApp = "android_untrusted_app" ) func createCommonHeader(p, mmapProg *prog.Prog, replacements map[string]string, opts Options) ([]byte, error) { @@ -64,29 +65,30 @@ func defineList(p, mmapProg *prog.Prog, opts Options) (defines []string) { sysTarget := targets.Get(p.Target.OS, p.Target.Arch) bitmasks, csums := prog.RequiredFeatures(p) enabled := map[string]bool{ - "GOOS_" + p.Target.OS: true, - "GOARCH_" + p.Target.Arch: true, - "SYZ_USE_BITMASKS": bitmasks, - "SYZ_USE_CHECKSUMS": csums, - "SYZ_SANDBOX_NONE": opts.Sandbox == sandboxNone, - "SYZ_SANDBOX_SETUID": opts.Sandbox == sandboxSetuid, - "SYZ_SANDBOX_NAMESPACE": opts.Sandbox == sandboxNamespace, - "SYZ_THREADED": opts.Threaded, - "SYZ_COLLIDE": opts.Collide, - "SYZ_REPEAT": opts.Repeat, - "SYZ_REPEAT_TIMES": opts.RepeatTimes > 1, - "SYZ_PROCS": opts.Procs > 1, - "SYZ_FAULT_INJECTION": opts.Fault, - "SYZ_TUN_ENABLE": opts.EnableTun, - "SYZ_ENABLE_CGROUPS": opts.EnableCgroups, - "SYZ_ENABLE_NETDEV": opts.EnableNetdev, - "SYZ_RESET_NET_NAMESPACE": opts.ResetNet, - "SYZ_USE_TMP_DIR": opts.UseTmpDir, - "SYZ_HANDLE_SEGV": opts.HandleSegv, - "SYZ_REPRO": opts.Repro, - "SYZ_TRACE": opts.Trace, - "SYZ_EXECUTOR_USES_SHMEM": sysTarget.ExecutorUsesShmem, - "SYZ_EXECUTOR_USES_FORK_SERVER": sysTarget.ExecutorUsesForkServer, + "GOOS_" + p.Target.OS: true, + "GOARCH_" + p.Target.Arch: true, + "SYZ_USE_BITMASKS": bitmasks, + "SYZ_USE_CHECKSUMS": csums, + "SYZ_SANDBOX_NONE": opts.Sandbox == sandboxNone, + "SYZ_SANDBOX_SETUID": opts.Sandbox == sandboxSetuid, + "SYZ_SANDBOX_NAMESPACE": opts.Sandbox == sandboxNamespace, + "SYZ_SANDBOX_ANDROID_UNTRUSTED_APP": opts.Sandbox == sandboxAndroidUntrustedApp, + "SYZ_THREADED": opts.Threaded, + "SYZ_COLLIDE": opts.Collide, + "SYZ_REPEAT": opts.Repeat, + "SYZ_REPEAT_TIMES": opts.RepeatTimes > 1, + "SYZ_PROCS": opts.Procs > 1, + "SYZ_FAULT_INJECTION": opts.Fault, + "SYZ_TUN_ENABLE": opts.EnableTun, + "SYZ_ENABLE_CGROUPS": opts.EnableCgroups, + "SYZ_ENABLE_NETDEV": opts.EnableNetdev, + "SYZ_RESET_NET_NAMESPACE": opts.ResetNet, + "SYZ_USE_TMP_DIR": opts.UseTmpDir, + "SYZ_HANDLE_SEGV": opts.HandleSegv, + "SYZ_REPRO": opts.Repro, + "SYZ_TRACE": opts.Trace, + "SYZ_EXECUTOR_USES_SHMEM": sysTarget.ExecutorUsesShmem, + "SYZ_EXECUTOR_USES_FORK_SERVER": sysTarget.ExecutorUsesForkServer, } for def, ok := range enabled { if ok { diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go index 7b5d05f63..475982ae5 100644 --- a/pkg/csource/generated.go +++ b/pkg/csource/generated.go @@ -393,6 +393,7 @@ void child() #if SYZ_EXECUTOR #define do_sandbox_setuid() 0 #define do_sandbox_namespace() 0 +#define do_sandbox_android_untrusted_app() 0 #endif #elif GOOS_freebsd || GOOS_netbsd || GOOS_openbsd @@ -411,6 +412,7 @@ static int do_sandbox_none(void) #if SYZ_EXECUTOR #define do_sandbox_setuid() 0 #define do_sandbox_namespace() 0 +#define do_sandbox_android_untrusted_app() 0 #endif #if GOOS_openbsd @@ -682,6 +684,7 @@ static int do_sandbox_none(void) #if SYZ_EXECUTOR #define do_sandbox_setuid() 0 #define do_sandbox_namespace() 0 +#define do_sandbox_android_untrusted_app() 0 #endif #define CAST(f) ({void* p = (void*)f; p; }) @@ -1177,7 +1180,7 @@ static long syz_open_pts(long a0, long a1) #endif #if SYZ_EXECUTOR || __NR_syz_init_net_socket -#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE +#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID_UNTRUSTED_APP #include <fcntl.h> #include <sched.h> #include <sys/stat.h> @@ -2983,7 +2986,7 @@ static void setup_binfmt_misc() } #endif -#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE +#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID_UNTRUSTED_APP #include <errno.h> #include <sys/mount.h> @@ -2997,9 +3000,7 @@ static void setup_common() setup_binfmt_misc(); #endif } -#endif -#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE #include <sched.h> #include <sys/prctl.h> #include <sys/resource.h> @@ -3255,6 +3256,113 @@ static int do_sandbox_namespace(void) } #endif +#if SYZ_EXECUTOR || SYZ_SANDBOX_ANDROID_UNTRUSTED_APP +#include <fcntl.h> +#include <grp.h> +#include <sys/xattr.h> + +#define AID_NET_BT_ADMIN 3001 +#define AID_NET_BT 3002 +#define AID_INET 3003 +#define AID_EVERYBODY 9997 +#define AID_APP 10000 + +#define UNTRUSTED_APP_UID AID_APP + 999 +#define UNTRUSTED_APP_GID AID_APP + 999 + +const char* SELINUX_CONTEXT_UNTRUSTED_APP = "u:r:untrusted_app:s0:c512,c768"; +const char* SELINUX_LABEL_APP_DATA_FILE = "u:object_r:app_data_file:s0:c512,c768"; +const char* SELINUX_CONTEXT_FILE = "/proc/thread-self/attr/current"; +const char* SELINUX_XATTR_NAME = "security.selinux"; + +const gid_t UNTRUSTED_APP_GROUPS[] = {UNTRUSTED_APP_GID, AID_NET_BT_ADMIN, AID_NET_BT, AID_INET, AID_EVERYBODY}; +const size_t UNTRUSTED_APP_NUM_GROUPS = sizeof(UNTRUSTED_APP_GROUPS) / sizeof(UNTRUSTED_APP_GROUPS[0]); +static void syz_getcon(char* context, size_t context_size) +{ + int fd = open(SELINUX_CONTEXT_FILE, O_RDONLY); + + if (fd < 0) + fail("getcon: Couldn't open %s", SELINUX_CONTEXT_FILE); + + ssize_t nread = read(fd, context, context_size); + + close(fd); + + if (nread <= 0) + fail("getcon: Failed to read from %s", SELINUX_CONTEXT_FILE); + if (context[nread - 1] == '\n') + context[nread - 1] = '\0'; +} +static void syz_setcon(const char* context) +{ + char new_context[512]; + int fd = open(SELINUX_CONTEXT_FILE, O_WRONLY); + + if (fd < 0) + fail("setcon: Could not open %s", SELINUX_CONTEXT_FILE); + + ssize_t bytes_written = write(fd, context, strlen(context)); + close(fd); + + if (bytes_written != (ssize_t)strlen(context)) + fail("setcon: Could not write entire context. Wrote %zi, expected %zu", bytes_written, strlen(context)); + syz_getcon(new_context, sizeof(new_context)); + + if (strcmp(context, new_context) != 0) + fail("setcon: Failed to change to %s, context is %s", context, new_context); +} +static int syz_getfilecon(const char* path, char* context, size_t context_size) +{ + int length = getxattr(path, SELINUX_XATTR_NAME, context, context_size); + + if (length == -1) + fail("getfilecon: getxattr failed"); + + return length; +} +static void syz_setfilecon(const char* path, const char* context) +{ + char new_context[512]; + + if (setxattr(path, SELINUX_XATTR_NAME, context, strlen(context) + 1, 0) != 0) + fail("setfilecon: setxattr failed"); + + if (syz_getfilecon(path, new_context, sizeof(new_context)) != 0) + fail("setfilecon: getfilecon failed"); + + if (strcmp(context, new_context) != 0) + fail("setfilecon: could not set context to %s, currently %s", context, new_context); +} + +static int do_sandbox_android_untrusted_app(void) +{ + setup_common(); + sandbox_common(); + + if (setgroups(UNTRUSTED_APP_NUM_GROUPS, UNTRUSTED_APP_GROUPS) != 0) + fail("setgroups failed"); + + if (setresgid(UNTRUSTED_APP_GID, UNTRUSTED_APP_GID, UNTRUSTED_APP_GID) != 0) + fail("setresgid failed"); + + 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_TUN_ENABLE + initialize_tun(); +#endif +#if SYZ_EXECUTOR || SYZ_ENABLE_NETDEV + initialize_netdevices(); +#endif + + loop(); + doexit(1); +} +#endif + #if SYZ_EXECUTOR || SYZ_REPEAT && SYZ_USE_TMP_DIR #include <dirent.h> #include <errno.h> @@ -3623,6 +3731,7 @@ static int do_sandbox_none(void) #if SYZ_EXECUTOR #define do_sandbox_setuid() 0 #define do_sandbox_namespace() 0 +#define do_sandbox_android_untrusted_app() 0 #endif #elif GOOS_windows @@ -3739,6 +3848,7 @@ static int do_sandbox_none(void) #if SYZ_EXECUTOR #define do_sandbox_setuid() 0 #define do_sandbox_namespace() 0 +#define do_sandbox_android_untrusted_app() 0 #endif #elif GOOS_test @@ -3794,6 +3904,7 @@ static int do_sandbox_none(void) #if SYZ_EXECUTOR #define do_sandbox_setuid() 0 #define do_sandbox_namespace() 0 +#define do_sandbox_android_untrusted_app() 0 #endif #else @@ -4015,7 +4126,7 @@ static void loop(void) [[RESULTS]] -#if SYZ_THREADED || SYZ_REPEAT || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE +#if SYZ_THREADED || SYZ_REPEAT || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID_UNTRUSTED_APP #if SYZ_THREADED void execute_call(int call) #elif SYZ_REPEAT diff --git a/pkg/csource/options.go b/pkg/csource/options.go index a43774bf6..6dc3a249e 100644 --- a/pkg/csource/options.go +++ b/pkg/csource/options.go @@ -45,7 +45,7 @@ type Options struct { // Invalid combinations must not be passed to Write. func (opts Options) Check(OS string) error { switch opts.Sandbox { - case "", sandboxNone, sandboxNamespace, sandboxSetuid: + case "", sandboxNone, sandboxNamespace, sandboxSetuid, sandboxAndroidUntrustedApp: default: return fmt.Errorf("unknown sandbox %v", opts.Sandbox) } @@ -107,7 +107,7 @@ func (opts Options) checkLinuxOnly(OS string) error { if opts.ResetNet { return fmt.Errorf("ResetNet is not supported on %v", OS) } - if opts.Sandbox == sandboxNamespace || opts.Sandbox == sandboxSetuid { + if opts.Sandbox == sandboxNamespace || opts.Sandbox == sandboxSetuid || opts.Sandbox == sandboxAndroidUntrustedApp { return fmt.Errorf("Sandbox=%v is not supported on %v", opts.Sandbox, OS) } if opts.Fault { diff --git a/pkg/csource/options_test.go b/pkg/csource/options_test.go index 61ebe5827..d8e8a217e 100644 --- a/pkg/csource/options_test.go +++ b/pkg/csource/options_test.go @@ -47,6 +47,26 @@ func TestParseOptionsCanned(t *testing.T) { HandleSegv: true, Repro: true, }, + `{"threaded":true,"collide":true,"repeat":true,"procs":10,"sandbox":"android_untrusted_app", + "fault":true,"fault_call":1,"fault_nth":2,"tun":true,"tmpdir":true,"cgroups":true, + "netdev":true,"resetnet":true, + "segv":true,"waitrepeat":true,"debug":true,"repro":true}`: { + Threaded: true, + Collide: true, + Repeat: true, + Procs: 10, + Sandbox: "android_untrusted_app", + Fault: true, + FaultCall: 1, + FaultNth: 2, + EnableTun: true, + UseTmpDir: true, + EnableCgroups: true, + EnableNetdev: true, + ResetNet: true, + HandleSegv: true, + Repro: true, + }, "{Threaded:true Collide:true Repeat:true Procs:1 Sandbox:none Fault:false FaultCall:-1 FaultNth:0 EnableTun:true UseTmpDir:true HandleSegv:true WaitRepeat:true Debug:false Repro:false}": { Threaded: true, Collide: true, @@ -140,7 +160,7 @@ func enumerateField(OS string, opt Options, field int) []Options { fldName := s.Type().Field(field).Name fld := s.Field(field) if fldName == "Sandbox" { - for _, sandbox := range []string{"", "none", "setuid", "namespace"} { + for _, sandbox := range []string{"", "none", "setuid", "namespace", "android_untrusted_app"} { fld.SetString(sandbox) opts = append(opts, opt) } |
