mm, floppy: unkillable task faulting on fd0

From: Dmitry Vyukov
Date: Fri Nov 18 2016 - 04:16:46 EST


Hello,

The following program produces unkillable tasks blocked at the following stack:

[<ffffffff8184c44b>] wait_on_page_bit+0x1eb/0x2a0 mm/filemap.c:802
[< inline >] wait_on_page_locked ./include/linux/pagemap.h:508
[<ffffffff81862fa7>] filemap_fault+0x17c7/0x1e50 mm/filemap.c:2201
[<ffffffff819423cc>] __do_fault+0x33c/0x8a0 mm/memory.c:2864
[< inline >] do_read_fault mm/memory.c:3191
[<ffffffff81953521>] do_fault+0xbb1/0x28d0 mm/memory.c:3326
[< inline >] handle_pte_fault mm/memory.c:3527
[< inline >] __handle_mm_fault mm/memory.c:3614
[<ffffffff81956ddb>] handle_mm_fault+0x159b/0x2cd0 mm/memory.c:3651
[<ffffffff812fc2eb>] __do_page_fault+0x4fb/0xb60 arch/x86/mm/fault.c:1397
[<ffffffff812fcb19>] trace_do_page_fault+0x159/0x830 arch/x86/mm/fault.c:1490
[<ffffffff812eb6fc>] do_async_page_fault+0x7c/0xd0 arch/x86/kernel/kvm.c:265
[<ffffffff88148cd8>] async_page_fault+0x28/0x30 arch/x86/entry/entry_64.S:1015
[<ffffffff81aadf93>] getname_flags+0x113/0x580 fs/namei.c:148
[<ffffffff81aaf112>] user_path_at_empty+0x32/0x50 fs/namei.c:2556
[< inline >] SYSC_readlinkat fs/stat.c:327
[< inline >] SyS_readlinkat fs/stat.c:315
[< inline >] SYSC_readlink fs/stat.c:352
[<ffffffff81a8295c>] SyS_readlink+0x12c/0x3f0 fs/stat.c:349
[<ffffffff88147885>] entry_SYSCALL_64_fastpath+0x23/0xc6
arch/x86/entry/entry_64.S:209


Before hang kernel prints:
[ 404.042351] floppy0: disk absent or changed during operation
[ 404.044187] floppy0: disk absent or changed during operation
[ 404.058637] floppy0: disk absent or changed during operation
[ 404.060152] floppy0: do_fd_request: timeout handler died. old
request running


On commit a25f0944ba9b1d8a6813fd6f1a86f1bd59ac25a6 (Nov 13).

Run this program in a loop:

// autogenerated by syzkaller (http://github.com/google/syzkaller)

#include <pthread.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>

int fd;

void* thr(void* arg)
{
if (rand() % 2)
usleep(rand() % 1000);
switch ((long)arg) {
case 0:
fd = syscall(__NR_open, "/dev/fd0", 0x900ul);
break;
case 1:
syscall(__NR_mmap, 0x20009000ul, 0x1000ul, 0x4ul, 0x12ul, fd, 0x0ul);
break;
case 2:
syscall(__NR_mmap, 0x20009000ul, 0x1000ul, 0x4ul, 0x12ul, fd, 0x0ul);
break;
case 3:
syscall(__NR_readlink, 0x20009000ul, 0x20009000ul, 0x100ul);
break;
case 4:
syscall(__NR_readlink, 0x20009000ul, 0x20009000ul, 0x100ul);
break;
}
return 0;
}

int main()
{
long i;
pthread_t th[5];

fd = syscall(__NR_open, "/dev/fd0", 0x900ul);
syscall(__NR_mmap, 0x20009000ul, 0x1000ul, 0x4ul, 0x12ul, fd, 0x0ul);

srand(getpid());
for (i = 0; i < 5; i++)
pthread_create(&th[i], 0, thr, (void*)i);
for (i = 0; i < 5; i++)
pthread_join(th[i], 0);
return 0;
}