aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2011-11-30 20:05:51 -0500
committerJesse Gross <jesse@nicira.com>2011-12-03 12:35:10 -0500
commit75f2811c6460ccc59d83c66059943ce9c9f81a18 (patch)
tree49373cf5f5b11358aeb587209ad270496f751609
parent396cf9430505cfba529a2f2a037d782719fa5844 (diff)
ipv6: Add fragment reporting to ipv6_skip_exthdr().
While parsing through IPv6 extension headers, fragment headers are skipped making them invisible to the caller. This reports the fragment offset of the last header in order to make it possible to determine whether the packet is fragmented and, if so whether it is a first or last fragment. Signed-off-by: Jesse Gross <jesse@nicira.com>
-rw-r--r--include/net/ipv6.h2
-rw-r--r--net/bridge/br_multicast.c3
-rw-r--r--net/bridge/netfilter/ebt_ip6.c3
-rw-r--r--net/bridge/netfilter/ebt_log.c3
-rw-r--r--net/ipv6/exthdrs_core.c11
-rw-r--r--net/ipv6/icmp.c7
-rw-r--r--net/ipv6/ip6_input.c3
-rw-r--r--net/ipv6/ip6_output.c3
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c3
-rw-r--r--net/netfilter/ipset/ip_set_getport.c4
-rw-r--r--net/netfilter/xt_AUDIT.c3
-rw-r--r--net/netfilter/xt_TCPMSS.c3
-rw-r--r--net/netfilter/xt_TCPOPTSTRIP.c3
-rw-r--r--net/netfilter/xt_hashlimit.c3
-rw-r--r--net/netfilter/xt_socket.c4
-rw-r--r--security/lsm_audit.c3
-rw-r--r--security/selinux/hooks.c3
17 files changed, 45 insertions, 19 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index f35188e002d9..e4170a22fc6f 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -558,7 +558,7 @@ extern void ipv6_push_frag_opts(struct sk_buff *skb,
558 u8 *proto); 558 u8 *proto);
559 559
560extern int ipv6_skip_exthdr(const struct sk_buff *, int start, 560extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
561 u8 *nexthdrp); 561 u8 *nexthdrp, __be16 *frag_offp);
562 562
563extern int ipv6_ext_hdr(u8 nexthdr); 563extern int ipv6_ext_hdr(u8 nexthdr);
564 564
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 7743e0d109ea..375417e633c9 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1458,6 +1458,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1458 const struct ipv6hdr *ip6h; 1458 const struct ipv6hdr *ip6h;
1459 u8 icmp6_type; 1459 u8 icmp6_type;
1460 u8 nexthdr; 1460 u8 nexthdr;
1461 __be16 frag_off;
1461 unsigned len; 1462 unsigned len;
1462 int offset; 1463 int offset;
1463 int err; 1464 int err;
@@ -1483,7 +1484,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1483 return -EINVAL; 1484 return -EINVAL;
1484 1485
1485 nexthdr = ip6h->nexthdr; 1486 nexthdr = ip6h->nexthdr;
1486 offset = ipv6_skip_exthdr(skb, sizeof(*ip6h), &nexthdr); 1487 offset = ipv6_skip_exthdr(skb, sizeof(*ip6h), &nexthdr, &frag_off);
1487 1488
1488 if (offset < 0 || nexthdr != IPPROTO_ICMPV6) 1489 if (offset < 0 || nexthdr != IPPROTO_ICMPV6)
1489 return 0; 1490 return 0;
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c
index 2ed0056a39a8..99c85668f551 100644
--- a/net/bridge/netfilter/ebt_ip6.c
+++ b/net/bridge/netfilter/ebt_ip6.c
@@ -55,9 +55,10 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par)
55 return false; 55 return false;
56 if (info->bitmask & EBT_IP6_PROTO) { 56 if (info->bitmask & EBT_IP6_PROTO) {
57 uint8_t nexthdr = ih6->nexthdr; 57 uint8_t nexthdr = ih6->nexthdr;
58 __be16 frag_off;
58 int offset_ph; 59 int offset_ph;
59 60
60 offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr); 61 offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr, &frag_off);
61 if (offset_ph == -1) 62 if (offset_ph == -1)
62 return false; 63 return false;
63 if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) 64 if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO))
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 6e5a8bb9b940..88d7d1d1cb1b 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -113,6 +113,7 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
113 const struct ipv6hdr *ih; 113 const struct ipv6hdr *ih;
114 struct ipv6hdr _iph; 114 struct ipv6hdr _iph;
115 uint8_t nexthdr; 115 uint8_t nexthdr;
116 __be16 frag_off;
116 int offset_ph; 117 int offset_ph;
117 118
118 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); 119 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
@@ -123,7 +124,7 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
123 printk(" IPv6 SRC=%pI6 IPv6 DST=%pI6, IPv6 priority=0x%01X, Next Header=%d", 124 printk(" IPv6 SRC=%pI6 IPv6 DST=%pI6, IPv6 priority=0x%01X, Next Header=%d",
124 &ih->saddr, &ih->daddr, ih->priority, ih->nexthdr); 125 &ih->saddr, &ih->daddr, ih->priority, ih->nexthdr);
125 nexthdr = ih->nexthdr; 126 nexthdr = ih->nexthdr;
126 offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr); 127 offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr, &frag_off);
127 if (offset_ph == -1) 128 if (offset_ph == -1)
128 goto out; 129 goto out;
129 print_ports(skb, nexthdr, offset_ph); 130 print_ports(skb, nexthdr, offset_ph);
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index 37f548b7f6dc..72957f4a7c6c 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -57,6 +57,9 @@ int ipv6_ext_hdr(u8 nexthdr)
57 * it returns NULL. 57 * it returns NULL.
58 * - First fragment header is skipped, not-first ones 58 * - First fragment header is skipped, not-first ones
59 * are considered as unparsable. 59 * are considered as unparsable.
60 * - Reports the offset field of the final fragment header so it is
61 * possible to tell whether this is a first fragment, later fragment,
62 * or not fragmented.
60 * - ESP is unparsable for now and considered like 63 * - ESP is unparsable for now and considered like
61 * normal payload protocol. 64 * normal payload protocol.
62 * - Note also special handling of AUTH header. Thanks to IPsec wizards. 65 * - Note also special handling of AUTH header. Thanks to IPsec wizards.
@@ -64,10 +67,13 @@ int ipv6_ext_hdr(u8 nexthdr)
64 * --ANK (980726) 67 * --ANK (980726)
65 */ 68 */
66 69
67int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp) 70int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
71 __be16 *frag_offp)
68{ 72{
69 u8 nexthdr = *nexthdrp; 73 u8 nexthdr = *nexthdrp;
70 74
75 *frag_offp = 0;
76
71 while (ipv6_ext_hdr(nexthdr)) { 77 while (ipv6_ext_hdr(nexthdr)) {
72 struct ipv6_opt_hdr _hdr, *hp; 78 struct ipv6_opt_hdr _hdr, *hp;
73 int hdrlen; 79 int hdrlen;
@@ -87,7 +93,8 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp)
87 if (fp == NULL) 93 if (fp == NULL)
88 return -1; 94 return -1;
89 95
90 if (ntohs(*fp) & ~0x7) 96 *frag_offp = *fp;
97 if (ntohs(*frag_offp) & ~0x7)
91 break; 98 break;
92 hdrlen = 8; 99 hdrlen = 8;
93 } else if (nexthdr == NEXTHDR_AUTH) 100 } else if (nexthdr == NEXTHDR_AUTH)
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 9e2bdccf9143..01d46bff63c3 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -135,11 +135,12 @@ static int is_ineligible(struct sk_buff *skb)
135 int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; 135 int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data;
136 int len = skb->len - ptr; 136 int len = skb->len - ptr;
137 __u8 nexthdr = ipv6_hdr(skb)->nexthdr; 137 __u8 nexthdr = ipv6_hdr(skb)->nexthdr;
138 __be16 frag_off;
138 139
139 if (len < 0) 140 if (len < 0)
140 return 1; 141 return 1;
141 142
142 ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr); 143 ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, &frag_off);
143 if (ptr < 0) 144 if (ptr < 0)
144 return 0; 145 return 0;
145 if (nexthdr == IPPROTO_ICMPV6) { 146 if (nexthdr == IPPROTO_ICMPV6) {
@@ -596,6 +597,7 @@ static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
596 int inner_offset; 597 int inner_offset;
597 int hash; 598 int hash;
598 u8 nexthdr; 599 u8 nexthdr;
600 __be16 frag_off;
599 601
600 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 602 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
601 return; 603 return;
@@ -603,7 +605,8 @@ static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
603 nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; 605 nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
604 if (ipv6_ext_hdr(nexthdr)) { 606 if (ipv6_ext_hdr(nexthdr)) {
605 /* now skip over extension headers */ 607 /* now skip over extension headers */
606 inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr); 608 inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
609 &nexthdr, &frag_off);
607 if (inner_offset<0) 610 if (inner_offset<0)
608 return; 611 return;
609 } else { 612 } else {
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index a46c64eb0a66..1ca5d45a12e8 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -280,6 +280,7 @@ int ip6_mc_input(struct sk_buff *skb)
280 u8 *ptr = skb_network_header(skb) + opt->ra; 280 u8 *ptr = skb_network_header(skb) + opt->ra;
281 struct icmp6hdr *icmp6; 281 struct icmp6hdr *icmp6;
282 u8 nexthdr = hdr->nexthdr; 282 u8 nexthdr = hdr->nexthdr;
283 __be16 frag_off;
283 int offset; 284 int offset;
284 285
285 /* Check if the value of Router Alert 286 /* Check if the value of Router Alert
@@ -293,7 +294,7 @@ int ip6_mc_input(struct sk_buff *skb)
293 goto out; 294 goto out;
294 } 295 }
295 offset = ipv6_skip_exthdr(skb, sizeof(*hdr), 296 offset = ipv6_skip_exthdr(skb, sizeof(*hdr),
296 &nexthdr); 297 &nexthdr, &frag_off);
297 if (offset < 0) 298 if (offset < 0)
298 goto out; 299 goto out;
299 300
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index a24e15557843..3221bc675654 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -329,10 +329,11 @@ static int ip6_forward_proxy_check(struct sk_buff *skb)
329{ 329{
330 struct ipv6hdr *hdr = ipv6_hdr(skb); 330 struct ipv6hdr *hdr = ipv6_hdr(skb);
331 u8 nexthdr = hdr->nexthdr; 331 u8 nexthdr = hdr->nexthdr;
332 __be16 frag_off;
332 int offset; 333 int offset;
333 334
334 if (ipv6_ext_hdr(nexthdr)) { 335 if (ipv6_ext_hdr(nexthdr)) {
335 offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr); 336 offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr, &frag_off);
336 if (offset < 0) 337 if (offset < 0)
337 return 0; 338 return 0;
338 } else 339 } else
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index b5a2aa58a03a..aad2fa41cf46 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -49,6 +49,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
49 const __u8 tclass = DEFAULT_TOS_VALUE; 49 const __u8 tclass = DEFAULT_TOS_VALUE;
50 struct dst_entry *dst = NULL; 50 struct dst_entry *dst = NULL;
51 u8 proto; 51 u8 proto;
52 __be16 frag_off;
52 struct flowi6 fl6; 53 struct flowi6 fl6;
53 54
54 if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || 55 if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
@@ -58,7 +59,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
58 } 59 }
59 60
60 proto = oip6h->nexthdr; 61 proto = oip6h->nexthdr;
61 tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); 62 tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off);
62 63
63 if ((tcphoff < 0) || (tcphoff > oldskb->len)) { 64 if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
64 pr_debug("Cannot get TCP header.\n"); 65 pr_debug("Cannot get TCP header.\n");
diff --git a/net/netfilter/ipset/ip_set_getport.c b/net/netfilter/ipset/ip_set_getport.c
index 052579fe389a..b71a6e7ab0a5 100644
--- a/net/netfilter/ipset/ip_set_getport.c
+++ b/net/netfilter/ipset/ip_set_getport.c
@@ -116,9 +116,11 @@ ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
116{ 116{
117 int protoff; 117 int protoff;
118 u8 nexthdr; 118 u8 nexthdr;
119 __be16 frag_off;
119 120
120 nexthdr = ipv6_hdr(skb)->nexthdr; 121 nexthdr = ipv6_hdr(skb)->nexthdr;
121 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr); 122 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
123 &frag_off);
122 if (protoff < 0) 124 if (protoff < 0)
123 return false; 125 return false;
124 126
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index 4bca15a0c385..ba92824086f3 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -98,6 +98,7 @@ static void audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
98 struct ipv6hdr _ip6h; 98 struct ipv6hdr _ip6h;
99 const struct ipv6hdr *ih; 99 const struct ipv6hdr *ih;
100 u8 nexthdr; 100 u8 nexthdr;
101 __be16 frag_off;
101 int offset; 102 int offset;
102 103
103 ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h); 104 ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h);
@@ -108,7 +109,7 @@ static void audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
108 109
109 nexthdr = ih->nexthdr; 110 nexthdr = ih->nexthdr;
110 offset = ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h), 111 offset = ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h),
111 &nexthdr); 112 &nexthdr, &frag_off);
112 113
113 audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu", 114 audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu",
114 &ih->saddr, &ih->daddr, nexthdr); 115 &ih->saddr, &ih->daddr, nexthdr);
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 3ecade3966d5..ba722621ed25 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -204,11 +204,12 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par)
204{ 204{
205 struct ipv6hdr *ipv6h = ipv6_hdr(skb); 205 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
206 u8 nexthdr; 206 u8 nexthdr;
207 __be16 frag_off;
207 int tcphoff; 208 int tcphoff;
208 int ret; 209 int ret;
209 210
210 nexthdr = ipv6h->nexthdr; 211 nexthdr = ipv6h->nexthdr;
211 tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); 212 tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off);
212 if (tcphoff < 0) 213 if (tcphoff < 0)
213 return NF_DROP; 214 return NF_DROP;
214 ret = tcpmss_mangle_packet(skb, par->targinfo, 215 ret = tcpmss_mangle_packet(skb, par->targinfo,
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c
index 9dc9ecfdd546..3a295cc734bd 100644
--- a/net/netfilter/xt_TCPOPTSTRIP.c
+++ b/net/netfilter/xt_TCPOPTSTRIP.c
@@ -87,9 +87,10 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par)
87 struct ipv6hdr *ipv6h = ipv6_hdr(skb); 87 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
88 int tcphoff; 88 int tcphoff;
89 u_int8_t nexthdr; 89 u_int8_t nexthdr;
90 __be16 frag_off;
90 91
91 nexthdr = ipv6h->nexthdr; 92 nexthdr = ipv6h->nexthdr;
92 tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); 93 tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off);
93 if (tcphoff < 0) 94 if (tcphoff < 0)
94 return NF_DROP; 95 return NF_DROP;
95 96
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index dfd52bad1523..068698f64791 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -445,6 +445,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
445{ 445{
446 __be16 _ports[2], *ports; 446 __be16 _ports[2], *ports;
447 u8 nexthdr; 447 u8 nexthdr;
448 __be16 frag_off;
448 int poff; 449 int poff;
449 450
450 memset(dst, 0, sizeof(*dst)); 451 memset(dst, 0, sizeof(*dst));
@@ -480,7 +481,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
480 (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT))) 481 (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT)))
481 return 0; 482 return 0;
482 nexthdr = ipv6_hdr(skb)->nexthdr; 483 nexthdr = ipv6_hdr(skb)->nexthdr;
483 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr); 484 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, &frag_off);
484 if ((int)protoff < 0) 485 if ((int)protoff < 0)
485 return -1; 486 return -1;
486 break; 487 break;
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index fe39f7e913df..c302e30dc50c 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -214,6 +214,7 @@ extract_icmp6_fields(const struct sk_buff *skb,
214 struct icmp6hdr *icmph, _icmph; 214 struct icmp6hdr *icmph, _icmph;
215 __be16 *ports, _ports[2]; 215 __be16 *ports, _ports[2];
216 u8 inside_nexthdr; 216 u8 inside_nexthdr;
217 __be16 inside_fragoff;
217 int inside_hdrlen; 218 int inside_hdrlen;
218 219
219 icmph = skb_header_pointer(skb, outside_hdrlen, 220 icmph = skb_header_pointer(skb, outside_hdrlen,
@@ -229,7 +230,8 @@ extract_icmp6_fields(const struct sk_buff *skb,
229 return 1; 230 return 1;
230 inside_nexthdr = inside_iph->nexthdr; 231 inside_nexthdr = inside_iph->nexthdr;
231 232
232 inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph), &inside_nexthdr); 233 inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph),
234 &inside_nexthdr, &inside_fragoff);
233 if (inside_hdrlen < 0) 235 if (inside_hdrlen < 0)
234 return 1; /* hjm: Packet has no/incomplete transport layer headers. */ 236 return 1; /* hjm: Packet has no/incomplete transport layer headers. */
235 237
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 199616bb68d3..7bd6f138236b 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -114,6 +114,7 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
114 int offset, ret = 0; 114 int offset, ret = 0;
115 struct ipv6hdr *ip6; 115 struct ipv6hdr *ip6;
116 u8 nexthdr; 116 u8 nexthdr;
117 __be16 frag_off;
117 118
118 ip6 = ipv6_hdr(skb); 119 ip6 = ipv6_hdr(skb);
119 if (ip6 == NULL) 120 if (ip6 == NULL)
@@ -126,7 +127,7 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
126 offset = skb_network_offset(skb); 127 offset = skb_network_offset(skb);
127 offset += sizeof(*ip6); 128 offset += sizeof(*ip6);
128 nexthdr = ip6->nexthdr; 129 nexthdr = ip6->nexthdr;
129 offset = ipv6_skip_exthdr(skb, offset, &nexthdr); 130 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
130 if (offset < 0) 131 if (offset < 0)
131 return 0; 132 return 0;
132 if (proto) 133 if (proto)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7e6c2564e741..cca09bb46502 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3561,6 +3561,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
3561 u8 nexthdr; 3561 u8 nexthdr;
3562 int ret = -EINVAL, offset; 3562 int ret = -EINVAL, offset;
3563 struct ipv6hdr _ipv6h, *ip6; 3563 struct ipv6hdr _ipv6h, *ip6;
3564 __be16 frag_off;
3564 3565
3565 offset = skb_network_offset(skb); 3566 offset = skb_network_offset(skb);
3566 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h); 3567 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
@@ -3573,7 +3574,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
3573 3574
3574 nexthdr = ip6->nexthdr; 3575 nexthdr = ip6->nexthdr;
3575 offset += sizeof(_ipv6h); 3576 offset += sizeof(_ipv6h);
3576 offset = ipv6_skip_exthdr(skb, offset, &nexthdr); 3577 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
3577 if (offset < 0) 3578 if (offset < 0)
3578 goto out; 3579 goto out;
3579 3580