• Andy Lutomirski's avatar
    membarrier: Execute SYNC_CORE on the calling thread · e45cdc71
    Andy Lutomirski authored
    membarrier()'s MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE is documented as
    syncing the core on all sibling threads but not necessarily the calling
    thread.  This behavior is fundamentally buggy and cannot be used safely.
    
    Suppose a user program has two threads.  Thread A is on CPU 0 and thread B
    is on CPU 1.  Thread A modifies some text and calls
    membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE).
    
    Then thread B executes the modified code.  If, at any point after
    membarrier() decides which CPUs to target, thread A could be preempted and
    replaced by thread B on CPU 0.  This could even happen on exit from the
    membarrier() syscall.  If this happens, thread B will end up running on CPU
    0 without having synced.
    
    In principle, this could be fixed by arranging for the scheduler to issue
    sync_core_before_usermode() whenever switching between two threads in the
    same mm if there is any possibility of a concurrent membarrier() call, but
    this would have considerable overhead.  Instead, make membarrier() sync the
    calling CPU as well.
    
    As an optimization, this avoids an extra smp_mb() in the default
    barrier-only mode and an extra rseq preempt on the caller.
    
    Fixes: 70216e18 ("membarrier: Provide core serializing command, *_SYNC_CORE")
    Signed-off-by: default avatarAndy Lutomirski <luto@kernel.org>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Reviewed-by: default avatarMathieu Desnoyers <mathieu.desnoyers@efficios.com>
    Link: https://lore.kernel.org/r/250ded637696d490c69bef1877148db86066881c.1607058304.git.luto@kernel.org
    e45cdc71
membarrier.c 14 KB