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

Last change on this file since 20552 was 20552, checked in by nbd, 6 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, 
    8787 
    8888#define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg))) 
    8989 
     90        if (ipinfo->flags & IPT_F_NO_DEF_MATCH) 
     91                return true; 
     92 
    9093        if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr, 
    9194                  IPT_INV_SRCIP) 
    9295            || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr, 
    ip_packet_match(const struct iphdr *ip, 
    137140                return false; 
    138141        } 
    139142 
     143#undef FWINV 
    140144        return true; 
    141145} 
    142146 
    143147static bool 
    144 ip_checkentry(const struct ipt_ip *ip) 
     148ip_checkentry(struct ipt_ip *ip) 
    145149{ 
    146         if (ip->flags & ~IPT_F_MASK) { 
     150#define FWINV(bool, invflg) ((bool) || (ip->invflags & (invflg))) 
     151 
     152        if (FWINV(ip->smsk.s_addr, IPT_INV_SRCIP) || 
     153                FWINV(ip->dmsk.s_addr, IPT_INV_DSTIP)) 
     154                goto has_match_rules; 
     155 
     156        if (FWINV(!!((const unsigned long *)ip->iniface_mask)[0], 
     157                IPT_INV_VIA_IN) || 
     158            FWINV(!!((const unsigned long *)ip->outiface_mask)[0], 
     159                IPT_INV_VIA_OUT)) 
     160                goto has_match_rules; 
     161 
     162        if (FWINV(ip->proto, IPT_INV_PROTO)) 
     163                goto has_match_rules; 
     164 
     165        if (FWINV(ip->flags&IPT_F_FRAG, IPT_INV_FRAG)) 
     166                goto has_match_rules; 
     167 
     168        ip->flags |= IPT_F_NO_DEF_MATCH; 
     169 
     170has_match_rules: 
     171        if (ip->flags & ~(IPT_F_MASK|IPT_F_NO_DEF_MATCH)) { 
    147172                duprintf("Unknown flag bits set: %08X\n", 
    148173                         ip->flags & ~IPT_F_MASK); 
    149174                return false; 
    ip_checkentry(const struct ipt_ip *ip) 
    153178                         ip->invflags & ~IPT_INV_MASK); 
    154179                return false; 
    155180        } 
     181 
     182#undef FWINV 
    156183        return true; 
    157184} 
    158185 
    unconditional(const struct ipt_ip *ip) 
    200227                        return 0; 
    201228 
    202229        return 1; 
    203 #undef FWINV 
    204230} 
    205231 
    206232#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ 
    ipt_do_table(struct sk_buff *skb, 
    326352        struct xt_match_param mtpar; 
    327353        struct xt_target_param tgpar; 
    328354 
    329         /* Initialization */ 
    330355        ip = ip_hdr(skb); 
     356 
     357        IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 
     358        xt_info_rdlock_bh(); 
     359        private = table->private; 
     360        table_base = private->entries[smp_processor_id()]; 
     361        e = get_entry(table_base, private->hook_entry[hook]); 
     362 
     363        if (e->target_offset <= sizeof(struct ipt_entry) && 
     364                (e->ip.flags & IPT_F_NO_DEF_MATCH)) { 
     365                        struct ipt_entry_target *t = ipt_get_target(e); 
     366                        if (!t->u.kernel.target->target) { 
     367                                int v = ((struct ipt_standard_target *)t)->verdict; 
     368                                if ((v < 0) && (v != IPT_RETURN)) { 
     369                                        ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); 
     370                                        xt_info_rdunlock_bh(); 
     371                                        return (unsigned)(-v) - 1; 
     372                                } 
     373                        } 
     374        } 
     375 
     376        /* Initialization */ 
    331377        datalen = skb->len - ip->ihl * 4; 
    332378        indev = in ? in->name : nulldevname; 
    333379        outdev = out ? out->name : nulldevname; 
    ipt_do_table(struct sk_buff *skb, 
    345391        mtpar.family  = tgpar.family = NFPROTO_IPV4; 
    346392        mtpar.hooknum = tgpar.hooknum = hook; 
    347393 
    348         IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 
    349         xt_info_rdlock_bh(); 
    350         private = table->private; 
    351         table_base = private->entries[smp_processor_id()]; 
    352  
    353         e = get_entry(table_base, private->hook_entry[hook]); 
    354  
    355394        /* For return from builtin chain */ 
    356395        back = get_entry(table_base, private->underflow[hook]); 
    357396 
    copy_entries_to_user(unsigned int total_ 
    9781017                unsigned int i; 
    9791018                const struct ipt_entry_match *m; 
    9801019                const struct ipt_entry_target *t; 
     1020                u8 flags; 
    9811021 
    9821022                e = (struct ipt_entry *)(loc_cpu_entry + off); 
    9831023                if (copy_to_user(userptr + off 
    copy_entries_to_user(unsigned int total_ 
    9881028                        goto free_counters; 
    9891029                } 
    9901030 
     1031                flags = e->ip.flags & ~IPT_F_NO_DEF_MATCH; 
     1032                if (copy_to_user(userptr + off 
     1033                                 + offsetof(struct ipt_entry, ip.flags), 
     1034                                 &flags, sizeof(flags)) != 0) { 
     1035                        ret = -EFAULT; 
     1036                        goto free_counters; 
     1037                } 
     1038 
    9911039                for (i = sizeof(struct ipt_entry); 
    9921040                     i < e->target_offset; 
    9931041                     i += m->u.match_size) { 
Note: See TracBrowser for help on using the repository browser.