@@ -263,8 +263,6 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
u8 **nexthdr)
{
u16 offset = sizeof(struct ipv6hdr);
- struct ipv6_opt_hdr *exthdr =
- (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
const unsigned char *nh = skb_network_header(skb);
unsigned int packet_len = skb_tail_pointer(skb) -
skb_network_header(skb);
@@ -272,7 +270,8 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
*nexthdr = &ipv6_hdr(skb)->nexthdr;
- while (offset + 1 <= packet_len) {
+ while (offset <= packet_len) {
+ struct ipv6_opt_hdr *exthdr;
switch (**nexthdr) {
case NEXTHDR_HOP:
@@ -299,12 +298,16 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
return offset;
}
+ if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
+ return -EINVAL;
+
+ exthdr = (struct ipv6_opt_hdr *)(nh + offset);
offset += ipv6_optlen(exthdr);
*nexthdr = &exthdr->nexthdr;
- exthdr = (struct ipv6_opt_hdr *)(nh + offset);
+
}
- return offset;
+ return -EINVAL;
}
static int mip6_destopt_init_state(struct xfrm_state *x)
@@ -399,8 +402,6 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
u8 **nexthdr)
{
u16 offset = sizeof(struct ipv6hdr);
- struct ipv6_opt_hdr *exthdr =
- (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
const unsigned char *nh = skb_network_header(skb);
unsigned int packet_len = skb_tail_pointer(skb) -
skb_network_header(skb);
@@ -408,7 +409,8 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
*nexthdr = &ipv6_hdr(skb)->nexthdr;
- while (offset + 1 <= packet_len) {
+ while (offset <= packet_len) {
+ struct ipv6_opt_hdr *exthdr;
switch (**nexthdr) {
case NEXTHDR_HOP:
@@ -434,12 +436,16 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
return offset;
}
+ if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
+ return -EINVAL;
+
+ exthdr = (struct ipv6_opt_hdr *)(nh + offset);
+
offset += ipv6_optlen(exthdr);
*nexthdr = &exthdr->nexthdr;
- exthdr = (struct ipv6_opt_hdr *)(nh + offset);
}
- return offset;
+ return -EINVAL;
}
static int mip6_rthdr_init_state(struct xfrm_state *x)