diff options
| author | ramesh.nagappa@gmail.com <ramesh.nagappa@gmail.com> | 2012-10-05 15:10:15 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-10-07 14:42:39 -0400 |
| commit | e1f165032c8bade3a6bdf546f8faf61fda4dd01c (patch) | |
| tree | 891c87188420b6a0d42fa25684266ca58ccfe7ef /net | |
| parent | 0bd8ba18b9384e1c9104eee1d912fd5c8b4234c0 (diff) | |
net: Fix skb_under_panic oops in neigh_resolve_output
The retry loop in neigh_resolve_output() and neigh_connected_output()
call dev_hard_header() with out reseting the skb to network_header.
This causes the retry to fail with skb_under_panic. The fix is to
reset the network_header within the retry loop.
Signed-off-by: Ramesh Nagappa <ramesh.nagappa@ericsson.com>
Reviewed-by: Shawn Lu <shawn.lu@ericsson.com>
Reviewed-by: Robert Coulson <robert.coulson@ericsson.com>
Reviewed-by: Billie Alsup <billie.alsup@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
| -rw-r--r-- | net/core/neighbour.c | 6 |
1 files changed, 2 insertions, 4 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index baca771caae2..22571488730a 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -1301,8 +1301,6 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) | |||
| 1301 | if (!dst) | 1301 | if (!dst) |
| 1302 | goto discard; | 1302 | goto discard; |
| 1303 | 1303 | ||
| 1304 | __skb_pull(skb, skb_network_offset(skb)); | ||
| 1305 | |||
| 1306 | if (!neigh_event_send(neigh, skb)) { | 1304 | if (!neigh_event_send(neigh, skb)) { |
| 1307 | int err; | 1305 | int err; |
| 1308 | struct net_device *dev = neigh->dev; | 1306 | struct net_device *dev = neigh->dev; |
| @@ -1312,6 +1310,7 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) | |||
| 1312 | neigh_hh_init(neigh, dst); | 1310 | neigh_hh_init(neigh, dst); |
| 1313 | 1311 | ||
| 1314 | do { | 1312 | do { |
| 1313 | __skb_pull(skb, skb_network_offset(skb)); | ||
| 1315 | seq = read_seqbegin(&neigh->ha_lock); | 1314 | seq = read_seqbegin(&neigh->ha_lock); |
| 1316 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), | 1315 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), |
| 1317 | neigh->ha, NULL, skb->len); | 1316 | neigh->ha, NULL, skb->len); |
| @@ -1342,9 +1341,8 @@ int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb) | |||
| 1342 | unsigned int seq; | 1341 | unsigned int seq; |
| 1343 | int err; | 1342 | int err; |
| 1344 | 1343 | ||
| 1345 | __skb_pull(skb, skb_network_offset(skb)); | ||
| 1346 | |||
| 1347 | do { | 1344 | do { |
| 1345 | __skb_pull(skb, skb_network_offset(skb)); | ||
| 1348 | seq = read_seqbegin(&neigh->ha_lock); | 1346 | seq = read_seqbegin(&neigh->ha_lock); |
| 1349 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), | 1347 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), |
| 1350 | neigh->ha, NULL, skb->len); | 1348 | neigh->ha, NULL, skb->len); |
