diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2024-09-18 17:38:12 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2024-09-19 08:37:17 +0000 |
| commit | 52c1f8045c38bcce0229b2cc3c69b1cbe21eb629 (patch) | |
| tree | 6795b28e4d5cf644369433d5e1906fbf1bfe7e1b | |
| parent | 6d197301fe4a048a54f3203599963947b6563bd9 (diff) | |
sys/linux: add syz_create_resource
syz_create_resource allows to turn any value into a resource.
Improve binfmt descriptions using syz_create_resource:
we need to pass the same file name to write syscalls and execve.
Use syz_create_resource to improve binfmt descriptions.
| -rw-r--r-- | executor/common_linux.h | 13 | ||||
| -rw-r--r-- | pkg/vminfo/linux_syscalls.go | 1 | ||||
| -rw-r--r-- | pkg/vminfo/syscalls.go | 2 | ||||
| -rw-r--r-- | sys/linux/binfmt.txt | 32 | ||||
| -rw-r--r-- | sys/linux/binfmt.txt.const | 4 | ||||
| -rw-r--r-- | sys/linux/sys.txt | 6 | ||||
| -rw-r--r-- | sys/linux/test/binfmt | 15 |
7 files changed, 55 insertions, 18 deletions
diff --git a/executor/common_linux.h b/executor/common_linux.h index 7356499de..30d29cb05 100644 --- a/executor/common_linux.h +++ b/executor/common_linux.h @@ -2277,6 +2277,19 @@ static long syz_memcpy_off(volatile long a0, volatile long a1, volatile long a2, } #endif +#if SYZ_EXECUTOR || __NR_syz_create_resource +// syz_create_resource(val intptr) intptr +// Variants of this pseudo-syscall are used to create resources from arbitrary values. +// For example: +// syz_create_resource$foo(x int32) resource_foo +// allows the fuzzer to use the same random int32 value in multiple syscalls, +// and should increase probability of generation of syscalls related to foo. +static long syz_create_resource(volatile long val) +{ + return val; +} +#endif + #if (SYZ_EXECUTOR || SYZ_REPEAT && SYZ_NET_INJECTION) && SYZ_EXECUTOR_USES_FORK_SERVER static void flush_tun() { diff --git a/pkg/vminfo/linux_syscalls.go b/pkg/vminfo/linux_syscalls.go index 2b02ad7f9..0effafa33 100644 --- a/pkg/vminfo/linux_syscalls.go +++ b/pkg/vminfo/linux_syscalls.go @@ -100,6 +100,7 @@ var linuxSyscallChecks = map[string]func(*checkContext, *prog.Syscall) string{ "syz_pkey_set": linuxPkeysSupported, "syz_socket_connect_nvme_tcp": linuxSyzSocketConnectNvmeTCPSupported, "syz_pidfd_open": alwaysSupported, + "syz_create_resource": alwaysSupported, } func linuxSyzOpenDevSupported(ctx *checkContext, call *prog.Syscall) string { diff --git a/pkg/vminfo/syscalls.go b/pkg/vminfo/syscalls.go index 707ab6543..21ae6edd1 100644 --- a/pkg/vminfo/syscalls.go +++ b/pkg/vminfo/syscalls.go @@ -283,7 +283,7 @@ func extractStringConst(typ prog.Type, isAutomatic bool) (string, bool) { } ptr, ok := typ.(*prog.PtrType) if !ok { - panic("first open arg is not a pointer to string const") + return "", false } str, ok := ptr.Elem.(*prog.BufferType) if !ok || str.Kind != prog.BufferString || len(str.Values) == 0 { diff --git a/sys/linux/binfmt.txt b/sys/linux/binfmt.txt index 3e86ab61a..d0e6b7b23 100644 --- a/sys/linux/binfmt.txt +++ b/sys/linux/binfmt.txt @@ -3,15 +3,33 @@ include <uapi/linux/a.out.h> include <uapi/linux/elf.h> +include <linux/fcntl.h> -execve(file ptr[in, filename], argv ptr[in, array[ptr[in, string]]], envp ptr[in, array[ptr[in, string]]]) -execveat(dirfd fd_dir, file ptr[in, filename], argv ptr[in, array[ptr[in, string]]], envp ptr[in, array[ptr[in, string]]], flags flags[at_flags]) +resource fd_binfmt[fd] +resource ptr_binfmt_file[intptr] -write$binfmt_script(fd fd, data ptr[in, binfmt_script], len bytesize[data]) -write$binfmt_misc(fd fd, data ptr[in, binfmt_misc], len bytesize[data]) -write$binfmt_aout(fd fd, data ptr[in, binfmt_aout], len bytesize[data]) -write$binfmt_elf32(fd fd, data ptr[in, binfmt_elf32], len bytesize[data]) -write$binfmt_elf64(fd fd, data ptr[in, binfmt_elf64], len bytesize[data]) +syz_create_resource$binfmt(file ptr[in, filename]) ptr_binfmt_file + +execve(file ptr[in, filename], argv ptr[in, argv_array], envp ptr[in, argv_array]) +execveat(dirfd fd_dir, file ptr[in, filename], argv ptr[in, argv_array], envp ptr[in, argv_array], flags flags[at_flags]) +execveat$binfmt(dirfd fd_dir, file ptr_binfmt_file, argv ptr[in, argv_array], envp ptr[in, argv_array], flags flags[at_flags]) + +openat$binfmt(fd const[AT_FDCWD], file ptr_binfmt_file, flags const[BINFMT_OPEN_FLAGS], mode const[0x1ff]) fd_binfmt + +write$binfmt_script(fd fd_binfmt, data ptr[in, binfmt_script], len bytesize[data]) +write$binfmt_misc(fd fd_binfmt, data ptr[in, binfmt_misc], len bytesize[data]) +write$binfmt_aout(fd fd_binfmt, data ptr[in, binfmt_aout], len bytesize[data]) +write$binfmt_elf32(fd fd_binfmt, data ptr[in, binfmt_elf32], len bytesize[data]) +write$binfmt_elf64(fd fd_binfmt, data ptr[in, binfmt_elf64], len bytesize[data]) + +close$binfmt(fd fd_binfmt) + +define BINFMT_OPEN_FLAGS O_WRONLY | O_CREAT + +argv_array { + args array[ptr[in, string]] + z const[0, intptr] +} [packed] binfmt_script { hdr stringnoz["#! "] diff --git a/sys/linux/binfmt.txt.const b/sys/linux/binfmt.txt.const index f87766baf..e9acd5aad 100644 --- a/sys/linux/binfmt.txt.const +++ b/sys/linux/binfmt.txt.const @@ -1,5 +1,7 @@ # Code generated by syz-sysgen. DO NOT EDIT. arches = 386, amd64, arm, arm64, mips64le, ppc64le, riscv64, s390x +AT_FDCWD = 18446744073709551516 +BINFMT_OPEN_FLAGS = 65, mips64le:257 ELF32_PHDR_SIZE = 32 ELF64_PHDR_SIZE = 56 EM_386 = 3 @@ -21,6 +23,8 @@ PT_SHLIB = 5 PT_TLS = 7 QMAGIC = 204 ZMAGIC = 267 +__NR_close = 6, amd64:3, arm64:riscv64:57, mips64le:5003 __NR_execve = 11, amd64:59, arm64:riscv64:221, mips64le:5057 __NR_execveat = 281, 386:358, amd64:322, arm:387, mips64le:5316, ppc64le:362, s390x:354 +__NR_openat = 56, 386:295, amd64:257, arm:322, mips64le:5247, ppc64le:286, s390x:288 __NR_write = 4, amd64:1, arm64:riscv64:64, mips64le:5001 diff --git a/sys/linux/sys.txt b/sys/linux/sys.txt index 4ee926fd6..a9fbd3f72 100644 --- a/sys/linux/sys.txt +++ b/sys/linux/sys.txt @@ -462,9 +462,9 @@ sysfs$3(option const[3]) statfs(path ptr[in, filename], buf buffer[out]) fstatfs(fd fd, buf buffer[out]) -uselib(lib ptr[in, filename]) -init_module(mod ptr[in, string], len len[mod], args ptr[in, string]) -finit_module(fd fd, args ptr[in, string], flags flags[finit_module_flags]) +uselib(lib ptr_binfmt_file) +init_module(mod ptr[in, binfmt_elf64], len len[mod], args ptr[in, string]) +finit_module(fd fd_binfmt, args ptr[in, string], flags flags[finit_module_flags]) delete_module(name ptr[in, string], flags flags[delete_module_flags]) kexec_load(entry intptr, nr_segments len[segments], segments ptr[in, array[kexec_segment]], flags flags[kexec_load_flags]) syslog(cmd flags[syslog_cmd], buf ptr[out, array[int8], opt], len len[buf]) diff --git a/sys/linux/test/binfmt b/sys/linux/test/binfmt index 8998c6226..617d75cfe 100644 --- a/sys/linux/test/binfmt +++ b/sys/linux/test/binfmt @@ -1,16 +1,17 @@ # Tests for binfmt_misc. # Executor setups binfmt_misc with ./file0 interpreter for files with byte 0x01 at offset 0. -execveat(0xffffffffffffff9c, &AUTO='./file1\x00', &AUTO=[0x0], &AUTO=[0x0], 0x0) # ENOENT -r0 = openat(0xffffffffffffff9c, &AUTO='./file1\x00', 0x42, 0x1ff) +r3 = syz_create_resource$binfmt(&AUTO='./file1\x00') +execveat$binfmt(0xffffffffffffff9c, r3, &AUTO={[], 0x0}, &AUTO={[], 0x0}, 0x0) # ENOENT +r0 = openat$binfmt(0xffffffffffffff9c, r3, 0x42, 0x1ff) close(r0) -execveat(0xffffffffffffff9c, &AUTO='./file1\x00', &AUTO=[0x0], &AUTO=[0x0], 0x0) # ENOEXEC -r1 = openat(0xffffffffffffff9c, &AUTO='./file1\x00', 0x2, 0x0) +execveat$binfmt(0xffffffffffffff9c, r3, &AUTO={[], 0x0}, &AUTO={[], 0x0}, 0x0) # ENOEXEC +r1 = openat$binfmt(0xffffffffffffff9c, r3, 0x2, 0x0) write(r1, &AUTO="01010101", 0x4) close(r1) -execveat(0xffffffffffffff9c, &AUTO='./file1\x00', &AUTO=[0x0], &AUTO=[0x0], 0x0) # ENOENT +execveat$binfmt(0xffffffffffffff9c, r3, &AUTO={[], 0x0}, &AUTO={[], 0x0}, 0x0) # ENOENT r2 = openat(0xffffffffffffff9c, &AUTO='./file0\x00', 0x42, 0x0) close(r2) -execveat(0xffffffffffffff9c, &AUTO='./file1\x00', &AUTO=[0x0], &AUTO=[0x0], 0x0) # EACCES +execveat$binfmt(0xffffffffffffff9c, r3, &AUTO={[], 0x0}, &AUTO={[], 0x0}, 0x0) # EACCES fchmodat(0xffffffffffffff9c, &AUTO='./file0\x00', 0x1ff) -execveat(0xffffffffffffff9c, &AUTO='./file1\x00', &AUTO=[0x0], &AUTO=[0x0], 0x0) # ENOEXEC +execveat$binfmt(0xffffffffffffff9c, r3, &AUTO={[], 0x0}, &AUTO={[], 0x0}, 0x0) # ENOEXEC |
