aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
authorTung Nguyen <tung.q.nguyen@dektech.com.au>2018-09-28 14:23:22 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-29 14:24:22 -0400
commit6787927475e52f6933e3affce365dabb2aa2fadf (patch)
treebb149221e75bb812ed610f50f993d81c55af9dd8 /net/tipc/socket.c
parent25b9221b959483f17c2964d0922869e16caa86b5 (diff)
tipc: buffer overflow handling in listener socket
Default socket receive buffer size for a listener socket is 2Mb. For each arriving empty SYN, the linux kernel allocates a 768 bytes buffer. This means that a listener socket can serve maximum 2700 simultaneous empty connection setup requests before it hits a receive buffer overflow, and much fewer if the SYN is carrying any significant amount of data. When this happens the setup request is rejected, and the client receives an ECONNREFUSED error. This commit mitigates this problem by letting the client socket try to retransmit the SYN message multiple times when it sees it rejected with the code TIPC_ERR_OVERLOAD. Retransmission is done at random intervals in the range of [100 ms, setup_timeout / 4], as many times as there is room for within the setup timeout limit. Signed-off-by: Tung Nguyen <tung.q.nguyen@dektech.com.au> Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 89d6dc0f456d..595c5001b28d 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -47,7 +47,7 @@
47#include "netlink.h" 47#include "netlink.h"
48#include "group.h" 48#include "group.h"
49 49
50#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ 50#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */
51#define CONN_PROBING_INTV msecs_to_jiffies(3600000) /* [ms] => 1 h */ 51#define CONN_PROBING_INTV msecs_to_jiffies(3600000) /* [ms] => 1 h */
52#define TIPC_FWD_MSG 1 52#define TIPC_FWD_MSG 1
53#define TIPC_MAX_PORT 0xffffffff 53#define TIPC_MAX_PORT 0xffffffff
@@ -80,7 +80,6 @@ struct sockaddr_pair {
80 * @publications: list of publications for port 80 * @publications: list of publications for port
81 * @blocking_link: address of the congested link we are currently sleeping on 81 * @blocking_link: address of the congested link we are currently sleeping on
82 * @pub_count: total # of publications port has made during its lifetime 82 * @pub_count: total # of publications port has made during its lifetime
83 * @probing_state:
84 * @conn_timeout: the time we can wait for an unresponded setup request 83 * @conn_timeout: the time we can wait for an unresponded setup request
85 * @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue 84 * @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue
86 * @cong_link_cnt: number of congested links 85 * @cong_link_cnt: number of congested links
@@ -102,8 +101,8 @@ struct tipc_sock {
102 struct list_head cong_links; 101 struct list_head cong_links;
103 struct list_head publications; 102 struct list_head publications;
104 u32 pub_count; 103 u32 pub_count;
105 uint conn_timeout;
106 atomic_t dupl_rcvcnt; 104 atomic_t dupl_rcvcnt;
105 u16 conn_timeout;
107 bool probe_unacked; 106 bool probe_unacked;
108 u16 cong_link_cnt; 107 u16 cong_link_cnt;
109 u16 snt_unacked; 108 u16 snt_unacked;
@@ -507,6 +506,9 @@ static void __tipc_shutdown(struct socket *sock, int error)
507 tipc_wait_for_cond(sock, &timeout, (!tsk->cong_link_cnt && 506 tipc_wait_for_cond(sock, &timeout, (!tsk->cong_link_cnt &&
508 !tsk_conn_cong(tsk))); 507 !tsk_conn_cong(tsk)));
509 508
509 /* Remove any pending SYN message */
510 __skb_queue_purge(&sk->sk_write_queue);
511
510 /* Reject all unreceived messages, except on an active connection 512 /* Reject all unreceived messages, except on an active connection
511 * (which disconnects locally & sends a 'FIN+' to peer). 513 * (which disconnects locally & sends a 'FIN+' to peer).
512 */ 514 */
@@ -1362,6 +1364,8 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
1362 rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts); 1364 rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts);
1363 if (unlikely(rc != dlen)) 1365 if (unlikely(rc != dlen))
1364 return rc; 1366 return rc;
1367 if (unlikely(syn && !tipc_msg_skb_clone(&pkts, &sk->sk_write_queue)))
1368 return -ENOMEM;
1365 1369
1366 rc = tipc_node_xmit(net, &pkts, dnode, tsk->portid); 1370 rc = tipc_node_xmit(net, &pkts, dnode, tsk->portid);
1367 if (unlikely(rc == -ELINKCONG)) { 1371 if (unlikely(rc == -ELINKCONG)) {
@@ -1491,6 +1495,7 @@ static void tipc_sk_finish_conn(struct tipc_sock *tsk, u32 peer_port,
1491 tipc_node_add_conn(net, peer_node, tsk->portid, peer_port); 1495 tipc_node_add_conn(net, peer_node, tsk->portid, peer_port);
1492 tsk->max_pkt = tipc_node_get_mtu(net, peer_node, tsk->portid); 1496 tsk->max_pkt = tipc_node_get_mtu(net, peer_node, tsk->portid);
1493 tsk->peer_caps = tipc_node_get_capabilities(net, peer_node); 1497 tsk->peer_caps = tipc_node_get_capabilities(net, peer_node);
1498 __skb_queue_purge(&sk->sk_write_queue);
1494 if (tsk->peer_caps & TIPC_BLOCK_FLOWCTL) 1499 if (tsk->peer_caps & TIPC_BLOCK_FLOWCTL)
1495 return; 1500 return;
1496 1501
@@ -1977,6 +1982,7 @@ static bool tipc_sk_filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
1977 u32 oport = msg_origport(hdr); 1982 u32 oport = msg_origport(hdr);
1978 u32 onode = msg_orignode(hdr); 1983 u32 onode = msg_orignode(hdr);
1979 int err = msg_errcode(hdr); 1984 int err = msg_errcode(hdr);
1985 unsigned long delay;
1980 1986
1981 if (unlikely(msg_mcast(hdr))) 1987 if (unlikely(msg_mcast(hdr)))
1982 return false; 1988 return false;
@@ -2001,8 +2007,18 @@ static bool tipc_sk_filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
2001 if (oport != pport || onode != pnode) 2007 if (oport != pport || onode != pnode)
2002 return false; 2008 return false;
2003 2009
2004 /* Rejected SYN - abort */ 2010 /* Rejected SYN */
2005 break; 2011 if (err != TIPC_ERR_OVERLOAD)
2012 break;
2013
2014 /* Prepare for new setup attempt if we have a SYN clone */
2015 if (skb_queue_empty(&sk->sk_write_queue))
2016 break;
2017 get_random_bytes(&delay, 2);
2018 delay %= (tsk->conn_timeout / 4);
2019 delay = msecs_to_jiffies(delay + 100);
2020 sk_reset_timer(sk, &sk->sk_timer, jiffies + delay);
2021 return false;
2006 case TIPC_OPEN: 2022 case TIPC_OPEN:
2007 case TIPC_DISCONNECTING: 2023 case TIPC_DISCONNECTING:
2008 return false; 2024 return false;
@@ -2561,12 +2577,26 @@ static void tipc_sk_check_probing_state(struct sock *sk,
2561 sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTV); 2577 sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTV);
2562} 2578}
2563 2579
2580static void tipc_sk_retry_connect(struct sock *sk, struct sk_buff_head *list)
2581{
2582 struct tipc_sock *tsk = tipc_sk(sk);
2583
2584 /* Try again later if dest link is congested */
2585 if (tsk->cong_link_cnt) {
2586 sk_reset_timer(sk, &sk->sk_timer, msecs_to_jiffies(100));
2587 return;
2588 }
2589 /* Prepare SYN for retransmit */
2590 tipc_msg_skb_clone(&sk->sk_write_queue, list);
2591}
2592
2564static void tipc_sk_timeout(struct timer_list *t) 2593static void tipc_sk_timeout(struct timer_list *t)
2565{ 2594{
2566 struct sock *sk = from_timer(sk, t, sk_timer); 2595 struct sock *sk = from_timer(sk, t, sk_timer);
2567 struct tipc_sock *tsk = tipc_sk(sk); 2596 struct tipc_sock *tsk = tipc_sk(sk);
2568 u32 pnode = tsk_peer_node(tsk); 2597 u32 pnode = tsk_peer_node(tsk);
2569 struct sk_buff_head list; 2598 struct sk_buff_head list;
2599 int rc = 0;
2570 2600
2571 skb_queue_head_init(&list); 2601 skb_queue_head_init(&list);
2572 bh_lock_sock(sk); 2602 bh_lock_sock(sk);
@@ -2580,12 +2610,19 @@ static void tipc_sk_timeout(struct timer_list *t)
2580 2610
2581 if (sk->sk_state == TIPC_ESTABLISHED) 2611 if (sk->sk_state == TIPC_ESTABLISHED)
2582 tipc_sk_check_probing_state(sk, &list); 2612 tipc_sk_check_probing_state(sk, &list);
2613 else if (sk->sk_state == TIPC_CONNECTING)
2614 tipc_sk_retry_connect(sk, &list);
2583 2615
2584 bh_unlock_sock(sk); 2616 bh_unlock_sock(sk);
2585 2617
2586 if (!skb_queue_empty(&list)) 2618 if (!skb_queue_empty(&list))
2587 tipc_node_xmit(sock_net(sk), &list, pnode, tsk->portid); 2619 rc = tipc_node_xmit(sock_net(sk), &list, pnode, tsk->portid);
2588 2620
2621 /* SYN messages may cause link congestion */
2622 if (rc == -ELINKCONG) {
2623 tipc_dest_push(&tsk->cong_links, pnode, 0);
2624 tsk->cong_link_cnt = 1;
2625 }
2589 sock_put(sk); 2626 sock_put(sk);
2590} 2627}
2591 2628