git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
ipv4: fix buffer overflow in ip_options_compile()
[pandora-kernel.git]
/
net
/
ipv4
/
ip_options.c
diff --git
a/net/ipv4/ip_options.c
b/net/ipv4/ip_options.c
index
05d20cc
..
08623e2
100644
(file)
--- a/
net/ipv4/ip_options.c
+++ b/
net/ipv4/ip_options.c
@@
-277,6
+277,10
@@
int ip_options_compile(struct net *net,
optptr++;
continue;
}
optptr++;
continue;
}
+ if (unlikely(l < 2)) {
+ pp_ptr = optptr;
+ goto error;
+ }
optlen = optptr[1];
if (optlen<2 || optlen>l) {
pp_ptr = optptr;
optlen = optptr[1];
if (optlen<2 || optlen>l) {
pp_ptr = optptr;
@@
-358,7
+362,6
@@
int ip_options_compile(struct net *net,
}
switch (optptr[3]&0xF) {
case IPOPT_TS_TSONLY:
}
switch (optptr[3]&0xF) {
case IPOPT_TS_TSONLY:
- opt->ts = optptr - iph;
if (skb)
timeptr = &optptr[optptr[2]-1];
opt->ts_needtime = 1;
if (skb)
timeptr = &optptr[optptr[2]-1];
opt->ts_needtime = 1;
@@
-369,7
+372,6
@@
int ip_options_compile(struct net *net,
pp_ptr = optptr + 2;
goto error;
}
pp_ptr = optptr + 2;
goto error;
}
- opt->ts = optptr - iph;
if (rt) {
memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
timeptr = &optptr[optptr[2]+3];
if (rt) {
memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
timeptr = &optptr[optptr[2]+3];
@@
-383,7
+385,6
@@
int ip_options_compile(struct net *net,
pp_ptr = optptr + 2;
goto error;
}
pp_ptr = optptr + 2;
goto error;
}
- opt->ts = optptr - iph;
{
__be32 addr;
memcpy(&addr, &optptr[optptr[2]-1], 4);
{
__be32 addr;
memcpy(&addr, &optptr[optptr[2]-1], 4);
@@
-416,12
+417,12
@@
int ip_options_compile(struct net *net,
pp_ptr = optptr + 3;
goto error;
}
pp_ptr = optptr + 3;
goto error;
}
- opt->ts = optptr - iph;
if (skb) {
optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
opt->is_changed = 1;
}
}
if (skb) {
optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
opt->is_changed = 1;
}
}
+ opt->ts = optptr - iph;
break;
case IPOPT_RA:
if (optlen < 4) {
break;
case IPOPT_RA:
if (optlen < 4) {
@@
-568,11
+569,12
@@
void ip_forward_options(struct sk_buff *skb)
) {
if (srrptr + 3 > srrspace)
break;
) {
if (srrptr + 3 > srrspace)
break;
- if (memcmp(&
ip_hdr(skb)->daddr
, &optptr[srrptr-1], 4) == 0)
+ if (memcmp(&
opt->nexthop
, &optptr[srrptr-1], 4) == 0)
break;
}
if (srrptr + 3 <= srrspace) {
opt->is_changed = 1;
break;
}
if (srrptr + 3 <= srrspace) {
opt->is_changed = 1;
+ ip_hdr(skb)->daddr = opt->nexthop;
ip_rt_get_source(&optptr[srrptr-1], skb, rt);
optptr[2] = srrptr+4;
} else if (net_ratelimit())
ip_rt_get_source(&optptr[srrptr-1], skb, rt);
optptr[2] = srrptr+4;
} else if (net_ratelimit())
@@
-640,7
+642,7
@@
int ip_options_rcv_srr(struct sk_buff *skb)
}
if (srrptr <= srrspace) {
opt->srr_is_hit = 1;
}
if (srrptr <= srrspace) {
opt->srr_is_hit = 1;
-
iph->daddr
= nexthop;
+
opt->nexthop
= nexthop;
opt->is_changed = 1;
}
return 0;
opt->is_changed = 1;
}
return 0;