source: trunk/target/linux/generic/patches-2.6.39/610-netfilter_match_bypass_default_checks.patch @ 27923

Last change on this file since 27923 was 27923, checked in by nbd, 5 years ago

kernel: add missing checks in the netfilter optimization patch which broke some rules containing only source/destination address checks

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

    a b struct ipt_ip { 
    9393#define IPT_F_FRAG              0x01    /* Set if rule is a fragment rule */ 
    9494#define IPT_F_GOTO              0x02    /* Set if jump is a goto */ 
    9595#define IPT_F_MASK              0x03    /* All possible flag bits mask. */ 
     96#define IPT_F_NO_DEF_MATCH      0x80    /* Internal: no default match rules present */ 
    9697 
    9798/* Values for "inv" field in struct ipt_ip. */ 
    9899#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, 
    9090 
    9191#define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg))) 
    9292 
     93        if (ipinfo->flags & IPT_F_NO_DEF_MATCH) 
     94                return true; 
     95 
    9396        if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr, 
    9497                  IPT_INV_SRCIP) || 
    9598            FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr, 
    ip_packet_match(const struct iphdr *ip, 
    143146        return true; 
    144147} 
    145148 
     149static void 
     150ip_checkdefault(struct ipt_ip *ip) 
     151{ 
     152        static const char iface_mask[IFNAMSIZ] = {}; 
     153 
     154        if (ip->invflags || ip->flags & IPT_F_FRAG) 
     155                return; 
     156 
     157        if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0) 
     158                return; 
     159 
     160        if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0) 
     161                return; 
     162 
     163        if (ip->smsk.s_addr || ip->dmsk.s_addr) 
     164                return; 
     165 
     166        if (ip->proto) 
     167                return; 
     168 
     169        ip->flags |= IPT_F_NO_DEF_MATCH; 
     170} 
     171 
    146172static bool 
    147173ip_checkentry(const struct ipt_ip *ip) 
    148174{ 
    static void cleanup_match(struct xt_entr 
    566592} 
    567593 
    568594static int 
    569 check_entry(const struct ipt_entry *e, const char *name) 
     595check_entry(struct ipt_entry *e, const char *name) 
    570596{ 
    571597        const struct xt_entry_target *t; 
    572598 
    check_entry(const struct ipt_entry *e, c 
    575601                return -EINVAL; 
    576602        } 
    577603 
     604        ip_checkdefault(&e->ip); 
     605 
    578606        if (e->target_offset + sizeof(struct xt_entry_target) > 
    579607            e->next_offset) 
    580608                return -EINVAL; 
    copy_entries_to_user(unsigned int total_ 
    936964        const struct xt_table_info *private = table->private; 
    937965        int ret = 0; 
    938966        const void *loc_cpu_entry; 
     967        u8 flags; 
    939968 
    940969        counters = alloc_counters(table); 
    941970        if (IS_ERR(counters)) 
    copy_entries_to_user(unsigned int total_ 
    967996                        goto free_counters; 
    968997                } 
    969998 
     999                flags = e->ip.flags & IPT_F_MASK; 
     1000                if (copy_to_user(userptr + off 
     1001                                 + offsetof(struct ipt_entry, ip.flags), 
     1002                                 &flags, sizeof(flags)) != 0) { 
     1003                        ret = -EFAULT; 
     1004                        goto free_counters; 
     1005                } 
     1006 
    9701007                for (i = sizeof(struct ipt_entry); 
    9711008                     i < e->target_offset; 
    9721009                     i += m->u.match_size) { 
Note: See TracBrowser for help on using the repository browser.