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 fixes for your net tree, they are:

1) Unitialize the set element key and data from the commit path,
   otherwise this leaks chain refcount if the transaction is aborted,
   reported by Thomas Graf.

2) Fix crash when updating chains without no counters in nf_tables,
   this slipped through in the new transaction infrastructure, reported
   by Matteo Croce.

3) Replace all mutex_lock_interruptible() by mutex_lock() in the Netfilter
   tree, suggested by Patrick McHardy. This implicitly fixes the problem
   that Eric Dumazet reported in: http://patchwork.ozlabs.org/patch/373076/

4) Fix error return code in nf_tables when deleting set element in
   nf_tables if the transaction cannot be allocated, from Julia Lawall.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 11, 2014
2 parents 4da5e6a + 609ccf0 commit f00439e
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 86 deletions.
10 changes: 2 additions & 8 deletions net/bridge/netfilter/ebtables.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,10 +327,7 @@ find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
char name[EBT_FUNCTION_MAXNAMELEN];
} *e;

*error = mutex_lock_interruptible(mutex);
if (*error != 0)
return NULL;

mutex_lock(mutex);
list_for_each_entry(e, head, list) {
if (strcmp(e->name, name) == 0)
return e;
Expand Down Expand Up @@ -1203,10 +1200,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table)

table->private = newinfo;
rwlock_init(&table->lock);
ret = mutex_lock_interruptible(&ebt_mutex);
if (ret != 0)
goto free_chainstack;

