aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-07-10 16:18:45 +0200
committerDmitry Vyukov <dvyukov@google.com>2018-07-10 16:18:45 +0200
commit95e7a88b9746c73e727b94d85a626cf6dd612f16 (patch)
tree4b70e3e852520ceb6d9051457d4fea21221b5002 /pkg
parent01e35718418b9c51f079b62117aa984bb7e3568b (diff)
sys/linux: implement fuse as normal syscalls
Remove syz_fuse* and implement them as normal syscalls. We not have enough expressive power to form mount options.
Diffstat (limited to 'pkg')
-rw-r--r--pkg/csource/linux_common.go63
-rw-r--r--pkg/host/host_linux.go50
2 files changed, 33 insertions, 80 deletions
diff --git a/pkg/csource/linux_common.go b/pkg/csource/linux_common.go
index 35a652b49..27b09e8be 100644
--- a/pkg/csource/linux_common.go
+++ b/pkg/csource/linux_common.go
@@ -93,11 +93,6 @@ var commonHeaderLinux = `
#include <string.h>
#include <sys/stat.h>
#endif
-#if defined(SYZ_EXECUTOR) || defined(__NR_syz_fuse_mount) || defined(__NR_syz_fuseblk_mount)
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#endif
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_open_pts)
#include <fcntl.h>
#include <sys/ioctl.h>
@@ -801,64 +796,6 @@ static uintptr_t syz_open_pts(uintptr_t a0, uintptr_t a1)
}
#endif
-#if defined(SYZ_EXECUTOR) || defined(__NR_syz_fuse_mount)
-static uintptr_t syz_fuse_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5)
-{
- uint64 target = a0;
- uint64 mode = a1;
- uint64 uid = a2;
- uint64 gid = a3;
- uint64 maxread = a4;
- uint64 flags = a5;
-
- int fd = open("/dev/fuse", O_RDWR);
- if (fd == -1)
- return fd;
- char buf[1024];
- sprintf(buf, "fd=%d,user_id=%ld,group_id=%ld,rootmode=0%o", fd, (long)uid, (long)gid, (unsigned)mode & ~3u);
- if (maxread != 0)
- sprintf(buf + strlen(buf), ",max_read=%ld", (long)maxread);
- if (mode & 1)
- strcat(buf, ",default_permissions");
- if (mode & 2)
- strcat(buf, ",allow_other");
- syscall(SYS_mount, "", target, "fuse", flags, buf);
- return fd;
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || defined(__NR_syz_fuseblk_mount)
-static uintptr_t syz_fuseblk_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7)
-{
- uint64 target = a0;
- uint64 blkdev = a1;
- uint64 mode = a2;
- uint64 uid = a3;
- uint64 gid = a4;
- uint64 maxread = a5;
- uint64 blksize = a6;
- uint64 flags = a7;
-
- int fd = open("/dev/fuse", O_RDWR);
- if (fd == -1)
- return fd;
- if (syscall(SYS_mknodat, AT_FDCWD, blkdev, S_IFBLK, makedev(7, 199)))
- return fd;
- char buf[256];
- sprintf(buf, "fd=%d,user_id=%ld,group_id=%ld,rootmode=0%o", fd, (long)uid, (long)gid, (unsigned)mode & ~3u);
- if (maxread != 0)
- sprintf(buf + strlen(buf), ",max_read=%ld", (long)maxread);
- if (blksize != 0)
- sprintf(buf + strlen(buf), ",blksize=%ld", (long)blksize);
- if (mode & 1)
- strcat(buf, ",default_permissions");
- if (mode & 2)
- strcat(buf, ",allow_other");
- syscall(SYS_mount, blkdev, target, "fuseblk", flags, buf);
- return fd;
-}
-#endif
-
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_init_net_socket)
#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE)
const int kInitNetNsFd = 253;
diff --git a/pkg/host/host_linux.go b/pkg/host/host_linux.go
index 2a72ec5f0..1dfa3c978 100644
--- a/pkg/host/host_linux.go
+++ b/pkg/host/host_linux.go
@@ -32,6 +32,9 @@ func isSupported(c *prog.Syscall, sandbox string) (bool, string) {
if strings.HasPrefix(c.Name, "openat$") {
return isSupportedOpenAt(c)
}
+ if strings.HasPrefix(c.Name, "mount$") {
+ return isSupportedMount(c, sandbox)
+ }
// There are 3 possible strategies for detecting supported syscalls:
// 1. Executes all syscalls with presumably invalid arguments and check for ENOprog.
// But not all syscalls are safe to execute. For example, pause will hang,
@@ -151,16 +154,6 @@ func isSupportedSyzkall(sandbox string, c *prog.Syscall) (bool, string) {
return true, ""
case "syz_open_pts":
return true, ""
- case "syz_fuse_mount":
- if err := osutil.IsAccessible("/dev/fuse"); err != nil {
- return false, err.Error()
- }
- return onlySandboxNoneOrNamespace(sandbox)
- case "syz_fuseblk_mount":
- if err := osutil.IsAccessible("/dev/fuse"); err != nil {
- return false, err.Error()
- }
- return onlySandboxNoneOrNamespace(sandbox)
case "syz_emit_ethernet", "syz_extract_tcp_res":
reason := checkNetworkInjection()
return reason == "", reason
@@ -200,13 +193,7 @@ func isSupportedSyzkall(sandbox string, c *prog.Syscall) (bool, string) {
if !ok {
panic("syz_mount_image arg is not string")
}
- filesystemsOnce.Do(func() {
- filesystems, _ = ioutil.ReadFile("/proc/filesystems")
- })
- if !bytes.Contains(filesystems, []byte("\t"+fstype+"\n")) {
- return false, "/proc/filesystems does not contain this fs"
- }
- return true, ""
+ return isSupportedFilesystem(fstype)
case "syz_read_part_table":
return onlySandboxNone(sandbox)
}
@@ -277,6 +264,35 @@ func isSupportedOpenAt(c *prog.Syscall) (bool, string) {
return true, ""
}
+func isSupportedMount(c *prog.Syscall, sandbox string) (bool, string) {
+ fstype, ok := extractStringConst(c.Args[2])
+ if !ok {
+ panic(fmt.Sprintf("%v: filesystem is not string const", c.Name))
+ }
+ if ok, reason := isSupportedFilesystem(fstype); !ok {
+ return ok, reason
+ }
+ switch fstype {
+ case "fuse", "fuseblk":
+ if err := osutil.IsAccessible("/dev/fuse"); err != nil {
+ return false, err.Error()
+ }
+ return onlySandboxNoneOrNamespace(sandbox)
+ default:
+ return onlySandboxNone(sandbox)
+ }
+}
+
+func isSupportedFilesystem(fstype string) (bool, string) {
+ filesystemsOnce.Do(func() {
+ filesystems, _ = ioutil.ReadFile("/proc/filesystems")
+ })
+ if !bytes.Contains(filesystems, []byte("\t"+fstype+"\n")) {
+ return false, fmt.Sprintf("/proc/filesystems does not contain %v", fstype)
+ }
+ return true, ""
+}
+
func extractStringConst(typ prog.Type) (string, bool) {
ptr, ok := typ.(*prog.PtrType)
if !ok {