123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- --- a/include/uapi/linux/netfilter_ipv4/ip_tables.h
- +++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h
- @@ -87,6 +87,7 @@ struct ipt_ip {
- #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
- #define IPT_F_GOTO 0x02 /* Set if jump is a goto */
- #define IPT_F_MASK 0x03 /* All possible flag bits mask. */
- +#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */
-
- /* Values for "inv" field in struct ipt_ip. */
- #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
- --- a/net/ipv4/netfilter/ip_tables.c
- +++ b/net/ipv4/netfilter/ip_tables.c
- @@ -82,6 +82,9 @@ ip_packet_match(const struct iphdr *ip,
-
- #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
-
- + if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
- + return true;
- +
- if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
- IPT_INV_SRCIP) ||
- FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
- @@ -135,6 +138,29 @@ ip_packet_match(const struct iphdr *ip,
- return true;
- }
-
- +static void
- +ip_checkdefault(struct ipt_ip *ip)
- +{
- + static const char iface_mask[IFNAMSIZ] = {};
- +
- + if (ip->invflags || ip->flags & IPT_F_FRAG)
- + return;
- +
- + if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0)
- + return;
- +
- + if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0)
- + return;
- +
- + if (ip->smsk.s_addr || ip->dmsk.s_addr)
- + return;
- +
- + if (ip->proto)
- + return;
- +
- + ip->flags |= IPT_F_NO_DEF_MATCH;
- +}
- +
- static bool
- ip_checkentry(const struct ipt_ip *ip)
- {
- @@ -655,6 +681,8 @@ find_check_entry(struct ipt_entry *e, st
- struct xt_entry_match *ematch;
- unsigned long pcnt;
-
- + ip_checkdefault(&e->ip);
- +
- pcnt = xt_percpu_counter_alloc();
- if (IS_ERR_VALUE(pcnt))
- return -ENOMEM;
- @@ -953,6 +981,7 @@ copy_entries_to_user(unsigned int total_
- const struct xt_table_info *private = table->private;
- int ret = 0;
- const void *loc_cpu_entry;
- + u8 flags;
-
- counters = alloc_counters(table);
- if (IS_ERR(counters))
- @@ -979,6 +1008,14 @@ copy_entries_to_user(unsigned int total_
- ret = -EFAULT;
- goto free_counters;
- }
- +
- + flags = e->ip.flags & IPT_F_MASK;
- + if (copy_to_user(userptr + off
- + + offsetof(struct ipt_entry, ip.flags),
- + &flags, sizeof(flags)) != 0) {
- + ret = -EFAULT;
- + goto free_counters;
- + }
-
- for (i = sizeof(struct ipt_entry);
- i < e->target_offset;
|