Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Browse files Browse the repository at this point in the history
Pablo Neira Ayuso says:

====================
netfilter fixes for net

The following patchset contains netfilter updates for your net tree,
they are:

1) Fix refcount leak when dumping the dying/unconfirmed conntrack lists,
   from Florian Westphal.

2) Fix crash in NAT when removing a netnamespace, also from Florian.

3) Fix a crash in IPVS when trying to remove an estimator out of the
   sysctl scope, from Julian Anastasov.

4) Add zone attribute to the routing to calculate the message size in
   ctnetlink events, from Ken-ichirou MATSUZAWA.

5) Another fix for the dying/unconfirmed list which was preventing to
   dump more than one memory page of entries (~17 entries in x86_64).

6) Fix missing RCU-safe list insertion in the rule replacement code
   in nf_tables.

7) Since the new transaction infrastructure is in place, we have to
   upgrade the chain use counter from u16 to u32 to avoid overflow
   after more than 2^16 rules are added.

8) Fix refcount leak when replacing rule in nf_tables. This problem
   was also introduced in new transaction.

9) Call the ->destroy() callback when releasing nft-xt rules to fix
   module refcount leaks.

10) Set the family in the netlink messages that contain set elements
    in nf_tables to make it consistent with other object types.

11) Don't dump NAT port information if it is unset in nft_nat.

12) Update the MAINTAINERS file, I have merged the ebtables entry
    into netfilter. While at it, also removed the netfilter users
    mailing list, the development list should be enough.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jun 18, 2014
2 parents 62a02c9 + db9cf3a commit 3a3ec1b
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 31 deletions.
11 changes: 1 addition & 10 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -3189,14 +3189,6 @@ L: linux-scsi@vger.kernel.org
S: Maintained
F: drivers/scsi/eata_pio.*

EBTABLES
L: netfilter-devel@vger.kernel.org
W: http://ebtables.sourceforge.net/
S: Orphan
F: include/linux/netfilter_bridge/ebt_*.h
F: include/uapi/linux/netfilter_bridge/ebt_*.h
F: net/bridge/netfilter/ebt*.c

EC100 MEDIA DRIVER
M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
Expand Down Expand Up @@ -6105,12 +6097,11 @@ F: Documentation/networking/s2io.txt
F: Documentation/networking/vxge.txt
F: drivers/net/ethernet/neterion/

NETFILTER/IPTABLES
NETFILTER ({IP,IP6,ARP,EB,NF}TABLES)
M: Pablo Neira Ayuso <pablo@netfilter.org>
M: Patrick McHardy <kaber@trash.net>
M: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
L: netfilter-devel@vger.kernel.org
L: netfilter@vger.kernel.org
L: coreteam@netfilter.org
W: http://www.netfilter.org/
W: http://www.iptables.org/
Expand Down
6 changes: 3 additions & 3 deletions include/net/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -503,9 +503,9 @@ enum nft_chain_flags {
* @net: net namespace that this chain belongs to
* @table: table that this chain belongs to
* @handle: chain handle
* @flags: bitmask of enum nft_chain_flags
* @use: number of jump references to this chain
* @level: length of longest path to this chain
* @flags: bitmask of enum nft_chain_flags
* @name: name of the chain
*/
struct nft_chain {
Expand All @@ -514,9 +514,9 @@ struct nft_chain {
struct net *net;
struct nft_table *table;
u64 handle;
u8 flags;
u16 use;
u32 use;
u16 level;
u8 flags;
char name[NFT_CHAIN_MAXNAMELEN];
};

Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/ipvs/ip_vs_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -3778,6 +3778,7 @@ static void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net)
cancel_delayed_work_sync(&ipvs->defense_work);
cancel_work_sync(&ipvs->defense_work.work);
unregister_net_sysctl_table(ipvs->sysctl_hdr);
ip_vs_stop_estimator(net, &ipvs->tot_stats);
}

#else
Expand Down Expand Up @@ -3840,7 +3841,6 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net)
struct netns_ipvs *ipvs = net_ipvs(net);

