source: trunk/target/linux/generic-2.6/patches-2.6.32/110-netfilter_match_speedup.patch @ 20552

Last change on this file since 20552 was 20552, checked in by nbd, 7 years ago

netfilter: fix ABI breakage caused by the netfilter match optimization (fixes #5628)

File size: 4.2 KB
  • include/linux/netfilter_ipv4/ip_tables.h

    a b struct ipt_ip { 
    6262#define IPT_F_FRAG              0x01    /* Set if rule is a fragment rule */ 
    6363#define IPT_F_GOTO              0x02    /* Set if jump is a goto */ 
    6464#define IPT_F_MASK              0x03    /* All possible flag bits mask. */ 
     65#define IPT_F_NO_DEF_MATCH      0x80    /* Internal: no default match rules present */ 
    6566 
    6667/* Values for "inv" field in struct ipt_ip. */ 
    6768#define IPT_INV_VIA_IN          0x01    /* Invert the sense of IN IFACE. */ 
  • net/ipv4/netfilter/ip_tables.c

    a b ip_packet_match(const struct iphdr *ip, 
    8888 
    8989#define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg))) 
    9090 
     91        if (ipinfo->flags & IPT_F_NO_DEF_MATCH) 
     92                return true; 
     93 
    9194        if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr, 
    9295                  IPT_INV_SRCIP) 
    9396            || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr, 
    ip_packet_match(const struct iphdr *ip, 
    138141                return false; 
    139142        } 
    140143 
     144#undef FWINV 
    141145        return true; 
    142146} 
    143147 
    144148static bool 
    145 ip_checkentry(const struct ipt_ip *ip) 
     149ip_checkentry(struct ipt_ip *ip) 
    146150{ 
    147         if (ip->flags & ~IPT_F_MASK) { 
     151#define FWINV(bool, invflg) ((bool) || (ip->invflags & (invflg))) 
     152 
     153        if (FWINV(ip->smsk.s_addr, IPT_INV_SRCIP) || 
     154                FWINV(ip->dmsk.s_addr, IPT_INV_DSTIP)) 
     155                goto has_match_rules; 
     156 
     157        if (FWINV(!!((const unsigned long *)ip->iniface_mask)[0], 
     158                IPT_INV_VIA_IN) || 
     159            FWINV(!!((const unsigned long *)ip->outiface_mask)[0], 
     160                IPT_INV_VIA_OUT)) 
     161                goto has_match_rules; 
     162 
     163        if (FWINV(ip->proto, IPT_INV_PROTO)) 
     164                goto has_match_rules; 
     165 
     166        if (FWINV(ip->flags&IPT_F_FRAG, IPT_INV_FRAG)) 
     167                goto has_match_rules; 
     168 
     169        ip->flags |= IPT_F_NO_DEF_MATCH; 
     170 
     171has_match_rules: 
     172        if (ip->flags & ~(IPT_F_MASK|IPT_F_NO_DEF_MATCH)) { 
    148173                duprintf("Unknown flag bits set: %08X\n", 
    149174                         ip->flags & ~IPT_F_MASK); 
    150175                return false; 
    ip_checkentry(const struct ipt_ip *ip) 
    154179                         ip->invflags & ~IPT_INV_MASK); 
    155180                return false; 
    156181        } 
     182 
     183#undef FWINV 
    157184        return true; 
    158185} 
    159186 
    static inline bool unconditional(const s 
    196223        static const struct ipt_ip uncond; 
    197224 
    198225        return memcmp(ip, &uncond, sizeof(uncond)) == 0; 
    199 #undef FWINV 
    200226} 
    201227 
    202228#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ 
    ipt_do_table(struct sk_buff *skb, 
    321347        struct xt_match_param mtpar; 
    322348        struct xt_target_param tgpar; 
    323349 
    324         /* Initialization */ 
    325350        ip = ip_hdr(skb); 
     351 
     352        IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 
     353        xt_info_rdlock_bh(); 
     354        private = table->private; 
     355        table_base = private->entries[smp_processor_id()]; 
     356        e = get_entry(table_base, private->hook_entry[hook]); 
     357 
     358        if (e->target_offset <= sizeof(struct ipt_entry) && 
     359                (e->ip.flags & IPT_F_NO_DEF_MATCH)) { 
     360                        struct ipt_entry_target *t = ipt_get_target(e); 
     361                        if (!t->u.kernel.target->target) { 
     362                                int v = ((struct ipt_standard_target *)t)->verdict; 
     363                                if ((v < 0) && (v != IPT_RETURN)) { 
     364                                        ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); 
     365                                        xt_info_rdunlock_bh(); 
     366                                        return (unsigned)(-v) - 1; 
     367                                } 
     368                        } 
     369        } 
     370 
     371        /* Initialization */ 
    326372        indev = in ? in->name : nulldevname; 
    327373        outdev = out ? out->name : nulldevname; 
    328374        /* We handle fragments by dealing with the first fragment as 
    ipt_do_table(struct sk_buff *skb, 
    339385        mtpar.family  = tgpar.family = NFPROTO_IPV4; 
    340386        mtpar.hooknum = tgpar.hooknum = hook; 
    341387 
    342         IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 
    343         xt_info_rdlock_bh(); 
    344         private = table->private; 
    345         table_base = private->entries[smp_processor_id()]; 
    346  
    347         e = get_entry(table_base, private->hook_entry[hook]); 
    348  
    349388        /* For return from builtin chain */ 
    350389        back = get_entry(table_base, private->underflow[hook]); 
    351390 
    copy_entries_to_user(unsigned int total_ 
    9921031                unsigned int i; 
    9931032                const struct ipt_entry_match *m; 
    9941033                const struct ipt_entry_target *t; 
     1034                u8 flags; 
    9951035 
    9961036                e = (struct ipt_entry *)(loc_cpu_entry + off); 
    9971037                if (copy_to_user(userptr + off 
    copy_entries_to_user(unsigned int total_ 
    10021042                        goto free_counters; 
    10031043                } 
    10041044 
     1045                flags = e->ip.flags & ~IPT_F_NO_DEF_MATCH; 
     1046                if (copy_to_user(userptr + off 
     1047                                 + offsetof(struct ipt_entry, ip.flags), 
     1048                                 &flags, sizeof(flags)) != 0) { 
     1049                        ret = -EFAULT; 
     1050                        goto free_counters; 
     1051                } 
     1052 
    10051053                for (i = sizeof(struct ipt_entry); 
    10061054                     i < e->target_offset; 
    10071055                     i += m->u.match_size) { 
Note: See TracBrowser for help on using the repository browser.