diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-28 14:13:16 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-28 14:13:16 -0700 |
commit | 0e9117882da14e7914d05cf14781a7ac9c61c670 (patch) | |
tree | 56a63c2e7758b387ed09ed57847660acb846b498 /net/tipc/socket.c | |
parent | affb852d2fa260402cbdc77976adb0dcda3b5fae (diff) | |
parent | 4c761daf8bb9a2cbda9facf53ea85d9061f4281e (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller:
"Just a couple more stragglers, I really hope this is it.
1) Don't let frags slip down into the GRO segmentation handlers, from
Steffen Klassert.
2) Truesize under-estimation triggers warnings in TCP over loopback
with socket filters, 2 part fix from Eric Dumazet.
3) Fix undesirable reset of bonding MTU to ETH_HLEN on slave removal,
from Paolo Abeni.
4) If we flush the XFRM policy after garbage collection, it doesn't
work because stray entries can be created afterwards. Fix from Xin
Long.
5) Hung socket connection fixes in TIPC from Parthasarathy Bhuvaragan.
6) Fix GRO regression with IPSEC when netfilter is disabled, from
Sabrina Dubroca.
7) Fix cpsw driver Kconfig dependency regression, from Arnd Bergmann"
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
net: hso: register netdev later to avoid a race condition
net: adjust skb->truesize in ___pskb_trim()
tcp: do not underestimate skb->truesize in tcp_trim_head()
bonding: avoid defaulting hard_header_len to ETH_HLEN on slave removal
ipv4: Don't pass IP fragments to upper layer GRO handlers.
cpsw/netcp: refine cpts dependency
tipc: close the connection if protocol messages contain errors
tipc: improve error validations for sockets in CONNECTING state
tipc: Fix missing connection request handling
xfrm: fix GRO for !CONFIG_NETFILTER
xfrm: do the garbage collection after flushing policy
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 566906795c8c..bdce99f9407a 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -866,6 +866,14 @@ static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb, if (!tsk_peer_msg(tsk, hdr)) goto exit; + if (unlikely(msg_errcode(hdr))) { + tipc_set_sk_state(sk, TIPC_DISCONNECTING); + tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk), + tsk_peer_port(tsk)); + sk->sk_state_change(sk); + goto exit; + } + tsk->probe_unacked = false; if (mtyp == CONN_PROBE) { @@ -1259,7 +1267,10 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop) struct sock *sk = sock->sk; DEFINE_WAIT(wait); long timeo = *timeop; - int err; + int err = sock_error(sk); + + if (err) + return err; for (;;) { prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); @@ -1281,6 +1292,10 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop) err = sock_intr_errno(timeo); if (signal_pending(current)) break; + + err = sock_error(sk); + if (err) + break; } finish_wait(sk_sleep(sk), &wait); *timeop = timeo; @@ -1551,6 +1566,8 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb) struct sock *sk = &tsk->sk; struct net *net = sock_net(sk); struct tipc_msg *hdr = buf_msg(skb); + u32 pport = msg_origport(hdr); + u32 pnode = msg_orignode(hdr); if (unlikely(msg_mcast(hdr))) return false; @@ -1558,18 +1575,28 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb) switch (sk->sk_state) { case TIPC_CONNECTING: /* Accept only ACK or NACK message */ - if (unlikely(!msg_connected(hdr))) - return false; + if (unlikely(!msg_connected(hdr))) { + if (pport != tsk_peer_port(tsk) || + pnode != tsk_peer_node(tsk)) + return false; + + tipc_set_sk_state(sk, TIPC_DISCONNECTING); + sk->sk_err = ECONNREFUSED; + sk->sk_state_change(sk); + return true; + } if (unlikely(msg_errcode(hdr))) { tipc_set_sk_state(sk, TIPC_DISCONNECTING); sk->sk_err = ECONNREFUSED; + sk->sk_state_change(sk); return true; } if (unlikely(!msg_isdata(hdr))) { tipc_set_sk_state(sk, TIPC_DISCONNECTING); sk->sk_err = EINVAL; + sk->sk_state_change(sk); return true; } @@ -1581,8 +1608,7 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb) return true; /* If empty 'ACK-' message, wake up sleeping connect() */ - if (waitqueue_active(sk_sleep(sk))) - wake_up_interruptible(sk_sleep(sk)); + sk->sk_data_ready(sk); /* 'ACK-' message is neither accepted nor rejected: */ msg_set_dest_droppable(hdr, 1); |