Re: KASAN: use-after-free Read in __fput (3)

2020-09-01 Thread Al Viro
On Tue, Sep 01, 2020 at 04:43:09PM +0800, Hillf Danton wrote:

> Below is my 2c for making it safe to access the rbtree entry and the
> file tucked in it by bumping up the file count before adding epi into
> rbtree.

NAK.  epitems, by design, do *NOT* pin files down.  That's what
eventpoll_release() is about - those references are not counting and
epitems can be taken out by the final close.

It's a user-visible aspect of API.  And the problem Marc's patch was
trying to solve had nothing to do with that - at the root it's
the lack of suitable exclusion and the atrocious way loop prevention
and reverse path count checks are done on watch insertion.

What happens there is that files that would have paths added by
EPOLL_CTL_ADD (including those via several intermediate epoll files)
are collected into a temporary list and then checked for excessive
reverse paths.  The list is emptied before epoll_ctl() returns.

And that's _the_ list - if epoll_ctl decides to go there in the
first place, it grabs a system-wide mutex and holds it as long as
it's playing around.  Everything would've worked, if not for the
fact that
* the bloody list goes through struct file instances.  It's
a bad decision, for a lot of reasons.
* in particular, files can go away while epoll_ctl() is playing
around.  The same system-wide mutex would've blocked their freeing (modulo
a narrow race in eventpoll_release()) *IF* they remained attached to
epitems.  However, explicit EPOLL_CTL_DEL removing such a beast
in the middle of EPOLL_CTL_ADD checks will remove such epitems without
touching the same mutex.

Marc's patch tried to brute-force the protection of files in that
temporary list; what it had missed was the fact that a file on it could
have already been committed to getting killed - f_count already zero,
just hadn't gotten through the __fput() yet.  In such cases we don't
want to do any reverse path checks for that sucker - it *is* going
away, so there's no point considering it.  We can't blindly bump the
refcount, though, for obvious reasons.

That struct file can't get freed right under the code inserting it into
the list - the locks held at the moment (ep->mtx) are more than enough.
It's what can happen to it while on the list that is a problem.

Of course, as a long-term solution we want to have that crap with
temporary list going through struct file instances taken out and
moved to epitems themselves; the check does scan all epitems for
every file in the set and we bloody well could gather those into
the list at once.  Then we'd only need to protect the list walking
vs. removals (with a spinlock, for all we care).

It's too invasive a change for -stable, though, and I'm still digging
through fs/eventpoll.c locking - it's much too convoluted and it
got no attention for a decade ;-/


Re: KASAN: use-after-free Read in __fput (3)

2020-08-31 Thread Al Viro
On Tue, Sep 01, 2020 at 10:35:47AM +0800, Hillf Danton wrote:

> Any light on how a9ed4a6560b8 ends up with __fput called twice is
> highly appreciated.

diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index e0decff22ae2..8107e06d7f6f 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1995,9 +1995,9 @@ static int ep_loop_check_proc(void *priv, void *cookie, 
int call_nests)
 * during ep_insert().
 */
if (list_empty(>ffd.file->f_tfile_llink)) {
-   get_file(epi->ffd.file);
-   list_add(>ffd.file->f_tfile_llink,
-_check_list);
+   if (get_file_rcu(epi->ffd.file))
+   list_add(>ffd.file->f_tfile_llink,
+_check_list);
}
}
}


KASAN: use-after-free Read in __fput (3)

2020-08-31 Thread syzbot
Hello,

syzbot found the following issue on:

HEAD commit:15bc20c6 Merge tag 'tty-5.9-rc3' of git://git.kernel.org/p..
git tree:   upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=10b440d190
kernel config:  https://syzkaller.appspot.com/x/.config?x=978db74cb30aa994
dashboard link: https://syzkaller.appspot.com/bug?extid=c282923e5da93549fa27
compiler:   gcc (GCC) 10.1.0-syz 20200507
syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=16a5452e90

The issue was bisected to:

commit a9ed4a6560b8562b7e2e2bed9527e88001f7b682
Author: Marc Zyngier 
Date:   Wed Aug 19 16:12:17 2020 +

epoll: Keep a reference on files added to the check list

bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=147a02f290
final oops: https://syzkaller.appspot.com/x/report.txt?x=167a02f290
console output: https://syzkaller.appspot.com/x/log.txt?x=127a02f290

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+c282923e5da93549f...@syzkaller.appspotmail.com
Fixes: a9ed4a6560b8 ("epoll: Keep a reference on files added to the check list")

