Thread (31 messages) 31 messages, 4 authors, 2019-01-16

Re: KASAN: use-after-free Read in task_is_descendant

From: Kees Cook <hidden>
Date: 2018-10-25 08:19:50
Also in: lkml

On Mon, Oct 22, 2018 at 10:54 AM, Oleg Nesterov [off-list ref] wrote:
On 10/21, Tetsuo Handa wrote:
quoted
On 2018/10/21 16:10, syzbot wrote:
quoted
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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help