aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorParthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>2018-10-10 11:50:23 -0400
committerDavid S. Miller <davem@davemloft.net>2018-10-11 01:56:07 -0400
commite7eb05823806502747eadc31039cecfd7836ddeb (patch)
tree7d60d5c73115548c7b18b955a6dcfbf8e2cc1f0b /net/tipc
parent047491ea334a454fa0647ec99dadcc6dd38417e0 (diff)
tipc: queue socket protocol error messages into socket receive buffer
In tipc_sk_filter_rcv(), when we detect protocol messages with error we call tipc_sk_conn_proto_rcv() and let it reset the connection and notify the socket by calling sk->sk_state_change(). However, tipc_sk_filter_rcv() may have been called from the function tipc_backlog_rcv(), in which case the socket lock is held and the socket already awake. This means that the sk_state_change() call is ignored and the error notification lost. Now the receive queue will remain empty and the socket sleeps forever. In this commit, we convert the protocol message into a connection abort message and enqueue it into the socket's receive queue. By this addition to the above state change we cover all conditions. Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/socket.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index b6f99b021d09..49810fdff4c5 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1196,6 +1196,7 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
1196 * @skb: pointer to message buffer. 1196 * @skb: pointer to message buffer.
1197 */ 1197 */
1198static void tipc_sk_conn_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb, 1198static void tipc_sk_conn_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
1199 struct sk_buff_head *inputq,
1199 struct sk_buff_head *xmitq) 1200 struct sk_buff_head *xmitq)
1200{ 1201{
1201 struct tipc_msg *hdr = buf_msg(skb); 1202 struct tipc_msg *hdr = buf_msg(skb);
@@ -1213,7 +1214,16 @@ static void tipc_sk_conn_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
1213 tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk), 1214 tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk),
1214 tsk_peer_port(tsk)); 1215 tsk_peer_port(tsk));
1215 sk->sk_state_change(sk); 1216 sk->sk_state_change(sk);
1216 goto exit; 1217
1218 /* State change is ignored if socket already awake,
1219 * - convert msg to abort msg and add to inqueue
1220 */
1221 msg_set_user(hdr, TIPC_CRITICAL_IMPORTANCE);
1222 msg_set_type(hdr, TIPC_CONN_MSG);
1223 msg_set_size(hdr, BASIC_H_SIZE);
1224 msg_set_hdr_sz(hdr, BASIC_H_SIZE);
1225 __skb_queue_tail(inputq, skb);
1226 return;
1217 } 1227 }
1218 1228
1219 tsk->probe_unacked = false; 1229 tsk->probe_unacked = false;
@@ -1936,7 +1946,7 @@ static void tipc_sk_proto_rcv(struct sock *sk,
1936 1946
1937 switch (msg_user(hdr)) { 1947 switch (msg_user(hdr)) {
1938 case CONN_MANAGER: 1948 case CONN_MANAGER:
1939 tipc_sk_conn_proto_rcv(tsk, skb, xmitq); 1949 tipc_sk_conn_proto_rcv(tsk, skb, inputq, xmitq);
1940 return; 1950 return;
1941 case SOCK_WAKEUP: 1951 case SOCK_WAKEUP:
1942 tipc_dest_del(&tsk->cong_links, msg_orignode(hdr), 0); 1952 tipc_dest_del(&tsk->cong_links, msg_orignode(hdr), 0);