Skip to content

Commit ea2bc48

Browse files
Tsutomu FujiiDavid S. Miller
Tsutomu Fujii
authored and
David S. Miller
committed
[SCTP]: Fix assertion (!atomic_read(&sk->sk_rmem_alloc)) failed message
In current implementation, LKSCTP does receive buffer accounting for data in sctp_receive_queue and pd_lobby. However, LKSCTP don't do accounting for data in frag_list when data is fragmented. In addition, LKSCTP doesn't do accounting for data in reasm and lobby queue in structure sctp_ulpq. When there are date in these queue, assertion failed message is printed in inet_sock_destruct because sk_rmem_alloc of oldsk does not become 0 when socket is destroyed. Signed-off-by: Tsutomu Fujii <t-fujii@nb.jp.nec.com> Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent c2ecba7 commit ea2bc48

File tree

1 file changed

+44
-4
lines changed

1 file changed

+44
-4
lines changed

Diff for: net/sctp/socket.c

+44-4
Original file line numberDiff line numberDiff line change
@@ -5638,6 +5638,36 @@ void sctp_wait_for_close(struct sock *sk, long timeout)
56385638
finish_wait(sk->sk_sleep, &wait);
56395639
}
56405640

5641+
static void sctp_sock_rfree_frag(struct sk_buff *skb)
5642+
{
5643+
struct sk_buff *frag;
5644+
5645+
if (!skb->data_len)
5646+
goto done;
5647+
5648+
/* Don't forget the fragments. */
5649+
for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next)
5650+
sctp_sock_rfree_frag(frag);
5651+
5652+
done:
5653+
sctp_sock_rfree(skb);
5654+
}
5655+
5656+
static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk)
5657+
{
5658+
struct sk_buff *frag;
5659+
5660+
if (!skb->data_len)
5661+
goto done;
5662+
5663+
/* Don't forget the fragments. */
5664+
for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next)
5665+
sctp_skb_set_owner_r_frag(frag, sk);
5666+
5667+
done:
5668+
sctp_skb_set_owner_r(skb, sk);
5669+
}
5670+
56415671
/* Populate the fields of the newsk from the oldsk and migrate the assoc
56425672
* and its messages to the newsk.
56435673
*/
@@ -5692,10 +5722,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
56925722
sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
56935723
event = sctp_skb2event(skb);
56945724
if (event->asoc == assoc) {
5695-
sctp_sock_rfree(skb);
5725+
sctp_sock_rfree_frag(skb);
56965726
__skb_unlink(skb, &oldsk->sk_receive_queue);
56975727
__skb_queue_tail(&newsk->sk_receive_queue, skb);
5698-
sctp_skb_set_owner_r(skb, newsk);
5728+
sctp_skb_set_owner_r_frag(skb, newsk);
56995729
}
57005730
}
57015731

@@ -5723,10 +5753,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
57235753
sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
57245754
event = sctp_skb2event(skb);
57255755
if (event->asoc == assoc) {
5726-
sctp_sock_rfree(skb);
5756+
sctp_sock_rfree_frag(skb);
57275757
__skb_unlink(skb, &oldsp->pd_lobby);
57285758
__skb_queue_tail(queue, skb);
5729-
sctp_skb_set_owner_r(skb, newsk);
5759+
sctp_skb_set_owner_r_frag(skb, newsk);
57305760
}
57315761
}
57325762

@@ -5738,6 +5768,16 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
57385768

57395769
}
57405770

5771+
sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) {
5772+
sctp_sock_rfree_frag(skb);
5773+
sctp_skb_set_owner_r_frag(skb, newsk);
5774+
}
5775+
5776+
sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) {
5777+
sctp_sock_rfree_frag(skb);
5778+
sctp_skb_set_owner_r_frag(skb, newsk);
5779+
}
5780+
57415781
/* Set the type of socket to indicate that it is peeled off from the
57425782
* original UDP-style socket or created with the accept() call on a
57435783
* TCP-style socket..

0 commit comments

Comments
 (0)