diff options
author | David S. Miller <davem@davemloft.net> | 2012-07-04 19:13:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-04 19:13:17 -0400 |
commit | 11604721a3c4bea60e2ddd9e4e30d741ecdba7b0 (patch) | |
tree | cfc0f846bdfc9e146398133f6beec39b6e255b4c /net/ipv4/ip_options.c | |
parent | e87183c2b5ab1f55ebad2f260a7eb4d31549ce25 (diff) |
ipv4: Fix crashes in ip_options_compile().
The spec_dst uses should be guarded by skb_rtable() being non-NULL
not just the SKB being non-null.
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ip_options.c')
-rw-r--r-- | net/ipv4/ip_options.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 766dfe56885a..1f022510abe3 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
@@ -253,12 +253,15 @@ int ip_options_compile(struct net *net, | |||
253 | { | 253 | { |
254 | __be32 spec_dst = (__force __be32) 0; | 254 | __be32 spec_dst = (__force __be32) 0; |
255 | unsigned char *pp_ptr = NULL; | 255 | unsigned char *pp_ptr = NULL; |
256 | struct rtable *rt = NULL; | ||
256 | unsigned char *optptr; | 257 | unsigned char *optptr; |
257 | unsigned char *iph; | 258 | unsigned char *iph; |
258 | int optlen, l; | 259 | int optlen, l; |
259 | 260 | ||
260 | if (skb != NULL) { | 261 | if (skb != NULL) { |
261 | spec_dst = fib_compute_spec_dst(skb); | 262 | rt = skb_rtable(skb); |
263 | if (rt) | ||
264 | spec_dst = fib_compute_spec_dst(skb); | ||
262 | optptr = (unsigned char *)&(ip_hdr(skb)[1]); | 265 | optptr = (unsigned char *)&(ip_hdr(skb)[1]); |
263 | } else | 266 | } else |
264 | optptr = opt->__data; | 267 | optptr = opt->__data; |
@@ -330,7 +333,7 @@ int ip_options_compile(struct net *net, | |||
330 | pp_ptr = optptr + 2; | 333 | pp_ptr = optptr + 2; |
331 | goto error; | 334 | goto error; |
332 | } | 335 | } |
333 | if (skb) { | 336 | if (rt) { |
334 | memcpy(&optptr[optptr[2]-1], &spec_dst, 4); | 337 | memcpy(&optptr[optptr[2]-1], &spec_dst, 4); |
335 | opt->is_changed = 1; | 338 | opt->is_changed = 1; |
336 | } | 339 | } |
@@ -372,7 +375,7 @@ int ip_options_compile(struct net *net, | |||
372 | goto error; | 375 | goto error; |
373 | } | 376 | } |
374 | opt->ts = optptr - iph; | 377 | opt->ts = optptr - iph; |
375 | if (skb) { | 378 | if (rt) { |
376 | memcpy(&optptr[optptr[2]-1], &spec_dst, 4); | 379 | memcpy(&optptr[optptr[2]-1], &spec_dst, 4); |
377 | timeptr = &optptr[optptr[2]+3]; | 380 | timeptr = &optptr[optptr[2]+3]; |
378 | } | 381 | } |