ip_vs_trash_cleanup(net);
ip_vs_stop_estimator(net, &ipvs->tot_stats);
ip_vs_control_net_cleanup_sysctl(net);
remove_proc_entry("ip_vs_stats_percpu", net->proc_net);
remove_proc_entry("ip_vs_stats", net->proc_net);
Expand Down
20 changes: 13 additions & 7 deletions net/netfilter/nf_conntrack_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,9 @@ ctnetlink_nlmsg_size(const struct nf_conn *ct)
#endif
#ifdef CONFIG_NF_CONNTRACK_MARK
+ nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */
#endif
#ifdef CONFIG_NF_CONNTRACK_ZONES
+ nla_total_size(sizeof(u_int16_t)) /* CTA_ZONE */
#endif
+ ctnetlink_proto_size(ct)
+ ctnetlink_label_size(ct)
Expand Down Expand Up @@ -1150,7 +1153,7 @@ static int ctnetlink_done_list(struct netlink_callback *cb)
static int
ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying)
{
struct nf_conn *ct, *last = NULL;
struct nf_conn *ct, *last;
struct nf_conntrack_tuple_hash *h;
struct hlist_nulls_node *n;
struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
Expand All @@ -1163,8 +1166,7 @@ ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying
if (cb->args[2])
return 0;

if (cb->args[0] == nr_cpu_ids)
return 0;
last = (struct nf_conn *)cb->args[1];

for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) {
struct ct_pcpu *pcpu;
Expand All @@ -1174,7 +1176,6 @@ ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying

pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu);
spin_lock_bh(&pcpu->lock);
last = (struct nf_conn *)cb->args[1];
list = dying ? &pcpu->dying : &pcpu->unconfirmed;
restart:
hlist_nulls_for_each_entry(h, n, list, hnnode) {
Expand All @@ -1193,7 +1194,9 @@ ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying
ct);
rcu_read_unlock();
if (res < 0) {
nf_conntrack_get(&ct->ct_general);
if (!atomic_inc_not_zero(&ct->ct_general.use))
continue;
cb->args[0] = cpu;
cb->args[1] = (unsigned long)ct;
spin_unlock_bh(&pcpu->lock);
goto out;
Expand All @@ -1202,10 +1205,10 @@ ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying
if (cb->args[1]) {
cb->args[1] = 0;
goto restart;
} else
cb->args[2] = 1;
}
spin_unlock_bh(&pcpu->lock);
}
cb->args[2] = 1;
out:
if (last)
nf_ct_put(last);
Expand Down Expand Up @@ -2039,6 +2042,9 @@ ctnetlink_nfqueue_build_size(const struct nf_conn *ct)
#endif
#ifdef CONFIG_NF_CONNTRACK_MARK
+ nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */
#endif
#ifdef CONFIG_NF_CONNTRACK_ZONES
+ nla_total_size(sizeof(u_int16_t)) /* CTA_ZONE */
#endif
+ ctnetlink_proto_size(ct)
;
Expand Down
35 changes: 34 additions & 1 deletion net/netfilter/nf_nat_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,39 @@ static int nf_nat_proto_remove(struct nf_conn *i, void *data)
return i->status & IPS_NAT_MASK ? 1 : 0;
}

static int nf_nat_proto_clean(struct nf_conn *ct, void *data)
{
struct nf_conn_nat *nat = nfct_nat(ct);

if (nf_nat_proto_remove(ct, data))
return 1;

if (!nat || !nat->ct)
return 0;

/* This netns is being destroyed, and conntrack has nat null binding.
* Remove it from bysource hash, as the table will be freed soon.
*
* Else, when the conntrack is destoyed, nf_nat_cleanup_conntrack()
* will delete entry from already-freed table.
*/
if (!del_timer(&ct->timeout))
return 1;

spin_lock_bh(&nf_nat_lock);
hlist_del_rcu(&nat->bysource);
ct->status &= ~IPS_NAT_DONE_MASK;
nat->ct = NULL;
spin_unlock_bh(&nf_nat_lock);

add_timer(&ct->timeout);

/* don't delete conntrack. Although that would make things a lot
* simpler, we'd end up flushing all conntracks on nat rmmod.
*/
return 0;
}