==
BUG: KASAN: use-after-free in d_inode include/linux/dcache.h:522 [inline]
BUG: KASAN: use-after-free in fsnotify_parent include/linux/fsnotify.h:54 
[inline]
BUG: KASAN: use-after-free in fsnotify_file include/linux/fsnotify.h:90 [inline]
BUG: KASAN: use-after-free in fsnotify_close include/linux/fsnotify.h:279 
[inline]
BUG: KASAN: use-after-free in __fput+0x8ac/0x920 fs/file_table.c:267
Read of size 8 at addr 888087a020a8 by task syz-executor.2/11261

CPU: 0 PID: 11261 Comm: syz-executor.2 Not tainted 5.9.0-rc2-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 
01/01/2011
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x18f/0x20d lib/dump_stack.c:118
 print_address_description.constprop.0.cold+0xae/0x497 mm/kasan/report.c:383
 __kasan_report mm/kasan/report.c:513 [inline]
 kasan_report.cold+0x1f/0x37 mm/kasan/report.c:530
 d_inode include/linux/dcache.h:522 [inline]
 fsnotify_parent include/linux/fsnotify.h:54 [inline]
 fsnotify_file include/linux/fsnotify.h:90 [inline]
 fsnotify_close include/linux/fsnotify.h:279 [inline]
 __fput+0x8ac/0x920 fs/file_table.c:267
 task_work_run+0xdd/0x190 kernel/task_work.c:141
 tracehook_notify_resume include/linux/tracehook.h:188 [inline]
 exit_to_user_mode_loop kernel/entry/common.c:140 [inline]
 exit_to_user_mode_prepare+0x195/0x1c0 kernel/entry/common.c:167
 syscall_exit_to_user_mode+0x59/0x2b0 kernel/entry/common.c:242
 entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x416f01
Code: 75 14 b8 03 00 00 00 0f 05 48 3d 01 f0 ff ff 0f 83 04 1b 00 00 c3 48 83 
ec 08 e8 0a fc ff ff 48 89 04 24 b8 03 00 00 00 0f 05 <48> 8b 3c 24 48 89 c2 e8 
53 fc ff ff 48 89 d0 48 83 c4 08 48 3d 01
RSP: 002b:7fff215c6f90 EFLAGS: 0293 ORIG_RAX: 0003
RAX:  RBX: 0004 RCX: 00416f01
RDX: 000f4240 RSI: 0081 RDI: 0003
RBP:  R08: 01190358 R09: 
R10: 7fff215c7070 R11: 0293 R12: 01190360
R13:  R14:  R15: 0118cf4c

Allocated by task 11262:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track mm/kasan/common.c:56 [inline]
 __kasan_kmalloc.constprop.0+0xbf/0xd0 mm/kasan/common.c:461
 slab_post_alloc_hook mm/slab.h:518 [inline]
 slab_alloc mm/slab.c:3312 [inline]
 kmem_cache_alloc+0x138/0x3a0 mm/slab.c:3482
 __d_alloc+0x2a/0x950 fs/dcache.c:1709
 d_alloc_pseudo+0x19/0x70 fs/dcache.c:1838
 alloc_file_pseudo+0xc6/0x250 fs/file_table.c:226
 sock_alloc_file+0x4f/0x190 net/socket.c:411
 sock_map_fd net/socket.c:435 [inline]
 __sys_socket+0x13d/0x200 net/socket.c:1524
 __do_sys_socket net/socket.c:1529 [inline]
 __se_sys_socket net/socket.c:1527 [inline]
 __x64_sys_socket+0x6f/0xb0 net/socket.c:1527
 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

Freed by task 11262:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track+0x1c/0x30 mm/kasan/common.c:56
 kasan_set_free_info+0x1b/0x30 mm/kasan/generic.c:355
 __kasan_slab_free+0xd8/0x120 mm/kasan/common.c:422
 __cache_free mm/slab.c:3418 [inline]
 kmem_cache_free.part.0+0x67/0x1f0 mm/slab.c:3693
 __d_free fs/dcache.c:271 [inline]
 dentry_free+0xde/0x160 fs/dcache.c:348
 __dentry_kill+0x4c6/0x640 fs/dcache.c:593
 dentry_kill fs/dcache.c:705 [inline]
 dput+0x725/0xbc0 fs/dcache.c:878
 __fput+0x3ab/0x920 fs/file_table.c:294
 task_work_run+0xdd/0x190 kernel/task_work.c:141
 tracehook_notify_resume include/linux/tracehook.h:188 [inline]
 exit_to_user_mode_loop kernel/entry/common.c:140 [inline]
 exit_to_user_mode_prepare+0x195/0x1c0 kernel/entry/common.c:167
 syscall_exit_to_user_mode+0x59/0x2b0 kernel/entry/common.c:242