Patch "tipc: Fix tipc_sk_reinit race conditions" has been added to the 4.9-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
tipc: Fix tipc_sk_reinit race conditions
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
tipc-fix-tipc_sk_reinit-race-conditions.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Thu Jun 15 09:31:48 CEST 2017
From: Herbert Xu <[email protected]>
Date: Tue, 23 May 2017 21:53:35 -0400
Subject: tipc: Fix tipc_sk_reinit race conditions
From: Herbert Xu <[email protected]>
[ Upstream commit 9dbbfb0ab6680c6a85609041011484e6658e7d3c ]
There are two problems with the function tipc_sk_reinit. Firstly it's doing a manual walk over an rhashtable. This is broken as an rhashtable can be resized and if you manually walk over it during a resize then you may miss entries.
Secondly it's missing memory barriers as previously the code used spinlocks which provide the barriers implicitly.
This patch fixes both problems.
--- net/tipc/net.c | 4 ++++ net/tipc/socket.c | 30 +++++++++++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-)
net/tipc/net.c +4 -0
@@ -110,6 +110,10 @@ int tipc_net_start(struct net *net, u32char addr_string[16 ]; tn->own_addr = addr; + +/* Ensure that the new address is visible before we reinit. */ +smp_mb (); +tipc_named_reinit (net);tipc_sk_reinit (net);
net/tipc/socket.c +19 -11
@@ -335,8 +335,6 @@ static int tipc_sk_create(struct net *neINIT_LIST_HEAD (&tsk->publications); msg = &tsk->phdr; tn =net_generic (sock_net (sk), tipc_net_id); -tipc_msg_init (tn->own_addr, msg,TIPC_LOW_IMPORTANCE ,TIPC_NAMED_MSG , -NAMED_H_SIZE ,0 );/* Finish initializing socket data structures */ sock->ops = ops;
@@ -346,6 +344,13 @@ static int tipc_sk_create(struct net *nepr_warn ("Socket create failed; port number exhausted\n" );return -EINVAL ; } + +/* Ensure tsk is visible before we read own_addr. */ +smp_mb (); + +tipc_msg_init (tn->own_addr, msg,TIPC_LOW_IMPORTANCE ,TIPC_NAMED_MSG , +NAMED_H_SIZE ,0 ); +msg_set_origport (msg, tsk->portid);setup_timer (&sk->sk_timer, tipc_sk_timeout, (unsigned long )tsk); sk->sk_backlog_rcv = tipc_backlog_rcv;
@@ -2264,24 +2269,27 @@ static int tipc_sk_withdraw(struct tipc_void tipc_sk_reinit (struct net *net) {struct tipc_net *tn =net_generic (net, tipc_net_id); -const struct bucket_table *tbl; -struct rhash_head *pos; +struct rhashtable_iter iter;struct tipc_sock *tsk;struct tipc_msg *msg; -int i; -rcu_read_lock (); - tbl =rht_dereference_rcu ((&tn->sk_rht)->tbl, &tn->sk_rht); -for (i =0 ; i < tbl->size; i++) { -rht_for_each_entry_rcu (tsk, pos, tbl, i, node) { +rhashtable_walk_enter (&tn->sk_rht, &iter); + +do { + tsk =ERR_PTR (rhashtable_walk_start (&iter)); +if (tsk) +continue ; + +while ((tsk =rhashtable_walk_next (&iter)) && !IS_ERR (tsk)) {spin_lock_bh (&tsk->sk.sk_lock.slock); msg = &tsk->phdr;msg_set_prevnode (msg, tn->own_addr);msg_set_orignode (msg, tn->own_addr);spin_unlock_bh (&tsk->sk.sk_lock.slock); } - } -rcu_read_unlock (); + +rhashtable_walk_stop (&iter); + }while (tsk ==ERR_PTR (-EAGAIN )); }static struct tipc_sock *tipc_sk_lookup (struct net *net,u32 portid)
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch queue-4.9/tipc-fix-tipc_sk_reinit-race-conditions.patch