aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2005-04-24 23:16:19 -0400
committerDavid S. Miller <davem@davemloft.net>2005-04-24 23:16:19 -0400
commit0d3d077cd4f1154e63a9858e47fe3fb1ad0c03e5 (patch)
tree63f376b3586412af712ffac7d500516c98f7bb2c
parentaa77d26961fa4ecb11fe4209578dcd62ad15819d (diff)
[SELINUX]: Fix ipv6_skip_exthdr() invocation causing OOPS.
The SELinux hooks invoke ipv6_skip_exthdr() with an incorrect length final argument. However, the length argument turns out to be superfluous. I was just reading ipv6_skip_exthdr and it occured to me that we can get rid of len altogether. The only place where len is used is to check whether the skb has two bytes for ipv6_opt_hdr. This check is done by skb_header_pointer/skb_copy_bits anyway. Now it might appear that we've made the code slower by deferring the check to skb_copy_bits. However, this check should not trigger in the common case so this is OK. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ipv6.h2
-rw-r--r--net/ipv6/exthdrs_core.c11
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--security/selinux/hooks.c3
4 files changed, 8 insertions, 12 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 87c45cbfbaf6..771b47e30f86 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -416,7 +416,7 @@ extern void ipv6_push_frag_opts(struct sk_buff *skb,
416 u8 *proto); 416 u8 *proto);
417 417
418extern int ipv6_skip_exthdr(const struct sk_buff *, int start, 418extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
419 u8 *nexthdrp, int len); 419 u8 *nexthdrp);
420 420
421extern int ipv6_ext_hdr(u8 nexthdr); 421extern int ipv6_ext_hdr(u8 nexthdr);
422 422
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index 6dda815c013f..315bc1fbec3f 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -41,8 +41,8 @@ int ipv6_ext_hdr(u8 nexthdr)
41 * when Linux implements ESP (and maybe AUTH) headers. 41 * when Linux implements ESP (and maybe AUTH) headers.
42 * --AK 42 * --AK
43 * 43 *
44 * This function parses (probably truncated) exthdr set "hdr" 44 * This function parses (probably truncated) exthdr set "hdr".
45 * of length "len". "nexthdrp" initially points to some place, 45 * "nexthdrp" initially points to some place,
46 * where type of the first header can be found. 46 * where type of the first header can be found.
47 * 47 *
48 * It skips all well-known exthdrs, and returns pointer to the start 48 * It skips all well-known exthdrs, and returns pointer to the start
@@ -63,7 +63,7 @@ int ipv6_ext_hdr(u8 nexthdr)
63 * --ANK (980726) 63 * --ANK (980726)
64 */ 64 */
65 65
66int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len) 66int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp)
67{ 67{
68 u8 nexthdr = *nexthdrp; 68 u8 nexthdr = *nexthdrp;
69 69
@@ -71,13 +71,11 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len
71 struct ipv6_opt_hdr _hdr, *hp; 71 struct ipv6_opt_hdr _hdr, *hp;
72 int hdrlen; 72 int hdrlen;
73 73
74 if (len < (int)sizeof(struct ipv6_opt_hdr))
75 return -1;
76 if (nexthdr == NEXTHDR_NONE) 74 if (nexthdr == NEXTHDR_NONE)
77 return -1; 75 return -1;
78 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); 76 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
79 if (hp == NULL) 77 if (hp == NULL)
80 BUG(); 78 return -1;
81 if (nexthdr == NEXTHDR_FRAGMENT) { 79 if (nexthdr == NEXTHDR_FRAGMENT) {
82 unsigned short _frag_off, *fp; 80 unsigned short _frag_off, *fp;
83 fp = skb_header_pointer(skb, 81 fp = skb_header_pointer(skb,
@@ -97,7 +95,6 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len
97 hdrlen = ipv6_optlen(hp); 95 hdrlen = ipv6_optlen(hp);
98 96
99 nexthdr = hp->nexthdr; 97 nexthdr = hp->nexthdr;
100 len -= hdrlen;
101 start += hdrlen; 98 start += hdrlen;
102 } 99 }
103 100
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 87b9082ceab2..8e0f569b883e 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -135,7 +135,7 @@ static int is_ineligible(struct sk_buff *skb)
135 if (len < 0) 135 if (len < 0)
136 return 1; 136 return 1;
137 137
138 ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len); 138 ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr);
139 if (ptr < 0) 139 if (ptr < 0)
140 return 0; 140 return 0;
141 if (nexthdr == IPPROTO_ICMPV6) { 141 if (nexthdr == IPPROTO_ICMPV6) {
@@ -514,7 +514,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
514 nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; 514 nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
515 if (ipv6_ext_hdr(nexthdr)) { 515 if (ipv6_ext_hdr(nexthdr)) {
516 /* now skip over extension headers */ 516 /* now skip over extension headers */
517 inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, skb->len - sizeof(struct ipv6hdr)); 517 inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr);
518 if (inner_offset<0) 518 if (inner_offset<0)
519 return; 519 return;
520 } else { 520 } else {
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 2ae7d3cb8df4..0d378141c95a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2855,8 +2855,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
2855 2855
2856 nexthdr = ip6->nexthdr; 2856 nexthdr = ip6->nexthdr;
2857 offset += sizeof(_ipv6h); 2857 offset += sizeof(_ipv6h);
2858 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, 2858 offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
2859 skb->tail - skb->head - offset);
2860 if (offset < 0) 2859 if (offset < 0)
2861 goto out; 2860 goto out;
2862 2861