2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-21 11:44:01 +08:00

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>
This commit is contained in:
Parthasarathy Bhuvaragan 2018-10-10 17:50:23 +02:00 committed by David S. Miller
parent 047491ea33
commit e7eb058238

View File

@ -1196,6 +1196,7 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
* @skb: pointer to message buffer. * @skb: pointer to message buffer.
*/ */
static void tipc_sk_conn_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb, static void tipc_sk_conn_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
struct sk_buff_head *inputq,
struct sk_buff_head *xmitq) struct sk_buff_head *xmitq)
{ {
struct tipc_msg *hdr = buf_msg(skb); 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,
tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk), tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk),
tsk_peer_port(tsk)); tsk_peer_port(tsk));
sk->sk_state_change(sk); sk->sk_state_change(sk);
goto exit;
/* State change is ignored if socket already awake,
* - convert msg to abort msg and add to inqueue
*/
msg_set_user(hdr, TIPC_CRITICAL_IMPORTANCE);
msg_set_type(hdr, TIPC_CONN_MSG);
msg_set_size(hdr, BASIC_H_SIZE);
msg_set_hdr_sz(hdr, BASIC_H_SIZE);
__skb_queue_tail(inputq, skb);
return;
} }
tsk->probe_unacked = false; tsk->probe_unacked = false;
@ -1936,7 +1946,7 @@ static void tipc_sk_proto_rcv(struct sock *sk,
switch (msg_user(hdr)) { switch (msg_user(hdr)) {
case CONN_MANAGER: case CONN_MANAGER:
tipc_sk_conn_proto_rcv(tsk, skb, xmitq); tipc_sk_conn_proto_rcv(tsk, skb, inputq, xmitq);
return; return;
case SOCK_WAKEUP: case SOCK_WAKEUP:
tipc_dest_del(&tsk->cong_links, msg_orignode(hdr), 0); tipc_dest_del(&tsk->cong_links, msg_orignode(hdr), 0);