static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto)
{
struct nf_nat_proto_clean clean = {
Expand Down Expand Up @@ -795,7 +828,7 @@ static void __net_exit nf_nat_net_exit(struct net *net)
{
struct nf_nat_proto_clean clean = {};

nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean, 0, 0);
nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean, 0, 0);
synchronize_rcu();
nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size);
}
Expand Down
11 changes: 8 additions & 3 deletions net/netfilter/nf_tables_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1730,6 +1730,9 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
if (!create || nlh->nlmsg_flags & NLM_F_REPLACE)
return -EINVAL;
handle = nf_tables_alloc_handle(table);

if (chain->use == UINT_MAX)
return -EOVERFLOW;
}

if (nla[NFTA_RULE_POSITION]) {
Expand Down Expand Up @@ -1789,14 +1792,15 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,

if (nlh->nlmsg_flags & NLM_F_REPLACE) {
if (nft_rule_is_active_next(net, old_rule)) {
trans = nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE,
trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE,
old_rule);
if (trans == NULL) {
err = -ENOMEM;
goto err2;
}
nft_rule_disactivate_next(net, old_rule);
list_add_tail(&rule->list, &old_rule->list);
chain->use--;
list_add_tail_rcu(&rule->list, &old_rule->list);
} else {
err = -ENOENT;
goto err2;
Expand Down Expand Up @@ -1826,6 +1830,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
list_del_rcu(&nft_trans_rule(trans)->list);
nft_rule_clear(net, nft_trans_rule(trans));
nft_trans_destroy(trans);
chain->use++;
}
err2:
nf_tables_rule_destroy(&ctx, rule);
Expand Down Expand Up @@ -2845,7 +2850,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
goto nla_put_failure;

nfmsg = nlmsg_data(nlh);
nfmsg->nfgen_family = NFPROTO_UNSPEC;
nfmsg->nfgen_family = ctx.afi->family;
nfmsg->version = NFNETLINK_V0;
nfmsg->res_id = 0;

Expand Down
18 changes: 18 additions & 0 deletions net/netfilter/nft_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,15 @@ static void
nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
{
struct xt_target *target = expr->ops->data;
void *info = nft_expr_priv(expr);
struct xt_tgdtor_param par;

par.net = ctx->net;
par.target = target;
par.targinfo = info;
par.family = ctx->afi->family;
if (par.target->destroy != NULL)
par.target->destroy(&par);

module_put(target->me);
}
Expand Down Expand Up @@ -382,6 +391,15 @@ static void
nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
{
struct xt_match *match = expr->ops->data;
void *info = nft_expr_priv(expr);
struct xt_mtdtor_param par;

par.net = ctx->net;
par.match = match;
par.matchinfo = info;
par.family = ctx->afi->family;
if (par.match->destroy != NULL)
par.match->destroy(&par);

module_put(match->me);
}
Expand Down
14 changes: 8 additions & 6 deletions net/netfilter/nft_nat.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,14 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
if (nla_put_be32(skb,
NFTA_NAT_REG_ADDR_MAX, htonl(priv->sreg_addr_max)))
goto nla_put_failure;
if (nla_put_be32(skb,
NFTA_NAT_REG_PROTO_MIN, htonl(priv->sreg_proto_min)))
goto nla_put_failure;
if (nla_put_be32(skb,
NFTA_NAT_REG_PROTO_MAX, htonl(priv->sreg_proto_max)))
goto nla_put_failure;
if (priv->sreg_proto_min) {
if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MIN,
htonl(priv->sreg_proto_min)))
goto nla_put_failure;
if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX,
htonl(priv->sreg_proto_max)))
goto nla_put_failure;
}
return 0;

nla_put_failure:
Expand Down

0 comments on commit 3a3ec1b

Please sign in to comment.