mutex_lock(&ebt_mutex);
list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) {
if (strcmp(t->name, table->name) == 0) {
ret = -EEXIST;
Expand Down
11 changes: 2 additions & 9 deletions net/netfilter/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ EXPORT_SYMBOL_GPL(nf_ipv6_ops);

int nf_register_afinfo(const struct nf_afinfo *afinfo)
{
int err;

err = mutex_lock_interruptible(&afinfo_mutex);
if (err < 0)
return err;
mutex_lock(&afinfo_mutex);
RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo);
mutex_unlock(&afinfo_mutex);
return 0;
Expand Down Expand Up @@ -68,11 +64,8 @@ static DEFINE_MUTEX(nf_hook_mutex);
int nf_register_hook(struct nf_hook_ops *reg)
{
struct nf_hook_ops *elem;
int err;

err = mutex_lock_interruptible(&nf_hook_mutex);
if (err < 0)
return err;
mutex_lock(&nf_hook_mutex);
list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
if (reg->priority < elem->priority)
break;
Expand Down
19 changes: 4 additions & 15 deletions net/netfilter/ipvs/ip_vs_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2271,10 +2271,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
cmd == IP_VS_SO_SET_STOPDAEMON) {
struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;

if (mutex_lock_interruptible(&ipvs->sync_mutex)) {
ret = -ERESTARTSYS;
goto out_dec;
}
mutex_lock(&ipvs->sync_mutex);
if (cmd == IP_VS_SO_SET_STARTDAEMON)
ret = start_sync_thread(net, dm->state, dm->mcast_ifn,
dm->syncid);
Expand All @@ -2284,11 +2281,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
goto out_dec;
}

if (mutex_lock_interruptible(&__ip_vs_mutex)) {
ret = -ERESTARTSYS;
goto out_dec;
}

mutex_lock(&__ip_vs_mutex);
if (cmd == IP_VS_SO_SET_FLUSH) {
/* Flush the virtual service */
ret = ip_vs_flush(net, false);
Expand Down Expand Up @@ -2573,9 +2566,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
struct ip_vs_daemon_user d[2];

memset(&d, 0, sizeof(d));
if (mutex_lock_interruptible(&ipvs->sync_mutex))
return -ERESTARTSYS;

mutex_lock(&ipvs->sync_mutex);
if (ipvs->sync_state & IP_VS_STATE_MASTER) {
d[0].state = IP_VS_STATE_MASTER;
strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn,
Expand All @@ -2594,9 +2585,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
return ret;
}

if (mutex_lock_interruptible(&__ip_vs_mutex))
return -ERESTARTSYS;

mutex_lock(&__ip_vs_mutex);
switch (cmd) {
case IP_VS_SO_GET_VERSION:
{
Expand Down
8 changes: 2 additions & 6 deletions net/netfilter/nf_sockopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ int nf_register_sockopt(struct nf_sockopt_ops *reg)
struct nf_sockopt_ops *ops;
int ret = 0;

if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
return -EINTR;

mutex_lock(&nf_sockopt_mutex);
list_for_each_entry(ops, &nf_sockopts, list) {
if (ops->pf == reg->pf
&& (overlap(ops->set_optmin, ops->set_optmax,
Expand Down Expand Up @@ -65,9 +63,7 @@ static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, u_int8_t pf,
{
struct nf_sockopt_ops *ops;

if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
return ERR_PTR(-EINTR);

mutex_lock(&nf_sockopt_mutex);
list_for_each_entry(ops, &nf_sockopts, list) {
if (ops->pf == pf) {
if (!try_module_get(ops->owner))
Expand Down
30 changes: 17 additions & 13 deletions net/netfilter/nf_tables_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,9 @@ static struct nft_stats __percpu *nft_stats_alloc(const struct nlattr *attr)
static void nft_chain_stats_replace(struct nft_base_chain *chain,
struct nft_stats __percpu *newstats)
{
if (newstats == NULL)
return;

if (chain->stats) {
struct nft_stats __percpu *oldstats =
nft_dereference(chain->stats);
Expand Down Expand Up @@ -3134,16 +3137,13 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
goto err2;

trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set);
if (trans == NULL)
if (trans == NULL) {
err = -ENOMEM;
goto err2;
}

nft_trans_elem(trans) = elem;
list_add_tail(&trans->list, &ctx->net->nft.commit_list);

nft_data_uninit(&elem.key, NFT_DATA_VALUE);
if (set->flags & NFT_SET_MAP)
nft_data_uninit(&elem.data, set->dtype);

return 0;
err2:
nft_data_uninit(&elem.key, desc.type);
Expand Down Expand Up @@ -3310,7 +3310,7 @@ static int nf_tables_commit(struct sk_buff *skb)
{
struct net *net = sock_net(skb->sk);
struct nft_trans *trans, *next;
struct nft_set *set;
struct nft_trans_elem *te;

/* Bump generation counter, invalidate any dump in progress */
while (++net->nft.base_seq == 0);
Expand Down Expand Up @@ -3396,13 +3396,17 @@ static int nf_tables_commit(struct sk_buff *skb)
nft_trans_destroy(trans);
break;
case NFT_MSG_DELSETELEM:
nf_tables_setelem_notify(&trans->ctx,
nft_trans_elem_set(trans),
&nft_trans_elem(trans),
te = (struct nft_trans_elem *)trans->data;
nf_tables_setelem_notify(&trans->ctx, te->set,
&te->elem,
NFT_MSG_DELSETELEM, 0);
set = nft_trans_elem_set(trans);
set->ops->get(set, &nft_trans_elem(trans));
set->ops->remove(set, &nft_trans_elem(trans));
te->set->ops->get(te->set, &te->elem);
te->set->ops->remove(te->set, &te->elem);
nft_data_uninit(&te->elem.key, NFT_DATA_VALUE);
if (te->elem.flags & NFT_SET_MAP) {
nft_data_uninit(&te->elem.data,
te->set->dtype);
}
nft_trans_destroy(trans);
break;
}
Expand Down
47 changes: 12 additions & 35 deletions net/netfilter/x_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,14 @@ static const char *const xt_prefix[NFPROTO_NUMPROTO] = {
static const unsigned int xt_jumpstack_multiplier = 2;

/* Registration hooks for targets. */
int
xt_register_target(struct xt_target *target)
int xt_register_target(struct xt_target *target)
{
u_int8_t af = target->family;
int ret;

ret = mutex_lock_interruptible(&xt[af].mutex);
if (ret != 0)
return ret;
mutex_lock(&xt[af].mutex);
list_add(&target->list, &xt[af].target);
mutex_unlock(&xt[af].mutex);
return ret;
return 0;
}
EXPORT_SYMBOL(xt_register_target);

Expand Down Expand Up @@ -125,20 +121,14 @@ xt_unregister_targets(struct xt_target *target, unsigned int n)
}
EXPORT_SYMBOL(xt_unregister_targets);

int
xt_register_match(struct xt_match *match)
int xt_register_match(struct xt_match *match)
{
u_int8_t af = match->family;
int ret;

ret = mutex_lock_interruptible(&xt[af].mutex);
if (ret != 0)
return ret;

mutex_lock(&xt[af].mutex);
list_add(&match->list, &xt[af].match);
mutex_unlock(&xt[af].mutex);

return ret;
return 0;
}
EXPORT_SYMBOL(xt_register_match);

Expand Down Expand Up @@ -194,9 +184,7 @@ struct xt_match *xt_find_match(u8 af, const char *name, u8 revision)
struct xt_match *m;
int err = -ENOENT;

if (mutex_lock_interruptible(&xt[af].mutex) != 0)
return ERR_PTR(-EINTR);

mutex_lock(&xt[af].mutex);
list_for_each_entry(m, &xt[af].match, list) {
if (strcmp(m->name, name) == 0) {
if (m->revision == revision) {
Expand Down Expand Up @@ -239,9 +227,7 @@ struct xt_target *xt_find_target(u8 af, const char *name, u8 revision)
struct xt_target *t;
int err = -ENOENT;

if (mutex_lock_interruptible(&xt[af].mutex) != 0)
return ERR_PTR(-EINTR);

mutex_lock(&xt[af].mutex);
list_for_each_entry(t, &xt[af].target, list) {
if (strcmp(t->name, name) == 0) {
if (t->revision == revision) {
Expand Down Expand Up @@ -323,10 +309,7 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target,
{
int have_rev, best = -1;

if (mutex_lock_interruptible(&xt[af].mutex) != 0) {
*err = -EINTR;
return 1;
}
mutex_lock(&xt[af].mutex);
if (target == 1)
have_rev = target_revfn(af, name, revision, &best);
else
Expand Down Expand Up @@ -732,9 +715,7 @@ struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
{
struct xt_table *t;

if (mutex_lock_interruptible(&xt[af].mutex) != 0)
return ERR_PTR(-EINTR);

mutex_lock(&xt[af].mutex);
list_for_each_entry(t, &net->xt.tables[af], list)
if (strcmp(t->name, name) == 0 && try_module_get(t->me))
return t;
Expand Down Expand Up @@ -883,10 +864,7 @@ struct xt_table *xt_register_table(struct net *net,
goto out;
}

ret = mutex_lock_interruptible(&xt[table->af].mutex);
if (ret != 0)
goto out_free;

mutex_lock(&xt[table->af].mutex);
/* Don't autoload: we'd eat our tail... */
list_for_each_entry(t, &net->xt.tables[table->af], list) {
if (strcmp(t->name, table->name) == 0) {
Expand All @@ -911,9 +889,8 @@ struct xt_table *xt_register_table(struct net *net,
mutex_unlock(&xt[table->af].mutex);
return table;

unlock:
unlock:
mutex_unlock(&xt[table->af].mutex);
out_free:
kfree(table);
out:
return ERR_PTR(ret);
Expand Down

0 comments on commit f00439e

Please sign in to comment.