Eric Dumazet 5037e9ef94 net: fix IP early demux races
David Wilder reported crashes caused by dst reuse.

<quote David>
  I am seeing a crash on a distro V4.2.3 kernel caused by a double
  release of a dst_entry.  In ipv4_dst_destroy() the call to
  list_empty() finds a poisoned next pointer, indicating the dst_entry
  has already been removed from the list and freed. The crash occurs
  18 to 24 hours into a run of a network stress exerciser.
</quote>

Thanks to his detailed report and analysis, we were able to understand
the core issue.

IP early demux can associate a dst to skb, after a lookup in TCP/UDP
sockets.

When socket cache is not properly set, we want to store into
sk->sk_dst_cache the dst for future IP early demux lookups,
by acquiring a stable refcount on the dst.

Problem is this acquisition is simply using an atomic_inc(),
which works well, unless the dst was queued for destruction from
dst_release() noticing dst refcount went to zero, if DST_NOCACHE
was set on dst.

We need to make sure current refcount is not zero before incrementing
it, or risk double free as David reported.

This patch, being a stable candidate, adds two new helpers, and use
them only from IP early demux problematic paths.

It might be possible to merge in net-next skb_dst_force() and
skb_dst_force_safe(), but I prefer having the smallest patch for stable
kernels : Maybe some skb_dst_force() callers do not expect skb->dst
can suddenly be cleared.

Can probably be backported back to linux-3.6 kernels

Reported-by: David J. Wilder <dwilder@us.ibm.com>
Tested-by: David J. Wilder <dwilder@us.ibm.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-12-14 23:52:00 -05:00
..
2015-08-25 13:38:50 -07:00
2015-05-28 11:23:20 +08:00
2015-11-04 21:34:37 -05:00
2015-08-29 13:07:54 -07:00
2015-11-02 22:47:14 -05:00
2013-12-29 16:34:25 -05:00
2015-11-02 22:47:14 -05:00
2015-10-22 19:39:25 -07:00
2015-10-21 07:00:48 -07:00
2015-07-09 21:09:10 -07:00
2015-07-09 14:22:52 -07:00
2015-07-09 14:22:52 -07:00
2015-12-14 23:52:00 -05:00
2015-11-05 14:36:09 -05:00
2014-09-01 18:12:45 -07:00
2015-10-21 07:00:53 -07:00
2015-07-09 14:22:52 -07:00
2015-07-09 14:22:52 -07:00
2015-01-28 22:18:37 -08:00
2012-03-11 23:42:51 -07:00
2015-11-18 14:58:02 -05:00
2014-05-23 16:28:53 -04:00
2015-09-17 17:18:37 -07:00
2013-05-31 17:19:05 -07:00