Commit d80e773f authored by David S. Miller's avatar David S. Miller

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

* Use 16-bits offset and length fields instead of 8-bits in the conntrack
  extension to avoid an overflow when many conntrack extension are used,
  from Andrey Vagin.

* Allow to use cgroup match from LOCAL_IN, there is no apparent reason
  for not allowing this, from Alexey Perevalov.

* Fix build of the connlimit match after recent changes to let it scale
  up that result in a divide by zero compilation error in UP, from
  Florian Westphal.

* Move the lock out of the structure connlimit_data to avoid a false
  sharing spotted by Eric Dumazet and Jesper D. Brouer, this needed as
  part of the recent connlimit scalability improvements, also from
  Florian Westphal.

* Add missing module aliases in xt_osf to fix loading of rules using
  this match, from Kirill Tkhai.

* Restrict set names in nf_tables to 15 characters instead of silently
  trimming them off, from me.

* Fix wrong format in nf_tables request module call for chain types,
  spotted by Florian Westphal, patch from me.

* Fix crash in xtables when it fails to copy the counters back to userspace
  after having replaced the table already.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 00aefceb c58dd2dd
...@@ -47,8 +47,8 @@ enum nf_ct_ext_id { ...@@ -47,8 +47,8 @@ enum nf_ct_ext_id {
/* Extensions: optional stuff which isn't permanently in struct. */ /* Extensions: optional stuff which isn't permanently in struct. */
struct nf_ct_ext { struct nf_ct_ext {
struct rcu_head rcu; struct rcu_head rcu;
u8 offset[NF_CT_EXT_NUM]; u16 offset[NF_CT_EXT_NUM];
u8 len; u16 len;
char data[0]; char data[0];
}; };
......
...@@ -1044,10 +1044,9 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl, ...@@ -1044,10 +1044,9 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,
if (repl->num_counters && if (repl->num_counters &&
copy_to_user(repl->counters, counterstmp, copy_to_user(repl->counters, counterstmp,
repl->num_counters * sizeof(struct ebt_counter))) { repl->num_counters * sizeof(struct ebt_counter))) {
ret = -EFAULT; /* Silent error, can't fail, new table is already in place */
net_warn_ratelimited("ebtables: counters copy to user failed while replacing table\n");
} }
else
ret = 0;
/* decrease module count and free resources */ /* decrease module count and free resources */
EBT_ENTRY_ITERATE(table->entries, table->entries_size, EBT_ENTRY_ITERATE(table->entries, table->entries_size,
......
...@@ -1044,8 +1044,10 @@ static int __do_replace(struct net *net, const char *name, ...@@ -1044,8 +1044,10 @@ static int __do_replace(struct net *net, const char *name,
xt_free_table_info(oldinfo); xt_free_table_info(oldinfo);
if (copy_to_user(counters_ptr, counters, if (copy_to_user(counters_ptr, counters,
sizeof(struct xt_counters) * num_counters) != 0) sizeof(struct xt_counters) * num_counters) != 0) {
ret = -EFAULT; /* Silent error, can't fail, new table is already in place */
net_warn_ratelimited("arptables: counters copy to user failed while replacing table\n");
}
vfree(counters); vfree(counters);
xt_table_unlock(t); xt_table_unlock(t);
return ret; return ret;
......
...@@ -1231,8 +1231,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, ...@@ -1231,8 +1231,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
xt_free_table_info(oldinfo); xt_free_table_info(oldinfo);
if (copy_to_user(counters_ptr, counters, if (copy_to_user(counters_ptr, counters,
sizeof(struct xt_counters) * num_counters) != 0) sizeof(struct xt_counters) * num_counters) != 0) {
ret = -EFAULT; /* Silent error, can't fail, new table is already in place */
net_warn_ratelimited("iptables: counters copy to user failed while replacing table\n");
}
vfree(counters); vfree(counters);
xt_table_unlock(t); xt_table_unlock(t);
return ret; return ret;
......
...@@ -1241,8 +1241,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, ...@@ -1241,8 +1241,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
xt_free_table_info(oldinfo); xt_free_table_info(oldinfo);
if (copy_to_user(counters_ptr, counters, if (copy_to_user(counters_ptr, counters,
sizeof(struct xt_counters) * num_counters) != 0) sizeof(struct xt_counters) * num_counters) != 0) {
ret = -EFAULT; /* Silent error, can't fail, new table is already in place */
net_warn_ratelimited("ip6tables: counters copy to user failed while replacing table\n");
}
vfree(counters); vfree(counters);
xt_table_unlock(t); xt_table_unlock(t);
return ret; return ret;
......
...@@ -152,8 +152,8 @@ nf_tables_chain_type_lookup(const struct nft_af_info *afi, ...@@ -152,8 +152,8 @@ nf_tables_chain_type_lookup(const struct nft_af_info *afi,
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
if (autoload) { if (autoload) {
nfnl_unlock(NFNL_SUBSYS_NFTABLES); nfnl_unlock(NFNL_SUBSYS_NFTABLES);
request_module("nft-chain-%u-%*.s", afi->family, request_module("nft-chain-%u-%.*s", afi->family,
nla_len(nla)-1, (const char *)nla_data(nla)); nla_len(nla), (const char *)nla_data(nla));
nfnl_lock(NFNL_SUBSYS_NFTABLES); nfnl_lock(NFNL_SUBSYS_NFTABLES);
type = __nf_tables_chain_type_lookup(afi->family, nla); type = __nf_tables_chain_type_lookup(afi->family, nla);
if (type != NULL) if (type != NULL)
...@@ -1946,7 +1946,8 @@ static const struct nft_set_ops *nft_select_set_ops(const struct nlattr * const ...@@ -1946,7 +1946,8 @@ static const struct nft_set_ops *nft_select_set_ops(const struct nlattr * const
static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = { static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
[NFTA_SET_TABLE] = { .type = NLA_STRING }, [NFTA_SET_TABLE] = { .type = NLA_STRING },
[NFTA_SET_NAME] = { .type = NLA_STRING }, [NFTA_SET_NAME] = { .type = NLA_STRING,
.len = IFNAMSIZ - 1 },
[NFTA_SET_FLAGS] = { .type = NLA_U32 }, [NFTA_SET_FLAGS] = { .type = NLA_U32 },
[NFTA_SET_KEY_TYPE] = { .type = NLA_U32 }, [NFTA_SET_KEY_TYPE] = { .type = NLA_U32 },
[NFTA_SET_KEY_LEN] = { .type = NLA_U32 }, [NFTA_SET_KEY_LEN] = { .type = NLA_U32 },
......
...@@ -54,7 +54,8 @@ static struct xt_match cgroup_mt_reg __read_mostly = { ...@@ -54,7 +54,8 @@ static struct xt_match cgroup_mt_reg __read_mostly = {
.matchsize = sizeof(struct xt_cgroup_info), .matchsize = sizeof(struct xt_cgroup_info),
.me = THIS_MODULE, .me = THIS_MODULE,
.hooks = (1 << NF_INET_LOCAL_OUT) | .hooks = (1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_POST_ROUTING), (1 << NF_INET_POST_ROUTING) |
(1 << NF_INET_LOCAL_IN),
}; };
static int __init cgroup_mt_init(void) static int __init cgroup_mt_init(void)
......
...@@ -32,8 +32,14 @@ ...@@ -32,8 +32,14 @@
#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_conntrack_zones.h>
#define CONNLIMIT_SLOTS 32 #define CONNLIMIT_SLOTS 256U
#define CONNLIMIT_LOCK_SLOTS 32
#ifdef CONFIG_LOCKDEP
#define CONNLIMIT_LOCK_SLOTS 8U
#else
#define CONNLIMIT_LOCK_SLOTS 256U
#endif
#define CONNLIMIT_GC_MAX_NODES 8 #define CONNLIMIT_GC_MAX_NODES 8
/* we will save the tuples of all connections we care about */ /* we will save the tuples of all connections we care about */
...@@ -49,10 +55,11 @@ struct xt_connlimit_rb { ...@@ -49,10 +55,11 @@ struct xt_connlimit_rb {
union nf_inet_addr addr; /* search key */ union nf_inet_addr addr; /* search key */
}; };
static spinlock_t xt_connlimit_locks[CONNLIMIT_LOCK_SLOTS] __cacheline_aligned_in_smp;
struct xt_connlimit_data { struct xt_connlimit_data {
struct rb_root climit_root4[CONNLIMIT_SLOTS]; struct rb_root climit_root4[CONNLIMIT_SLOTS];
struct rb_root climit_root6[CONNLIMIT_SLOTS]; struct rb_root climit_root6[CONNLIMIT_SLOTS];
spinlock_t locks[CONNLIMIT_LOCK_SLOTS];
}; };
static u_int32_t connlimit_rnd __read_mostly; static u_int32_t connlimit_rnd __read_mostly;
...@@ -297,11 +304,11 @@ static int count_them(struct net *net, ...@@ -297,11 +304,11 @@ static int count_them(struct net *net,
root = &data->climit_root4[hash]; root = &data->climit_root4[hash];
} }
spin_lock_bh(&data->locks[hash % CONNLIMIT_LOCK_SLOTS]); spin_lock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]);
count = count_tree(net, root, tuple, addr, mask, family); count = count_tree(net, root, tuple, addr, mask, family);
spin_unlock_bh(&data->locks[hash % CONNLIMIT_LOCK_SLOTS]); spin_unlock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]);
return count; return count;
} }
...@@ -377,9 +384,6 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par) ...@@ -377,9 +384,6 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par)
return -ENOMEM; return -ENOMEM;
} }
for (i = 0; i < ARRAY_SIZE(info->data->locks); ++i)
spin_lock_init(&info->data->locks[i]);
for (i = 0; i < ARRAY_SIZE(info->data->climit_root4); ++i) for (i = 0; i < ARRAY_SIZE(info->data->climit_root4); ++i)
info->data->climit_root4[i] = RB_ROOT; info->data->climit_root4[i] = RB_ROOT;
for (i = 0; i < ARRAY_SIZE(info->data->climit_root6); ++i) for (i = 0; i < ARRAY_SIZE(info->data->climit_root6); ++i)
...@@ -435,11 +439,14 @@ static struct xt_match connlimit_mt_reg __read_mostly = { ...@@ -435,11 +439,14 @@ static struct xt_match connlimit_mt_reg __read_mostly = {
static int __init connlimit_mt_init(void) static int __init connlimit_mt_init(void)
{ {
int ret; int ret, i;
BUILD_BUG_ON(CONNLIMIT_LOCK_SLOTS > CONNLIMIT_SLOTS); BUILD_BUG_ON(CONNLIMIT_LOCK_SLOTS > CONNLIMIT_SLOTS);
BUILD_BUG_ON((CONNLIMIT_SLOTS % CONNLIMIT_LOCK_SLOTS) != 0); BUILD_BUG_ON((CONNLIMIT_SLOTS % CONNLIMIT_LOCK_SLOTS) != 0);
for (i = 0; i < CONNLIMIT_LOCK_SLOTS; ++i)
spin_lock_init(&xt_connlimit_locks[i]);
connlimit_conn_cachep = kmem_cache_create("xt_connlimit_conn", connlimit_conn_cachep = kmem_cache_create("xt_connlimit_conn",
sizeof(struct xt_connlimit_conn), sizeof(struct xt_connlimit_conn),
0, 0, NULL); 0, 0, NULL);
......
...@@ -422,4 +422,6 @@ module_exit(xt_osf_fini); ...@@ -422,4 +422,6 @@ module_exit(xt_osf_fini);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
MODULE_DESCRIPTION("Passive OS fingerprint matching."); MODULE_DESCRIPTION("Passive OS fingerprint matching.");
MODULE_ALIAS("ipt_osf");
MODULE_ALIAS("ip6t_osf");
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF); MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF);
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