| Summary: | Divide by zero in kern_fcntl_freebsd | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Andrew Turner <Andrew> |
| Component: | kern | Assignee: | Mark Johnston <markj> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | CC: | cem, emaste, markj |
| Priority: | --- | ||
| Version: | CURRENT | ||
| Hardware: | Any | ||
| OS: | Any | ||
|
Description
Andrew Turner
2019-05-21 22:37:10 UTC
Looks like F_READAHEAD on devfs. The problematic code is a handcoded roundup(arg, bsize). It seems like possible solutions would be either not rounding the arg when bsize==0, or EINVALing the request. The reproducer Syzkaller found is below. // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include <pwd.h> #include <stdarg.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/endian.h> #include <sys/syscall.h> #include <unistd.h> uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff}; int main(void) { syscall(SYS_mmap, 0x20000000, 0x1000000, 3, 0x1012, -1, 0); intptr_t res = 0; memcpy((void*)0x20000040, "/dev///\000", 8); res = syscall(SYS_openat, 0xffffffffffffff9c, 0x20000040, 0, 0); if (res != -1) r[0] = res; res = syscall(SYS_dup2, r[0], r[0]); if (res != -1) r[1] = res; syscall(SYS_fcntl, r[1], 0xf, 0); return 0; } 0xffffffffffffff9c is just AT_FDCWD, so this is essentially just open("/dev/", O_RDONLY) and then fcntl(F_READAHEAD==0xf), I think.
Smaller repro:
#include <fcntl.h>
int
main(int argc, char **argv)
{
int fd;
(void)argc;
(void)argv;
fd = open("/dev/", O_RDONLY);
fcntl(fd, F_READAHEAD, 0);
return (0);
}
Hm, devfs_statfs() does fill f_iosize, and it looks like we did that, so how is this dividing by zero?
0xfffff8000377d000 devfs on /dev (devfs)
mnt_flag = MULTILABEL, LOCAL
mnt_kern_flag = EXTENDED_SHARED, LOOKUP_SHARED
mnt_opt =
mnt_stat = { version=538182936 type=113 flags=0x0000000000000000 bsize=512 iosize=512 blocks=2 bfree=0 bavail=0 files=0 ffree=0 syncwrites=0 asyncwrites=0 syncreads=0 asyncreads=0 namemax=255 owner=0 fsid=[1895890688, 113] }
It's definitely "Fatal trap 18: integer divide fault while in kernel mode" and
that line, though.
This was fixed by r353010. |