Commit 2a43ecf9 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso

netfilter: nf_tables: avoid global info storage

This works because all accesses are currently serialized by nfnl
nf_tables subsys mutex.

If we want to have per-netns locking, we need to make this scratch
area pernetns or allocate it on demand.

This does the latter, its ~28kbyte but we can fallback to vmalloc
so it should be fine.
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent be2ab5b4
...@@ -2454,8 +2454,6 @@ static int nft_table_validate(struct net *net, const struct nft_table *table) ...@@ -2454,8 +2454,6 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
#define NFT_RULE_MAXEXPRS 128 #define NFT_RULE_MAXEXPRS 128
static struct nft_expr_info *info;
static int nf_tables_newrule(struct net *net, struct sock *nlsk, static int nf_tables_newrule(struct net *net, struct sock *nlsk,
struct sk_buff *skb, const struct nlmsghdr *nlh, struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const nla[], const struct nlattr * const nla[],
...@@ -2463,6 +2461,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, ...@@ -2463,6 +2461,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
{ {
const struct nfgenmsg *nfmsg = nlmsg_data(nlh); const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
u8 genmask = nft_genmask_next(net); u8 genmask = nft_genmask_next(net);
struct nft_expr_info *info = NULL;
int family = nfmsg->nfgen_family; int family = nfmsg->nfgen_family;
struct nft_table *table; struct nft_table *table;
struct nft_chain *chain; struct nft_chain *chain;
...@@ -2533,6 +2532,12 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, ...@@ -2533,6 +2532,12 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
n = 0; n = 0;
size = 0; size = 0;
if (nla[NFTA_RULE_EXPRESSIONS]) { if (nla[NFTA_RULE_EXPRESSIONS]) {
info = kvmalloc_array(NFT_RULE_MAXEXPRS,
sizeof(struct nft_expr_info),
GFP_KERNEL);
if (!info)
return -ENOMEM;
nla_for_each_nested(tmp, nla[NFTA_RULE_EXPRESSIONS], rem) { nla_for_each_nested(tmp, nla[NFTA_RULE_EXPRESSIONS], rem) {
err = -EINVAL; err = -EINVAL;
if (nla_type(tmp) != NFTA_LIST_ELEM) if (nla_type(tmp) != NFTA_LIST_ELEM)
...@@ -2625,6 +2630,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, ...@@ -2625,6 +2630,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
list_add_rcu(&rule->list, &chain->rules); list_add_rcu(&rule->list, &chain->rules);
} }
} }
kvfree(info);
chain->use++; chain->use++;
if (net->nft.validate_state == NFT_VALIDATE_DO) if (net->nft.validate_state == NFT_VALIDATE_DO)
...@@ -2638,6 +2644,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, ...@@ -2638,6 +2644,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
if (info[i].ops != NULL) if (info[i].ops != NULL)
module_put(info[i].ops->type->owner); module_put(info[i].ops->type->owner);
} }
kvfree(info);
return err; return err;
} }
...@@ -7203,29 +7210,19 @@ static int __init nf_tables_module_init(void) ...@@ -7203,29 +7210,19 @@ static int __init nf_tables_module_init(void)
nft_chain_filter_init(); nft_chain_filter_init();
info = kmalloc_array(NFT_RULE_MAXEXPRS, sizeof(struct nft_expr_info),
GFP_KERNEL);
if (info == NULL) {
err = -ENOMEM;
goto err1;
}
err = nf_tables_core_module_init(); err = nf_tables_core_module_init();
if (err < 0) if (err < 0)
goto err2; return err;
err = nfnetlink_subsys_register(&nf_tables_subsys); err = nfnetlink_subsys_register(&nf_tables_subsys);
if (err < 0) if (err < 0)
goto err3; goto err;
register_netdevice_notifier(&nf_tables_flowtable_notifier); register_netdevice_notifier(&nf_tables_flowtable_notifier);
return register_pernet_subsys(&nf_tables_net_ops); return register_pernet_subsys(&nf_tables_net_ops);
err3: err:
nf_tables_core_module_exit(); nf_tables_core_module_exit();
err2:
kfree(info);
err1:
return err; return err;
} }
...@@ -7237,7 +7234,6 @@ static void __exit nf_tables_module_exit(void) ...@@ -7237,7 +7234,6 @@ static void __exit nf_tables_module_exit(void)
unregister_pernet_subsys(&nf_tables_net_ops); unregister_pernet_subsys(&nf_tables_net_ops);
rcu_barrier(); rcu_barrier();
nf_tables_core_module_exit(); nf_tables_core_module_exit();
kfree(info);
} }
module_init(nf_tables_module_init); module_init(nf_tables_module_init);
......
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