Partha,
I think it would be simpler to just always keep the packet list on the 
stack, like it was before I introduced the faulty patch.
Yes, it costs a couple of cycles extra, but simplicity is also an 
important factor here.

///jon


On 02/24/2016 10:23 AM, Parthasarathy Bhuvaragan wrote:
> In Commit 94153e36e709e ("tipc: use existing sk_write_queue for
> outgoing packet chain"), we assume that we fill & empty the socket's
> sk_write_queue within the same lock_sock() session.
>
> This is not true if the link is congested. During congestion, the
> socket lock is released while we wait for the congestion to cease.
> This implementation causes a nullptr exception, if the user space
> program has several threads accessing the same socket descriptor.
>
> Consider two threads of the same program performing the following:
>       Thread1                                  Thread2
> --------------------                    ----------------------
> Enter tipc_sendmsg()                    Enter tipc_sendmsg()
> lock_sock()                             lock_sock()
> Enter tipc_link_xmit(), ret=ELINKCONG   spin on socket lock..
> sk_wait_event()                             :
> release_sock()                          grab socket lock
>      :                                   Enter tipc_link_xmit(), ret=0
>      :                                   release_sock()
> Wakeup after congestion
> lock_sock()
> skb = skb_peek(pktchain);
> !! TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong;
>
> In this case, the second thread transmits the buffers belonging to both
> thread1 and thread2 successfully. When the first thread wakeup after the
> congestion it assumes that the pktchain is intact and operates on the skb's
> in it, which leads to nullptr exception as follows:
>
> [2102.439969] BUG: unable to handle kernel NULL pointer dereference at 
> 00000000000000d0
> [2102.440074] IP: [<ffffffffa005f330>] __tipc_link_xmit+0x2b0/0x4d0 [tipc]
> [2102.440074] PGD 3fa3f067 PUD 3fa6b067 PMD 0
> [2102.440074] Oops: 0000 [#1] SMP
> [2102.440074] CPU: 2 PID: 244 Comm: sender Not tainted 3.12.28 #1
> [2102.440074] RIP: 0010:[<ffffffffa005f330>]  [<ffffffffa005f330>] 
> __tipc_link_xmit+0x2b0/0x4d0 [tipc]
> [...]
> [2102.440074] Call Trace:
> [2102.440074]  [<ffffffff8163f0b9>] ? schedule+0x29/0x70
> [2102.440074]  [<ffffffffa006a756>] ? tipc_node_unlock+0x46/0x170 [tipc]
> [2102.440074]  [<ffffffffa005f761>] tipc_link_xmit+0x51/0xf0 [tipc]
> [2102.440074]  [<ffffffffa006d8ae>] tipc_send_stream+0x11e/0x4f0 [tipc]
> [2102.440074]  [<ffffffff8106b150>] ? __wake_up_sync+0x20/0x20
> [2102.440074]  [<ffffffffa006dc9c>] tipc_send_packet+0x1c/0x20 [tipc]
> [2102.440074]  [<ffffffff81502478>] sock_sendmsg+0xa8/0xd0
> [2102.440074]  [<ffffffff81507895>] ? release_sock+0x145/0x170
> [2102.440074]  [<ffffffff815030d8>] ___sys_sendmsg+0x3d8/0x3e0
> [2102.440074]  [<ffffffff816426ae>] ? _raw_spin_unlock+0xe/0x10
> [2102.440074]  [<ffffffff81115c2a>] ? handle_mm_fault+0x6ca/0x9d0
> [2102.440074]  [<ffffffff8107dd65>] ? set_next_entity+0x85/0xa0
> [2102.440074]  [<ffffffff816426de>] ? _raw_spin_unlock_irq+0xe/0x20
> [2102.440074]  [<ffffffff8107463c>] ? finish_task_switch+0x5c/0xc0
> [2102.440074]  [<ffffffff8163ea8c>] ? __schedule+0x34c/0x950
> [2102.440074]  [<ffffffff81504e12>] __sys_sendmsg+0x42/0x80
> [2102.440074]  [<ffffffff81504e62>] SyS_sendmsg+0x12/0x20
> [2102.440074]  [<ffffffff8164aed2>] system_call_fastpath+0x16/0x1b
>
> In this commit, we maintain the buffer list in the stack during congestion
> and use sk_write_queue otherwise.
>
> Fixes:
> 94153e36e709e ("tipc: use existing sk_write_queue for outgoing packet chain")
> Signed-off-by: Parthasarathy Bhuvaragan 
> <[email protected]>
> ---
>   net/tipc/socket.c | 19 +++++++++++++++++++
>   1 file changed, 19 insertions(+)
>
> diff --git a/net/tipc/socket.c b/net/tipc/socket.c
> index 69c29050f14a..bb5875c18c98 100644
> --- a/net/tipc/socket.c
> +++ b/net/tipc/socket.c
> @@ -674,6 +674,7 @@ static int tipc_sendmcast(struct  socket *sock, struct 
> tipc_name_seq *seq,
>       struct net *net = sock_net(sk);
>       struct tipc_msg *mhdr = &tsk->phdr;
>       struct sk_buff_head *pktchain = &sk->sk_write_queue;
> +     struct sk_buff_head tmpq;
>       struct iov_iter save = msg->msg_iter;
>       uint mtu;
>       int rc;
> @@ -687,6 +688,11 @@ static int tipc_sendmcast(struct  socket *sock, struct 
> tipc_name_seq *seq,
>       msg_set_nameupper(mhdr, seq->upper);
>       msg_set_hdr_sz(mhdr, MCAST_H_SIZE);
>   
> +     if (likely(!skb_queue_empty(pktchain))) {
> +             skb_queue_head_init(&tmpq);
> +             pktchain = &tmpq;
> +     }
> +
>   new_mtu:
>       mtu = tipc_bcast_get_mtu(net);
>       rc = tipc_msg_build(mhdr, msg, 0, dsz, mtu, pktchain);
> @@ -864,6 +870,7 @@ static int __tipc_sendmsg(struct socket *sock, struct 
> msghdr *m, size_t dsz)
>       struct tipc_msg *mhdr = &tsk->phdr;
>       u32 dnode, dport;
>       struct sk_buff_head *pktchain = &sk->sk_write_queue;
> +     struct sk_buff_head tmpq;
>       struct sk_buff *skb;
>       struct tipc_name_seq *seq;
>       struct iov_iter save;
> @@ -924,6 +931,11 @@ static int __tipc_sendmsg(struct socket *sock, struct 
> msghdr *m, size_t dsz)
>               msg_set_hdr_sz(mhdr, BASIC_H_SIZE);
>       }
>   
> +     if (likely(!skb_queue_empty(pktchain))) {
> +             skb_queue_head_init(&tmpq);
> +             pktchain = &tmpq;
> +     }
> +
>       save = m->msg_iter;
>   new_mtu:
>       mtu = tipc_node_get_mtu(net, dnode, tsk->portid);
> @@ -1017,6 +1029,7 @@ static int __tipc_send_stream(struct socket *sock, 
> struct msghdr *m, size_t dsz)
>       struct tipc_sock *tsk = tipc_sk(sk);
>       struct tipc_msg *mhdr = &tsk->phdr;
>       struct sk_buff_head *pktchain = &sk->sk_write_queue;
> +     struct sk_buff_head tmpq;
>       DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
>       u32 portid = tsk->portid;
>       int rc = -EINVAL;
> @@ -1045,6 +1058,11 @@ static int __tipc_send_stream(struct socket *sock, 
> struct msghdr *m, size_t dsz)
>       timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
>       dnode = tsk_peer_node(tsk);
>   
> +     if (likely(!skb_queue_empty(pktchain))) {
> +             skb_queue_head_init(&tmpq);
> +             pktchain = &tmpq;
> +     }
> +
>   next:
>       save = m->msg_iter;
>       mtu = tsk->max_pkt;
> @@ -1052,6 +1070,7 @@ next:
>       rc = tipc_msg_build(mhdr, m, sent, send, mtu, pktchain);
>       if (unlikely(rc < 0))
>               return rc;
> +
>       do {
>               if (likely(!tsk_conn_cong(tsk))) {
>                       rc = tipc_node_xmit(net, pktchain, dnode, portid);


------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
tipc-discussion mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tipc-discussion

Reply via email to