Commit 9d7b0fc1ef1f17aff57c0dc9a59453d8fca255c3
Committed by
David S. Miller
1 parent
ae4d8cf299
net: ipv6: fix oops in inet_putpeer()
Commit 97bab73f (inet: Hide route peer accesses behind helpers.) introduced a bug in xfrm6_policy_destroy(). The xfrm_dst's _rt6i_peer member is not initialized, causing a false positive result from inetpeer_ptr_is_peer(), which in turn causes a NULL pointer dereference in inet_putpeer(). Pid: 314, comm: kworker/0:1 Not tainted 3.6.0-rc1+ #17 To Be Filled By O.E.M. To Be Filled By O.E.M./P4S800D-X EIP: 0060:[<c03abf93>] EFLAGS: 00010246 CPU: 0 EIP is at inet_putpeer+0xe/0x16 EAX: 00000000 EBX: f3481700 ECX: 00000000 EDX: 000dd641 ESI: f3481700 EDI: c05e949c EBP: f551def4 ESP: f551def4 DS: 007b ES: 007b FS: 0000 GS: 00e0 SS: 0068 CR0: 8005003b CR2: 00000070 CR3: 3243d000 CR4: 00000750 DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff0ff0 DR7: 00000400 f551df04 c0423de1 00000000 f3481700 f551df18 c038d5f7 f254b9f8 f551df28 f34f85d8 f551df20 c03ef48d f551df3c c0396870 f30697e8 f24e1738 c05e98f4 f5509540 c05cd2b4 f551df7c c0142d2b c043feb5 f5509540 00000000 c05cd2e8 [<c0423de1>] xfrm6_dst_destroy+0x42/0xdb [<c038d5f7>] dst_destroy+0x1d/0xa4 [<c03ef48d>] xfrm_bundle_flo_delete+0x2b/0x36 [<c0396870>] flow_cache_gc_task+0x85/0x9f [<c0142d2b>] process_one_work+0x122/0x441 [<c043feb5>] ? apic_timer_interrupt+0x31/0x38 [<c03967eb>] ? flow_cache_new_hashrnd+0x2b/0x2b [<c0143e2d>] worker_thread+0x113/0x3cc Fix by adding a init_dst() callback to struct xfrm_policy_afinfo to properly initialize the dst's peer pointer. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 3 changed files with 12 additions and 0 deletions Side-by-side Diff
include/net/xfrm.h
net/ipv6/xfrm6_policy.c
... | ... | @@ -73,6 +73,13 @@ |
73 | 73 | return 0; |
74 | 74 | } |
75 | 75 | |
76 | +static void xfrm6_init_dst(struct net *net, struct xfrm_dst *xdst) | |
77 | +{ | |
78 | + struct rt6_info *rt = (struct rt6_info *)xdst; | |
79 | + | |
80 | + rt6_init_peer(rt, net->ipv6.peers); | |
81 | +} | |
82 | + | |
76 | 83 | static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, |
77 | 84 | int nfheader_len) |
78 | 85 | { |
... | ... | @@ -286,6 +293,7 @@ |
286 | 293 | .get_saddr = xfrm6_get_saddr, |
287 | 294 | .decode_session = _decode_session6, |
288 | 295 | .get_tos = xfrm6_get_tos, |
296 | + .init_dst = xfrm6_init_dst, | |
289 | 297 | .init_path = xfrm6_init_path, |
290 | 298 | .fill_dst = xfrm6_fill_dst, |
291 | 299 | .blackhole_route = ip6_blackhole_route, |
net/xfrm/xfrm_policy.c