• Peter Zijlstra's avatar
    kthread: Fix PF_KTHREAD vs to_kthread() race · 3a7956e2
    Peter Zijlstra authored
    The kthread_is_per_cpu() construct relies on only being called on
    PF_KTHREAD tasks (per the WARN in to_kthread). This gives rise to the
    following usage pattern:
    
    	if ((p->flags & PF_KTHREAD) && kthread_is_per_cpu(p))
    
    However, as reported by syzcaller, this is broken. The scenario is:
    
    	CPU0				CPU1 (running p)
    
    	(p->flags & PF_KTHREAD) // true
    
    					begin_new_exec()
    					  me->flags &= ~(PF_KTHREAD|...);
    	kthread_is_per_cpu(p)
    	  to_kthread(p)
    	    WARN(!(p->flags & PF_KTHREAD) <-- *SPLAT*
    
    Introduce __to_kthread() that omits the WARN and is sure to check both
    values.
    
    Use this to remove the problematic pattern for kthread_is_per_cpu()
    and fix a number of other kthread_*() functions that have similar
    issues but are currently not used in ways that would expose the
    problem.
    
    Notably kthread_func() is only ever called on 'current', while
    kthread_probe_data() is only used for PF_WQ_WORKER, which implies the
    task is from kthread_create*().
    
    Fixes: ac687e6e ("kthread: Extract KTHREAD_IS_PER_CPU")
    Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Reviewed-by: default avatarValentin Schneider <Valentin.Schneider@arm.com>
    Link: https://lkml.kernel.org/r/YH6WJc825C4P0FCK@hirez.programming.kicks-ass.net
    3a7956e2
core.c 243 KB