Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== The following patchset contains Netfilter fixes for you net tree, mostly targeted to ipset, they are: * Fix ICMPv6 NAT due to wrong comparison, code instead of type, from Phil Oester. * Fix RCU race in conntrack extensions release path, from Michal Kubecek. * Fix missing inversion in the userspace ipset test command match if the nomatch option is specified, from Jozsef Kadlecsik. * Skip layer 4 protocol matching in ipset in case of IPv6 fragments, also from Jozsef Kadlecsik. * Fix sequence adjustment in nfnetlink_queue due to using the netlink skb instead of the network skb, from Gao feng. * Make sure we cannot swap of sets with different layer 3 family in ipset, from Jozsef Kadlecsik. * Fix possible bogus matching in ipset if hash sets with net elements are used, from Oliver Smith. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
61c5923a2f
11 changed files with 35 additions and 30 deletions
|
@ -296,10 +296,12 @@ ip_set_eexist(int ret, u32 flags)
|
|||
|
||||
/* Match elements marked with nomatch */
|
||||
static inline bool
|
||||
ip_set_enomatch(int ret, u32 flags, enum ipset_adt adt)
|
||||
ip_set_enomatch(int ret, u32 flags, enum ipset_adt adt, struct ip_set *set)
|
||||
{
|
||||
return adt == IPSET_TEST &&
|
||||
ret == -ENOTEMPTY && ((flags >> 16) & IPSET_FLAG_NOMATCH);
|
||||
(set->type->features & IPSET_TYPE_NOMATCH) &&
|
||||
((flags >> 16) & IPSET_FLAG_NOMATCH) &&
|
||||
(ret > 0 || ret == -ENOTEMPTY);
|
||||
}
|
||||
|
||||
/* Check the NLA_F_NET_BYTEORDER flag */
|
||||
|
|
|
@ -86,7 +86,7 @@ static inline void nf_ct_ext_destroy(struct nf_conn *ct)
|
|||
static inline void nf_ct_ext_free(struct nf_conn *ct)
|
||||
{
|
||||
if (ct->ext)
|
||||
kfree(ct->ext);
|
||||
kfree_rcu(ct->ext, rcu);
|
||||
}
|
||||
|
||||
/* Add this type, returns pointer to data or NULL. */
|
||||
|
|
|
@ -69,8 +69,8 @@ icmpv6_manip_pkt(struct sk_buff *skb,
|
|||
hdr = (struct icmp6hdr *)(skb->data + hdroff);
|
||||
l3proto->csum_update(skb, iphdroff, &hdr->icmp6_cksum,
|
||||
tuple, maniptype);
|
||||
if (hdr->icmp6_code == ICMPV6_ECHO_REQUEST ||
|
||||
hdr->icmp6_code == ICMPV6_ECHO_REPLY) {
|
||||
if (hdr->icmp6_type == ICMPV6_ECHO_REQUEST ||
|
||||
hdr->icmp6_type == ICMPV6_ECHO_REPLY) {
|
||||
inet_proto_csum_replace2(&hdr->icmp6_cksum, skb,
|
||||
hdr->icmp6_identifier,
|
||||
tuple->src.u.icmp.id, 0);
|
||||
|
|
|
@ -1052,7 +1052,7 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
|
|||
* Not an artificial restriction anymore, as we must prevent
|
||||
* possible loops created by swapping in setlist type of sets. */
|
||||
if (!(from->type->features == to->type->features &&
|
||||
from->type->family == to->type->family))
|
||||
from->family == to->family))
|
||||
return -IPSET_ERR_TYPE_MISMATCH;
|
||||
|
||||
strncpy(from_name, from->name, IPSET_MAXNAMELEN);
|
||||
|
@ -1489,8 +1489,7 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
|
|||
if (ret == -EAGAIN)
|
||||
ret = 1;
|
||||
|
||||
return (ret < 0 && ret != -ENOTEMPTY) ? ret :
|
||||
ret > 0 ? 0 : -IPSET_ERR_EXIST;
|
||||
return ret > 0 ? 0 : -IPSET_ERR_EXIST;
|
||||
}
|
||||
|
||||
/* Get headed data of a set */
|
||||
|
|
|
@ -116,12 +116,12 @@ ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
|
|||
{
|
||||
int protoff;
|
||||
u8 nexthdr;
|
||||
__be16 frag_off;
|
||||
__be16 frag_off = 0;
|
||||
|
||||
nexthdr = ipv6_hdr(skb)->nexthdr;
|
||||
protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
|
||||
&frag_off);
|
||||
if (protoff < 0)
|
||||
if (protoff < 0 || (frag_off & htons(~0x7)) != 0)
|
||||
return false;
|
||||
|
||||
return get_port(skb, nexthdr, protoff, src, port, proto);
|
||||
|
|
|
@ -325,18 +325,22 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length)
|
|||
static void
|
||||
mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length)
|
||||
{
|
||||
u8 i, j;
|
||||
u8 i, j, net_end = nets_length - 1;
|
||||
|
||||
for (i = 0; i < nets_length - 1 && h->nets[i].cidr != cidr; i++)
|
||||
;
|
||||
h->nets[i].nets--;
|
||||
|
||||
if (h->nets[i].nets != 0)
|
||||
return;
|
||||
|
||||
for (j = i; j < nets_length - 1 && h->nets[j].nets; j++) {
|
||||
h->nets[j].cidr = h->nets[j + 1].cidr;
|
||||
h->nets[j].nets = h->nets[j + 1].nets;
|
||||
for (i = 0; i < nets_length; i++) {
|
||||
if (h->nets[i].cidr != cidr)
|
||||
continue;
|
||||
if (h->nets[i].nets > 1 || i == net_end ||
|
||||
h->nets[i + 1].nets == 0) {
|
||||
h->nets[i].nets--;
|
||||
return;
|
||||
}
|
||||
for (j = i; j < net_end && h->nets[j].nets; j++) {
|
||||
h->nets[j].cidr = h->nets[j + 1].cidr;
|
||||
h->nets[j].nets = h->nets[j + 1].nets;
|
||||
}
|
||||
h->nets[j].nets = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -260,7 +260,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
e.ip = htonl(ip);
|
||||
e.ip2 = htonl(ip2_from & ip_set_hostmask(e.cidr + 1));
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
return ip_set_enomatch(ret, flags, adt) ? 1 :
|
||||
return ip_set_enomatch(ret, flags, adt, set) ? -ret :
|
||||
ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
|
@ -544,7 +544,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
return ip_set_enomatch(ret, flags, adt) ? 1 :
|
||||
return ip_set_enomatch(ret, flags, adt, set) ? -ret :
|
||||
ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
|
||||
e.ip = htonl(ip & ip_set_hostmask(e.cidr));
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
return ip_set_enomatch(ret, flags, adt) ? 1 :
|
||||
return ip_set_enomatch(ret, flags, adt, set) ? -ret:
|
||||
ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
|
@ -396,7 +396,7 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
|
||||
return ip_set_enomatch(ret, flags, adt) ? 1 :
|
||||
return ip_set_enomatch(ret, flags, adt, set) ? -ret :
|
||||
ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -368,7 +368,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
|
||||
e.ip = htonl(ip & ip_set_hostmask(e.cidr));
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
return ip_set_enomatch(ret, flags, adt) ? 1 :
|
||||
return ip_set_enomatch(ret, flags, adt, set) ? -ret :
|
||||
ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
|
@ -634,7 +634,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
|
||||
return ip_set_enomatch(ret, flags, adt) ? 1 :
|
||||
return ip_set_enomatch(ret, flags, adt, set) ? -ret :
|
||||
ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) {
|
||||
e.ip = htonl(ip & ip_set_hostmask(e.cidr + 1));
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
return ip_set_enomatch(ret, flags, adt) ? 1 :
|
||||
return ip_set_enomatch(ret, flags, adt, set) ? -ret :
|
||||
ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
|
@ -489,7 +489,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
return ip_set_enomatch(ret, flags, adt) ? 1 :
|
||||
return ip_set_enomatch(ret, flags, adt, set) ? -ret :
|
||||
ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1009,7 +1009,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
|
|||
verdict = NF_DROP;
|
||||
|
||||
if (ct)
|
||||
nfqnl_ct_seq_adjust(skb, ct, ctinfo, diff);
|
||||
nfqnl_ct_seq_adjust(entry->skb, ct, ctinfo, diff);
|
||||
}
|
||||
|
||||
if (nfqa[NFQA_MARK])
|
||||
|
|
Loading…
Reference in a new issue