ChangeSet 1.1539, 2004/12/21 17:35:47+01:00, [EMAIL PROTECTED]

        [NETFILTER]: Backport fixes for ip6t_dst
        
        This patch fixes the following bugs in ip6t_dst.c:
        
          - The cast of the pointer to the next IPv6 extension header is wrong.
          - hdrlen may underflow.
          - (u16)*optdesc causes to alignment problem.
          - The calculation of the offset to next option is wrong. In the case
            that the type isn't 0, it should be Opt Data Len field + 2
            (see RFC2460).
        
        Signed-off-by: Yasuyuki KOZAKAI <[EMAIL PROTECTED]>
        Signed-off-by: Patrick McHardy <[EMAIL PROTECTED]>



 ip6t_dst.c |   74 +++++++++++++++++++++++++++++++------------------------------
 1 files changed, 38 insertions(+), 36 deletions(-)


diff -Nru a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
--- a/net/ipv6/netfilter/ip6t_dst.c     2005-01-15 07:04:24 -08:00
+++ b/net/ipv6/netfilter/ip6t_dst.c     2005-01-15 07:04:24 -08:00
@@ -11,8 +11,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_opts.h>
 
-#define LOW(n)         (n & 0x00FF)
-
 #define HOPBYHOP       0
 
 EXPORT_NO_SYMBOLS;
@@ -40,8 +38,8 @@
  *     0       -> invariant
  *     1       -> can change the routing
  *  (Type & 0x1F) Type
- *      0      -> PAD0 (only 1 byte!)
- *      1      -> PAD1 LENGTH info (total length = length + 2)
+ *      0      -> Pad1 (only 1 byte!)
+ *      1      -> PadN LENGTH info (total length = length + 2)
  *      C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k )
  *      5      -> RTALERT 2 x x
  */
@@ -64,7 +62,8 @@
        unsigned int ptr;
        unsigned int hdrlen = 0;
        unsigned int ret = 0;
-       u_int16_t *optdesc = NULL;
+       u8 *opttype = NULL;
+       unsigned int optlen;
        
        /* type of the 1st exthdr */
        nexthdr = skb->nh.ipv6h->nexthdr;
@@ -91,7 +90,7 @@
                      break;
               }
 
-              hdr=(void *)(skb->data)+ptr;
+             hdr = (void *)(skb->data + ptr);
 
               /* Calculate the header length */
                 if (nexthdr == NEXTHDR_FRAGMENT) {
@@ -153,7 +152,7 @@
                        return 0;
        }
 
-       optsh=(void *)(skb->data)+ptr;
+       optsh = (void *)(skb->data + ptr);
 
        DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen);
 
@@ -169,7 +168,6 @@
                            ((optinfo->hdrlen == hdrlen) ^
                            !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
 
-       temp = len = 0;
        ptr += 2;
        hdrlen -= 2;
        if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
@@ -180,48 +178,52 @@
                DEBUGP("Strict ");
                DEBUGP("#%d ",optinfo->optsnr);
                for(temp=0; temp<optinfo->optsnr; temp++){
-                       optdesc = (void *)(skb->data)+ptr;
+                       /* type field exists ? */
+                       if (ptr > skb->len - 1 || hdrlen < 1)
+                               break;
+                       opttype = (void *)(skb->data + ptr);
+
                        /* Type check */
-                       if ( (unsigned char)*optdesc != 
-                               (optinfo->opts[temp] & 0xFF00)>>8 ){
+                       if (*opttype != (optinfo->opts[temp] & 0xFF00)>>8){
                                DEBUGP("Tbad %02X %02X\n",
-                                               (unsigned char)*optdesc,
-                                               (optinfo->opts[temp] &
-                                                0xFF00)>>8);
+                                      *opttype,
+                                      (optinfo->opts[temp] & 0xFF00)>>8);
                                return 0;
                        } else {
                                DEBUGP("Tok ");
                        }
                        /* Length check */
-                       if (((optinfo->opts[temp] & 0x00FF) != 0xFF) &&
-                               (unsigned char)*optdesc != 0){
-                               if ( ntohs((u16)*optdesc) != 
-                                               optinfo->opts[temp] ){
-                                       DEBUGP("Lbad %02X %04X %04X\n",
-                                                       (unsigned char)*optdesc,
-                                                       ntohs((u16)*optdesc),
-                                                       optinfo->opts[temp]);
+                       if (*opttype) {
+                               u16 spec_len;
+
+                               /* length field exists ? */
+                               if (ptr > skb->len - 2 || hdrlen < 2)
+                                       break;
+                               optlen = *((u8 *)(skb->data + ptr + 1));
+                               spec_len = optinfo->opts[temp] & 0x00FF;
+
+                               if (spec_len != 0x00FF && spec_len != optlen) {
+                                       DEBUGP("Lbad %02X %04X\n", optlen,
+                                              spec_len);
                                        return 0;
-                               } else {
-                                       DEBUGP("Lok ");
                                }
-                       }
-                       /* Step to the next */
-                       if ((unsigned char)*optdesc == 0){
-                               DEBUGP("PAD0 \n");
-                               ptr++;
-                               hdrlen--;
+                               DEBUGP("Lok ");
+                               optlen += 2;
                        } else {
-                               ptr += LOW(ntohs(*optdesc));
-                               hdrlen -= LOW(ntohs(*optdesc));
-                               DEBUGP("len%04X \n", 
-                                       LOW(ntohs(*optdesc)));
+                               DEBUGP("Pad1\n");
+                               optlen = 1;
                        }
-                       if (ptr > skb->len || ( !hdrlen && 
-                               (temp != optinfo->optsnr - 1))) {
+
+                       /* Step to the next */
+                       DEBUGP("len%04X \n", optlen);
+
+                       if ((ptr > skb->len - optlen || hdrlen < optlen) &&
+                           (temp < optinfo->optsnr - 1)) {
                                DEBUGP("new pointer is too large! \n");
                                break;
                        }
+                       ptr += optlen;
+                       hdrlen -= optlen;
                }
                if (temp == optinfo->optsnr)
                        return ret;
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-24" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to