Skip to content

Commit f6ba8d3

Browse files
edumazetdavem330
authored andcommitted
netem: fix skb_orphan_partial()
I should have known that lowering skb->truesize was dangerous :/ In case packets are not leaving the host via a standard Ethernet device, but looped back to local sockets, bad things can happen, as reported by Michael Madsen ( https://bugzilla.kernel.org/show_bug.cgi?id=195713 ) So instead of tweaking skb->truesize, lets change skb->destructor and keep a reference on the owner socket via its sk_refcnt. Fixes: f2f872f ("netem: Introduce skb_orphan_partial() helper") Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Michael Madsen <mkm@nabto.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 4e3c60e commit f6ba8d3

File tree

1 file changed

+8
-12
lines changed

1 file changed

+8
-12
lines changed

net/core/sock.c

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1803,28 +1803,24 @@ EXPORT_SYMBOL(skb_set_owner_w);
18031803
* delay queue. We want to allow the owner socket to send more
18041804
* packets, as if they were already TX completed by a typical driver.
18051805
* But we also want to keep skb->sk set because some packet schedulers
1806-
* rely on it (sch_fq for example). So we set skb->truesize to a small
1807-
* amount (1) and decrease sk_wmem_alloc accordingly.
1806+
* rely on it (sch_fq for example).
18081807
*/
18091808
void skb_orphan_partial(struct sk_buff *skb)
18101809
{
1811-
/* If this skb is a TCP pure ACK or already went here,
1812-
* we have nothing to do. 2 is already a very small truesize.
1813-
*/
1814-
if (skb->truesize <= 2)
1810+
if (skb_is_tcp_pure_ack(skb))
18151811
return;
18161812

1817-
/* TCP stack sets skb->ooo_okay based on sk_wmem_alloc,
1818-
* so we do not completely orphan skb, but transfert all
1819-
* accounted bytes but one, to avoid unexpected reorders.
1820-
*/
18211813
if (skb->destructor == sock_wfree
18221814
#ifdef CONFIG_INET
18231815
|| skb->destructor == tcp_wfree
18241816
#endif
18251817
) {
1826-
atomic_sub(skb->truesize - 1, &skb->sk->sk_wmem_alloc);
1827-
skb->truesize = 1;
1818+
struct sock *sk = skb->sk;
1819+
1820+
if (atomic_inc_not_zero(&sk->sk_refcnt)) {
1821+
atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
1822+
skb->destructor = sock_efree;
1823+
}
18281824
} else {
18291825
skb_orphan(skb);
18301826
}

0 commit comments

Comments
 (0)