aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2023-12-18 11:58:39 +0100
committerAleksandr Nogikh <nogikh@google.com>2023-12-19 00:16:19 +0000
commit3ad490ea48468e50fe91f6f6b2ca4cbc74d924bf (patch)
treed6960156ac4fcbeb908fbbbba79c8716d8e47172
parent924661f4beda6a647079237cc843df44626fc44b (diff)
executor: introduce syz_pidfd_open()
This kernel interface provides access to fds of other processes, which is readily abused by the fuzzer to mangle parent syz-executor fds. Pid=1 is the parent syz-executor process when PID namespace is created. Sanitize it in the new syz_pidfd_open() pseudo-syscall. We could not patch the argument in sys/linux/init.go because the first argument is a resource.
-rw-r--r--executor/common_linux.h18
-rw-r--r--pkg/csource/generated.go12
-rw-r--r--pkg/host/syscalls_linux.go1
-rw-r--r--sys/linux/sys.txt5
-rw-r--r--sys/targets/targets.go1
5 files changed, 36 insertions, 1 deletions
diff --git a/executor/common_linux.h b/executor/common_linux.h
index 2f10ae3d6..85f9b966a 100644
--- a/executor/common_linux.h
+++ b/executor/common_linux.h
@@ -5655,3 +5655,21 @@ static void setup_swap()
}
#endif
+
+#if SYZ_EXECUTOR || __NR_syz_pidfd_open
+#include <sys/syscall.h>
+
+// TODO: long-term we should improve our sandboxing rules since there are also
+// many other opportunities for a fuzzer process to access what it shouldn't.
+// Here we only shut down one of the recently discovered ways.
+static long syz_pidfd_open(volatile long pid, volatile long flags)
+{
+ if (pid == 1) {
+ // Under a PID namespace, pid=1 is the parent process.
+ // We don't want a forked child to mangle parent syz-executor's fds.
+ pid = 0;
+ }
+ return syscall(__NR_pidfd_open, pid, flags);
+}
+
+#endif
diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go
index 4c3fae47c..e65b95095 100644
--- a/pkg/csource/generated.go
+++ b/pkg/csource/generated.go
@@ -11823,6 +11823,18 @@ static void setup_swap()
#endif
+#if SYZ_EXECUTOR || __NR_syz_pidfd_open
+#include <sys/syscall.h>
+static long syz_pidfd_open(volatile long pid, volatile long flags)
+{
+ if (pid == 1) {
+ pid = 0;
+ }
+ return syscall(__NR_pidfd_open, pid, flags);
+}
+
+#endif
+
#elif GOOS_test
#include <stdlib.h>
diff --git a/pkg/host/syscalls_linux.go b/pkg/host/syscalls_linux.go
index b1bcbfb8b..d59fe491b 100644
--- a/pkg/host/syscalls_linux.go
+++ b/pkg/host/syscalls_linux.go
@@ -327,6 +327,7 @@ var syzkallSupport = map[string]func(*prog.Syscall, *prog.Target, string) (bool,
"syz_clone3": alwaysSupported,
"syz_pkey_set": isSyzPkeySetSupported,
"syz_socket_connect_nvme_tcp": isSyzSocketConnectNvmeTCPSupported,
+ "syz_pidfd_open": alwaysSupported,
}
func isSupportedSyzkall(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) {
diff --git a/sys/linux/sys.txt b/sys/linux/sys.txt
index 30266900f..d6a19b787 100644
--- a/sys/linux/sys.txt
+++ b/sys/linux/sys.txt
@@ -653,7 +653,10 @@ resource fd_pidfd[fd]
openat$pidfd(fd const[AT_FDCWD], file ptr[in, string["/proc/self"]], flags flags[open_flags], mode const[0]) fd_pidfd
openat$thread_pidfd(fd const[AT_FDCWD], file ptr[in, string["/proc/thread-self"]], flags flags[open_flags], mode const[0]) fd_pidfd
pidfd_send_signal(fd fd_pidfd, sig signalno, info ptr[in, siginfo], flags const[0])
-pidfd_open(pid pid, flags const[0]) fd_pidfd
+
+# pidfd_open is dangerous, so we use syz_pidfd_open instead.
+pidfd_open(pid pid, flags const[0]) fd_pidfd (disabled)
+syz_pidfd_open(pid pid, flags const[0]) fd_pidfd
pidfd_getfd(pidfd fd_pidfd, fd fd, flags const[0]) fd
close_range(fd fd, max_fd fd, flags flags[close_range_flags])
diff --git a/sys/targets/targets.go b/sys/targets/targets.go
index b81b0ce70..4c840119a 100644
--- a/sys/targets/targets.go
+++ b/sys/targets/targets.go
@@ -490,6 +490,7 @@ var oses = map[string]osCommon{
"syz_io_uring_setup": {"io_uring_setup"},
"syz_clone3": {"clone3", "exit"},
"syz_clone": {"clone", "exit"},
+ "syz_pidfd_open": {"pidfd_open"},
},
cflags: []string{"-static-pie"},
},