locking/qspinlock: Ensure node->count is updated before initialising node

"Linux Kernel Mailing List" <[email protected]> Thu, 15 Feb 2018 17:37:49 +0000 (UTC)
Newsgroups gmane.linux.kernel.commits.head
Message-ID <[email protected]>
Web:        https://git.kernel.org/torvalds/c/11dc13224c975efcec96647a4768a6f1bb7a19a8
Commit:     11dc13224c975efcec96647a4768a6f1bb7a19a8
Parent:     95bcade33a8af38755c9b0636e36a36ad3789fe6
Refname:    refs/heads/master
Author:     Will Deacon <[email protected]>
AuthorDate: Tue Feb 13 13:22:57 2018 +0000
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue Feb 13 14:50:14 2018 +0100

    locking/qspinlock: Ensure node->count is updated before initialising node
    
    When queuing on the qspinlock, the count field for the current CPU's head
    node is incremented. This needn't be atomic because locking in e.g. IRQ
    context is balanced and so an IRQ will return with node->count as it
    found it.
    
    However, the compiler could in theory reorder the initialisation of
    node[idx] before the increment of the head node->count, causing an
    IRQ to overwrite the initialised node and potentially corrupt the lock
    state.
    
    Avoid the potential for this harmful compiler reordering by placing a
    barrier() between the increment of the head node->count and the subsequent
    node initialisation.
    
    Signed-off-by: Will Deacon <[email protected]>
    Acked-by: Peter Zijlstra (Intel) <[email protected]>
    Cc: Linus Torvalds <[email protected]>
    Cc: Thomas Gleixner <[email protected]>
    Link: http://lkml.kernel.org/r/[email protected]
    Signed-off-by: Ingo Molnar <[email protected]>
---
 kernel/locking/qspinlock.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
index 348c8cec1042..d880296245c5 100644
--- a/kernel/locking/qspinlock.c
+++ b/kernel/locking/qspinlock.c
@@ -379,6 +379,14 @@ queue:
 	tail = encode_tail(smp_processor_id(), idx);
 
 	node += idx;
+
+	/*
+	 * Ensure that we increment the head node->count before initialising
+	 * the actual node. If the compiler is kind enough to reorder these
+	 * stores, then an IRQ could overwrite our assignments.
+	 */
+	barrier();
+
 	node->locked = 0;
 	node->next = NULL;
 	pv_init_node(node);
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html