• Christian Brauner's avatar
    close_range: unshare all fds for CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC · fec8a6a6
    Christian Brauner authored
    After introducing CLOSE_RANGE_CLOEXEC syzbot reported a crash when
    CLOSE_RANGE_CLOEXEC is specified in conjunction with CLOSE_RANGE_UNSHARE.
    When CLOSE_RANGE_UNSHARE is specified the caller will receive a private
    file descriptor table in case their file descriptor table is currently
    shared.
    
    For the case where the caller has requested all file descriptors to be
    actually closed via e.g. close_range(3, ~0U, 0) the kernel knows that
    the caller does not need any of the file descriptors anymore and will
    optimize the close operation by only copying all files in the range from
    0 to 3 and no others.
    
    However, if the caller requested CLOSE_RANGE_CLOEXEC together with
    CLOSE_RANGE_UNSHARE the caller wants to still make use of the file
    descriptors so the kernel needs to copy all of them and can't optimize.
    
    The original patch didn't account for this and thus could cause oopses
    as evidenced by the syzbot report because it assumed that all fds had
    been copied. Fix this by handling the CLOSE_RANGE_CLOEXEC case.
    
    syzbot reported
    ==================================================================
    BUG: KASAN: null-ptr-deref in instrument_atomic_read include/linux/instrumented.h:71 [inline]
    BUG: KASAN: null-ptr-deref in atomic64_read include/asm-generic/atomic-instrumented.h:837 [inline]
    BUG: KASAN: null-ptr-deref in atomic_long_read include/asm-generic/atomic-long.h:29 [inline]
    BUG: KASAN: null-ptr-deref in filp_close+0x22/0x170 fs/open.c:1274
    Read of size 8 at addr 0000000000000077 by task syz-executor511/8522
    
    CPU: 1 PID: 8522 Comm: syz-executor511 Not tainted 5.10.0-syzkaller #0
    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
    Call Trace:
     __dump_stack lib/dump_stack.c:79 [inline]
     dump_stack+0x107/0x163 lib/dump_stack.c:120
     __kasan_report mm/kasan/report.c:549 [inline]
     kasan_report.cold+0x5/0x37 mm/kasan/report.c:562
     check_memory_region_inline mm/kasan/generic.c:186 [inline]
     check_memory_region+0x13d/0x180 mm/kasan/generic.c:192
     instrument_atomic_read include/linux/instrumented.h:71 [inline]
     atomic64_read include/asm-generic/atomic-instrumented.h:837 [inline]
     atomic_long_read include/asm-generic/atomic-long.h:29 [inline]
     filp_close+0x22/0x170 fs/open.c:1274
     close_files fs/file.c:402 [inline]
     put_files_struct fs/file.c:417 [inline]
     put_files_struct+0x1cc/0x350 fs/file.c:414
     exit_files+0x12a/0x170 fs/file.c:435
     do_exit+0xb4f/0x2a00 kernel/exit.c:818
     do_group_exit+0x125/0x310 kernel/exit.c:920
     get_signal+0x428/0x2100 kernel/signal.c:2792
     arch_do_signal_or_restart+0x2a8/0x1eb0 arch/x86/kernel/signal.c:811
     handle_signal_work kernel/entry/common.c:147 [inline]
     exit_to_user_mode_loop kernel/entry/common.c:171 [inline]
     exit_to_user_mode_prepare+0x124/0x200 kernel/entry/common.c:201
     __syscall_exit_to_user_mode_work kernel/entry/common.c:291 [inline]
     syscall_exit_to_user_mode+0x19/0x50 kernel/entry/common.c:302
     entry_SYSCALL_64_after_hwframe+0x44/0xa9
    RIP: 0033:0x447039
    Code: Unable to access opcode bytes at RIP 0x44700f.
    RSP: 002b:00007f1b1225cdb8 EFLAGS: 00000246 ORIG_RAX: 00000000000000ca
    RAX: 0000000000000001 RBX: 00000000006dbc28 RCX: 0000000000447039
    RDX: 00000000000f4240 RSI: 0000000000000081 RDI: 00000000006dbc2c
    RBP: 00000000006dbc20 R08: 0000000000000000 R09: 0000000000000000
    R10: 0000000000000000 R11: 0000000000000246 R12: 00000000006dbc2c
    R13: 00007fff223b6bef R14: 00007f1b1225d9c0 R15: 00000000006dbc2c
    ==================================================================
    
    syzbot has tested the proposed patch and the reproducer did not trigger any issue:
    
    Reported-and-tested-by: syzbot+96cfd2b22b3213646a93@syzkaller.appspotmail.com
    
    Tested on:
    
    commit:         10f7cddd selftests/core: add regression test for CLOSE_RAN..
    git tree:       git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux.git vfs
    kernel config:  https://syzkaller.appspot.com/x/.config?x=5d42216b510180e3
    dashboard link: https://syzkaller.appspot.com/bug?extid=96cfd2b22b3213646a93
    compiler:       gcc (GCC) 10.1.0-syz 20200507
    
    Reported-by: syzbot+96cfd2b22b3213646a93@syzkaller.appspotmail.com
    Fixes: 582f1fb6 ("fs, close_range: add flag CLOSE_RANGE_CLOEXEC")
    Cc: Giuseppe Scrivano <gscrivan@redhat.com>
    Cc: linux-fsdevel@vger.kernel.org
    Link: https://lore.kernel.org/r/20201217213303.722643-1-christian.brauner@ubuntu.comSigned-off-by: default avatarChristian Brauner <christian.brauner@ubuntu.com>
    fec8a6a6
file.c 28.7 KB