[SELINUX]: Fix ipv6_skip_exthdr() invocation causing OOPS.
authorHerbert Xu <herbert@gondor.apana.org.au>
Mon, 25 Apr 2005 03:16:19 +0000 (20:16 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 25 Apr 2005 03:16:19 +0000 (20:16 -0700)
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>
include/net/ipv6.h
net/ipv6/exthdrs_core.c
net/ipv6/icmp.c
security/selinux/hooks.c

index 87c45cbfbaf64ad7fd35f8b1c3890f3696099e80..771b47e30f86eed68fb3c9d221847704b81572a7 100644 (file)
@@ -416,7 +416,7 @@ extern void                 ipv6_push_frag_opts(struct sk_buff *skb,
                                                    u8 *proto);
 
 extern int                     ipv6_skip_exthdr(const struct sk_buff *, int start,
-                                                u8 *nexthdrp, int len);
+                                                u8 *nexthdrp);
 
 extern int                     ipv6_ext_hdr(u8 nexthdr);
 
index 6dda815c013f8791ad0b5a467b2161f782786b2a..315bc1fbec3f35a6f82c1fd653b8f7cb7f716846 100644 (file)
@@ -41,8 +41,8 @@ int ipv6_ext_hdr(u8 nexthdr)
  * when Linux implements ESP (and maybe AUTH) headers.
  * --AK
  *
- * This function parses (probably truncated) exthdr set "hdr"
- * of length "len". "nexthdrp" initially points to some place,
+ * This function parses (probably truncated) exthdr set "hdr".
+ * "nexthdrp" initially points to some place,
  * where type of the first header can be found.
  *
  * It skips all well-known exthdrs, and returns pointer to the start
@@ -63,7 +63,7 @@ int ipv6_ext_hdr(u8 nexthdr)
  * --ANK (980726)
  */
 
-int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len)
+int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp)
 {
        u8 nexthdr = *nexthdrp;
 
@@ -71,13 +71,11 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len
                struct ipv6_opt_hdr _hdr, *hp;
                int hdrlen;
 
-               if (len < (int)sizeof(struct ipv6_opt_hdr))
-                       return -1;
                if (nexthdr == NEXTHDR_NONE)
                        return -1;
                hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
                if (hp == NULL)
-                       BUG();
+                       return -1;
                if (nexthdr == NEXTHDR_FRAGMENT) {
                        unsigned short _frag_off, *fp;
                        fp = skb_header_pointer(skb,
@@ -97,7 +95,6 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len
                        hdrlen = ipv6_optlen(hp); 
 
                nexthdr = hp->nexthdr;
-               len -= hdrlen;
                start += hdrlen;
        }
 
index 87b9082ceab27367e6415e41b26f0c0417cfaa61..8e0f569b883e419acd311e79670d9ea916f0a034 100644 (file)
@@ -135,7 +135,7 @@ static int is_ineligible(struct sk_buff *skb)
        if (len < 0)
                return 1;
 
-       ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len);
+       ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr);
        if (ptr < 0)
                return 0;
        if (nexthdr == IPPROTO_ICMPV6) {
@@ -514,7 +514,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
        nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
        if (ipv6_ext_hdr(nexthdr)) {
                /* now skip over extension headers */
-               inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, skb->len - sizeof(struct ipv6hdr));
+               inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr);
                if (inner_offset<0)
                        return;
        } else {
index 2ae7d3cb8df4b0b02b1d3c217c465dbacc6c4bb4..0d378141c95acea1d3471aafc1c9ceda135da8de 100644 (file)
@@ -2855,8 +2855,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
 
        nexthdr = ip6->nexthdr;
        offset += sizeof(_ipv6h);
-       offset = ipv6_skip_exthdr(skb, offset, &nexthdr,
-                                 skb->tail - skb->head - offset);
+       offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
        if (offset < 0)
                goto out;