aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2015-04-02 03:58:24 -0400
committerSteffen Klassert <steffen.klassert@secunet.com>2015-04-07 01:52:27 -0400
commit68c11e98ef6748ddb63865799b12fc45abb3755d (patch)
tree0e50342a5653383d927364a0158f650e83d77bd0 /net/xfrm
parentf22e6e847115abc3a0e2ad7bb18d243d42275af1 (diff)
xfrm: fix xfrm_input/xfrm_tunnel_check oops
https://bugzilla.kernel.org/show_bug.cgi?id=95211 Commit 70be6c91c86596ad2b60c73587880b47df170a41 ("xfrm: Add xfrm_tunnel_skb_cb to the skb common buffer") added check which dereferences ->outer_mode too early but larval SAs don't have this pointer set (yet). So check for tunnel stuff later. Mike Noordermeer reported this bug and patiently applied all the debugging. Technically this is remote-oops-in-interrupt-context type of thing. BUG: unable to handle kernel NULL pointer dereference at 0000000000000034 IP: [<ffffffff8150dca2>] xfrm_input+0x3c2/0x5a0 ... [<ffffffff81500fc6>] ? xfrm4_esp_rcv+0x36/0x70 [<ffffffff814acc9a>] ? ip_local_deliver_finish+0x9a/0x200 [<ffffffff81471b83>] ? __netif_receive_skb_core+0x6f3/0x8f0 ... RIP [<ffffffff8150dca2>] xfrm_input+0x3c2/0x5a0 Kernel panic - not syncing: Fatal exception in interrupt Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_input.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 85d1d4764612..526c4feb3b50 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -238,11 +238,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
238 238
239 skb->sp->xvec[skb->sp->len++] = x; 239 skb->sp->xvec[skb->sp->len++] = x;
240 240
241 if (xfrm_tunnel_check(skb, x, family)) {
242 XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR);
243 goto drop;
244 }
245
246 spin_lock(&x->lock); 241 spin_lock(&x->lock);
247 if (unlikely(x->km.state == XFRM_STATE_ACQ)) { 242 if (unlikely(x->km.state == XFRM_STATE_ACQ)) {
248 XFRM_INC_STATS(net, LINUX_MIB_XFRMACQUIREERROR); 243 XFRM_INC_STATS(net, LINUX_MIB_XFRMACQUIREERROR);
@@ -271,6 +266,11 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
271 266
272 spin_unlock(&x->lock); 267 spin_unlock(&x->lock);
273 268
269 if (xfrm_tunnel_check(skb, x, family)) {
270 XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR);
271 goto drop;
272 }
273
274 seq_hi = htonl(xfrm_replay_seqhi(x, seq)); 274 seq_hi = htonl(xfrm_replay_seqhi(x, seq));
275 275
276 XFRM_SKB_CB(skb)->seq.input.low = seq; 276 XFRM_SKB_CB(skb)->seq.input.low = seq;