Commit 53cfd053 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Conflicts:
	include/net/netfilter/nf_conntrack.h

The conflict was an overlap between changing the type of the zone
argument to nf_ct_tmpl_alloc() whilst exporting nf_ct_tmpl_free.

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net, they are:

1) Oneliner to restore maps in nf_tables since we support addressing registers
   at 32 bits level.

2) Restore previous default behaviour in bridge netfilter when CONFIG_IPV6=n,
   oneliner from Bernhard Thaler.

3) Out of bound access in ipset hash:net* set types, reported by Dave Jones'
   KASan utility, patch from Jozsef Kadlecsik.

4) Fix ipset compilation with gcc 4.4.7 related to C99 initialization of
   unnamed unions, patch from Elad Raz.

5) Add a workaround to address inconsistent endianess in the res_id field of
   nfnetlink batch messages, reported by Florian Westphal.

6) Fix error paths of CT/synproxy since the conntrack template was moved to use
   kmalloc, patch from Daniel Borkmann.

All of them look good to me to reach 4.2, I can route this to -stable myself
too, just let me know what you prefer.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents bd516bd1 9cf94eab
...@@ -59,7 +59,7 @@ static inline unsigned int ...@@ -59,7 +59,7 @@ static inline unsigned int
br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops, struct sk_buff *skb, br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops, struct sk_buff *skb,
const struct nf_hook_state *state) const struct nf_hook_state *state)
{ {
return NF_DROP; return NF_ACCEPT;
} }
#endif #endif
......
...@@ -298,6 +298,7 @@ void init_nf_conntrack_hash_rnd(void); ...@@ -298,6 +298,7 @@ void init_nf_conntrack_hash_rnd(void);
struct nf_conn *nf_ct_tmpl_alloc(struct net *net, struct nf_conn *nf_ct_tmpl_alloc(struct net *net,
const struct nf_conntrack_zone *zone, const struct nf_conntrack_zone *zone,
gfp_t flags); gfp_t flags);
void nf_ct_tmpl_free(struct nf_conn *tmpl);
#define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count) #define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count)
#define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count) #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count)
......
...@@ -125,7 +125,7 @@ static inline enum nft_data_types nft_dreg_to_type(enum nft_registers reg) ...@@ -125,7 +125,7 @@ static inline enum nft_data_types nft_dreg_to_type(enum nft_registers reg)
static inline enum nft_registers nft_type_to_reg(enum nft_data_types type) static inline enum nft_registers nft_type_to_reg(enum nft_data_types type)
{ {
return type == NFT_DATA_VERDICT ? NFT_REG_VERDICT : NFT_REG_1; return type == NFT_DATA_VERDICT ? NFT_REG_VERDICT : NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE;
} }
unsigned int nft_parse_register(const struct nlattr *attr); unsigned int nft_parse_register(const struct nlattr *attr);
......
...@@ -152,9 +152,13 @@ htable_bits(u32 hashsize) ...@@ -152,9 +152,13 @@ htable_bits(u32 hashsize)
#define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128) #define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128)
#ifdef IP_SET_HASH_WITH_NET0 #ifdef IP_SET_HASH_WITH_NET0
/* cidr from 0 to SET_HOST_MASK() value and c = cidr + 1 */
#define NLEN(family) (SET_HOST_MASK(family) + 1) #define NLEN(family) (SET_HOST_MASK(family) + 1)
#define CIDR_POS(c) ((c) - 1)
#else #else
/* cidr from 1 to SET_HOST_MASK() value and c = cidr + 1 */
#define NLEN(family) SET_HOST_MASK(family) #define NLEN(family) SET_HOST_MASK(family)
#define CIDR_POS(c) ((c) - 2)
#endif #endif
#else #else
...@@ -305,7 +309,7 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n) ...@@ -305,7 +309,7 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
} else if (h->nets[i].cidr[n] < cidr) { } else if (h->nets[i].cidr[n] < cidr) {
j = i; j = i;
} else if (h->nets[i].cidr[n] == cidr) { } else if (h->nets[i].cidr[n] == cidr) {
h->nets[cidr - 1].nets[n]++; h->nets[CIDR_POS(cidr)].nets[n]++;
return; return;
} }
} }
...@@ -314,7 +318,7 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n) ...@@ -314,7 +318,7 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
h->nets[i].cidr[n] = h->nets[i - 1].cidr[n]; h->nets[i].cidr[n] = h->nets[i - 1].cidr[n];
} }
h->nets[i].cidr[n] = cidr; h->nets[i].cidr[n] = cidr;
h->nets[cidr - 1].nets[n] = 1; h->nets[CIDR_POS(cidr)].nets[n] = 1;
} }
static void static void
...@@ -325,8 +329,8 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n) ...@@ -325,8 +329,8 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
for (i = 0; i < nets_length; i++) { for (i = 0; i < nets_length; i++) {
if (h->nets[i].cidr[n] != cidr) if (h->nets[i].cidr[n] != cidr)
continue; continue;
h->nets[cidr - 1].nets[n]--; h->nets[CIDR_POS(cidr)].nets[n]--;
if (h->nets[cidr - 1].nets[n] > 0) if (h->nets[CIDR_POS(cidr)].nets[n] > 0)
return; return;
for (j = i; j < net_end && h->nets[j].cidr[n]; j++) for (j = i; j < net_end && h->nets[j].cidr[n]; j++)
h->nets[j].cidr[n] = h->nets[j + 1].cidr[n]; h->nets[j].cidr[n] = h->nets[j + 1].cidr[n];
......
...@@ -131,6 +131,13 @@ hash_netnet4_data_next(struct hash_netnet4_elem *next, ...@@ -131,6 +131,13 @@ hash_netnet4_data_next(struct hash_netnet4_elem *next,
#define HOST_MASK 32 #define HOST_MASK 32
#include "ip_set_hash_gen.h" #include "ip_set_hash_gen.h"
static void
hash_netnet4_init(struct hash_netnet4_elem *e)
{
e->cidr[0] = HOST_MASK;
e->cidr[1] = HOST_MASK;
}
static int static int
hash_netnet4_kadt(struct ip_set *set, const struct sk_buff *skb, hash_netnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par, const struct xt_action_param *par,
...@@ -160,7 +167,7 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -160,7 +167,7 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
{ {
const struct hash_netnet *h = set->data; const struct hash_netnet *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netnet4_elem e = { .cidr = { HOST_MASK, HOST_MASK, }, }; struct hash_netnet4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip = 0, ip_to = 0, last; u32 ip = 0, ip_to = 0, last;
u32 ip2 = 0, ip2_from = 0, ip2_to = 0, last2; u32 ip2 = 0, ip2_from = 0, ip2_to = 0, last2;
...@@ -169,6 +176,7 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -169,6 +176,7 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
if (tb[IPSET_ATTR_LINENO]) if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
hash_netnet4_init(&e);
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
return -IPSET_ERR_PROTOCOL; return -IPSET_ERR_PROTOCOL;
...@@ -357,6 +365,13 @@ hash_netnet6_data_next(struct hash_netnet4_elem *next, ...@@ -357,6 +365,13 @@ hash_netnet6_data_next(struct hash_netnet4_elem *next,
#define IP_SET_EMIT_CREATE #define IP_SET_EMIT_CREATE
#include "ip_set_hash_gen.h" #include "ip_set_hash_gen.h"
static void
hash_netnet6_init(struct hash_netnet6_elem *e)
{
e->cidr[0] = HOST_MASK;
e->cidr[1] = HOST_MASK;
}
static int static int
hash_netnet6_kadt(struct ip_set *set, const struct sk_buff *skb, hash_netnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par, const struct xt_action_param *par,
...@@ -385,13 +400,14 @@ hash_netnet6_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -385,13 +400,14 @@ hash_netnet6_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{ {
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netnet6_elem e = { .cidr = { HOST_MASK, HOST_MASK, }, }; struct hash_netnet6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
int ret; int ret;
if (tb[IPSET_ATTR_LINENO]) if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
hash_netnet6_init(&e);
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
return -IPSET_ERR_PROTOCOL; return -IPSET_ERR_PROTOCOL;
......
...@@ -142,6 +142,13 @@ hash_netportnet4_data_next(struct hash_netportnet4_elem *next, ...@@ -142,6 +142,13 @@ hash_netportnet4_data_next(struct hash_netportnet4_elem *next,
#define HOST_MASK 32 #define HOST_MASK 32
#include "ip_set_hash_gen.h" #include "ip_set_hash_gen.h"
static void
hash_netportnet4_init(struct hash_netportnet4_elem *e)
{
e->cidr[0] = HOST_MASK;
e->cidr[1] = HOST_MASK;
}
static int static int
hash_netportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, hash_netportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par, const struct xt_action_param *par,
...@@ -175,7 +182,7 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -175,7 +182,7 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
{ {
const struct hash_netportnet *h = set->data; const struct hash_netportnet *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netportnet4_elem e = { .cidr = { HOST_MASK, HOST_MASK, }, }; struct hash_netportnet4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip = 0, ip_to = 0, ip_last, p = 0, port, port_to; u32 ip = 0, ip_to = 0, ip_last, p = 0, port, port_to;
u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2; u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2;
...@@ -185,6 +192,7 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -185,6 +192,7 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
if (tb[IPSET_ATTR_LINENO]) if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
hash_netportnet4_init(&e);
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
...@@ -412,6 +420,13 @@ hash_netportnet6_data_next(struct hash_netportnet4_elem *next, ...@@ -412,6 +420,13 @@ hash_netportnet6_data_next(struct hash_netportnet4_elem *next,
#define IP_SET_EMIT_CREATE #define IP_SET_EMIT_CREATE
#include "ip_set_hash_gen.h" #include "ip_set_hash_gen.h"
static void
hash_netportnet6_init(struct hash_netportnet6_elem *e)
{
e->cidr[0] = HOST_MASK;
e->cidr[1] = HOST_MASK;
}
static int static int
hash_netportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, hash_netportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par, const struct xt_action_param *par,
...@@ -445,7 +460,7 @@ hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -445,7 +460,7 @@ hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
{ {
const struct hash_netportnet *h = set->data; const struct hash_netportnet *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netportnet6_elem e = { .cidr = { HOST_MASK, HOST_MASK, }, }; struct hash_netportnet6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 port, port_to; u32 port, port_to;
bool with_ports = false; bool with_ports = false;
...@@ -454,6 +469,7 @@ hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -454,6 +469,7 @@ hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
if (tb[IPSET_ATTR_LINENO]) if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
hash_netportnet6_init(&e);
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
......
...@@ -313,12 +313,13 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net, ...@@ -313,12 +313,13 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net,
} }
EXPORT_SYMBOL_GPL(nf_ct_tmpl_alloc); EXPORT_SYMBOL_GPL(nf_ct_tmpl_alloc);
static void nf_ct_tmpl_free(struct nf_conn *tmpl) void nf_ct_tmpl_free(struct nf_conn *tmpl)
{ {
nf_ct_ext_destroy(tmpl); nf_ct_ext_destroy(tmpl);
nf_ct_ext_free(tmpl); nf_ct_ext_free(tmpl);
kfree(tmpl); kfree(tmpl);
} }
EXPORT_SYMBOL_GPL(nf_ct_tmpl_free);
static void static void
destroy_conntrack(struct nf_conntrack *nfct) destroy_conntrack(struct nf_conntrack *nfct)
......
...@@ -380,7 +380,7 @@ static int __net_init synproxy_net_init(struct net *net) ...@@ -380,7 +380,7 @@ static int __net_init synproxy_net_init(struct net *net)
err3: err3:
free_percpu(snet->stats); free_percpu(snet->stats);
err2: err2:
nf_conntrack_free(ct); nf_ct_tmpl_free(ct);
err1: err1:
return err; return err;
} }
......
...@@ -444,6 +444,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -444,6 +444,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
static void nfnetlink_rcv(struct sk_buff *skb) static void nfnetlink_rcv(struct sk_buff *skb)
{ {
struct nlmsghdr *nlh = nlmsg_hdr(skb); struct nlmsghdr *nlh = nlmsg_hdr(skb);
u_int16_t res_id;
int msglen; int msglen;
if (nlh->nlmsg_len < NLMSG_HDRLEN || if (nlh->nlmsg_len < NLMSG_HDRLEN ||
...@@ -468,7 +469,12 @@ static void nfnetlink_rcv(struct sk_buff *skb) ...@@ -468,7 +469,12 @@ static void nfnetlink_rcv(struct sk_buff *skb)
nfgenmsg = nlmsg_data(nlh); nfgenmsg = nlmsg_data(nlh);
skb_pull(skb, msglen); skb_pull(skb, msglen);
nfnetlink_rcv_batch(skb, nlh, nfgenmsg->res_id); /* Work around old nft using host byte order */
if (nfgenmsg->res_id == NFNL_SUBSYS_NFTABLES)
res_id = NFNL_SUBSYS_NFTABLES;
else
res_id = ntohs(nfgenmsg->res_id);
nfnetlink_rcv_batch(skb, nlh, res_id);
} else { } else {
netlink_rcv_skb(skb, &nfnetlink_rcv_msg); netlink_rcv_skb(skb, &nfnetlink_rcv_msg);
} }
......
...@@ -255,7 +255,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, ...@@ -255,7 +255,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
return 0; return 0;
err3: err3:
nf_conntrack_free(ct); nf_ct_tmpl_free(ct);
err2: err2:
nf_ct_l3proto_module_put(par->family); nf_ct_l3proto_module_put(par->family);
err1: err1:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment