On Mon, Oct 22, 2018 at 10:54 AM, Oleg Nesterov <o...@redhat.com> wrote: > On 10/21, Tetsuo Handa wrote: >> >> On 2018/10/21 16:10, syzbot wrote: >> > BUG: KASAN: use-after-free in __read_once_size >> > include/linux/compiler.h:188 [inline] >> > BUG: KASAN: use-after-free in task_is_descendant.part.2+0x610/0x670 >> > security/yama/yama_lsm.c:295 >> > Read of size 8 at addr ffff8801c4666b20 by task syz-executor3/12722 >> > >> > CPU: 1 PID: 12722 Comm: syz-executor3 Not tainted 4.19.0-rc8+ #70 >> > 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+0x1c4/0x2b4 lib/dump_stack.c:113 >> > print_address_description.cold.8+0x9/0x1ff mm/kasan/report.c:256 >> > kasan_report_error mm/kasan/report.c:354 [inline] >> > kasan_report.cold.9+0x242/0x309 mm/kasan/report.c:412 >> > __asan_report_load8_noabort+0x14/0x20 mm/kasan/report.c:433 >> > __read_once_size include/linux/compiler.h:188 [inline] >> > task_is_descendant.part.2+0x610/0x670 security/yama/yama_lsm.c:295 >> >> Do we need to hold >> >> write_lock_irq(&tasklist_lock); >> >> rather than >> >> rcu_read_lock(); >> >> when accessing >> >> "struct task_struct"->real_parent > > Well, if "task" is stable (can't exit), then I think > > rcu_dereference(task->real_parent) > > is fine, we know that ->real_parent did not pass exit_notif() yet. > > However, task_is_descendant() looks unnecessarily complicated, it could be > > static int task_is_descendant(struct task_struct *parent, > struct task_struct *child) > { > int rc = 0; > struct task_struct *walker; > > if (!parent || !child) > return 0; > > rcu_read_lock(); > for (walker = child; walker->pid; walker = > rcu_dereference(walker->real_parent)) > if (same_thread_group(parent, walker)) { > rc = 1; > break; > } > rcu_read_unlock(); > > return rc; > } > > And again, I do not know how/if yama ensures that child is rcu-protected, > perhaps > task_is_descendant() needs to check pid_alive(child) right after > rcu_read_lock() ?
task_is_descendant() is called under rcu_read_lock() in both ptracer_exception_found() and yama_ptrace_access_check() so I don't understand how any of the tasks could get freed? This is walking group_leader and real_parent -- are these not stable under rcu_lock()? -- Kees Cook