Skip to content

Commit 452238e

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: nf_tables: add and use helper for module autoload
module autoload is problematic, it requires dropping the mutex that protects the transaction. Once the mutex has been dropped, another client can start a new transaction before we had a chance to abort current transaction log. This helper makes sure we first zap the transaction log, then drop mutex for module autoload. In case autload is successful, the caller has to reply entire message anyway. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent 440534d commit 452238e

File tree

1 file changed

+52
-29
lines changed

1 file changed

+52
-29
lines changed

net/netfilter/nf_tables_api.c

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -455,8 +455,40 @@ __nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family)
455455
return NULL;
456456
}
457457

458+
/*
459+
* Loading a module requires dropping mutex that guards the
460+
* transaction.
461+
* We first need to abort any pending transactions as once
462+
* mutex is unlocked a different client could start a new
463+
* transaction. It must not see any 'future generation'
464+
* changes * as these changes will never happen.
465+
*/
466+
#ifdef CONFIG_MODULES
467+
static int __nf_tables_abort(struct net *net);
468+
469+
static void nft_request_module(struct net *net, const char *fmt, ...)
470+
{
471+
char module_name[MODULE_NAME_LEN];
472+
va_list args;
473+
int ret;
474+
475+
__nf_tables_abort(net);
476+
477+
va_start(args, fmt);
478+
ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
479+
va_end(args);
480+
if (WARN(ret >= MODULE_NAME_LEN, "truncated: '%s' (len %d)", module_name, ret))
481+
return;
482+
483+
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
484+
request_module("%s", module_name);
485+
nfnl_lock(NFNL_SUBSYS_NFTABLES);
486+
}
487+
#endif
488+
458489
static const struct nft_chain_type *
459-
nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family, bool autoload)
490+
nf_tables_chain_type_lookup(struct net *net, const struct nlattr *nla,
491+
u8 family, bool autoload)
460492
{
461493
const struct nft_chain_type *type;
462494

@@ -465,10 +497,8 @@ nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family, bool autoload)
465497
return type;
466498
#ifdef CONFIG_MODULES
467499
if (autoload) {
468-
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
469-
request_module("nft-chain-%u-%.*s", family,
470-
nla_len(nla), (const char *)nla_data(nla));
471-
nfnl_lock(NFNL_SUBSYS_NFTABLES);
500+
nft_request_module(net, "nft-chain-%u-%.*s", family,
501+
nla_len(nla), (const char *)nla_data(nla));
472502
type = __nf_tables_chain_type_lookup(nla, family);
473503
if (type != NULL)
474504
return ERR_PTR(-EAGAIN);
@@ -1412,7 +1442,7 @@ static int nft_chain_parse_hook(struct net *net,
14121442

14131443
type = chain_type[family][NFT_CHAIN_T_DEFAULT];
14141444
if (nla[NFTA_CHAIN_TYPE]) {
1415-
type = nf_tables_chain_type_lookup(nla[NFTA_CHAIN_TYPE],
1445+
type = nf_tables_chain_type_lookup(net, nla[NFTA_CHAIN_TYPE],
14161446
family, create);
14171447
if (IS_ERR(type))
14181448
return PTR_ERR(type);
@@ -1875,7 +1905,8 @@ static const struct nft_expr_type *__nft_expr_type_get(u8 family,
18751905
return NULL;
18761906
}
18771907

1878-
static const struct nft_expr_type *nft_expr_type_get(u8 family,
1908+
static const struct nft_expr_type *nft_expr_type_get(struct net *net,
1909+
u8 family,
18791910
struct nlattr *nla)
18801911
{
18811912
const struct nft_expr_type *type;
@@ -1889,17 +1920,13 @@ static const struct nft_expr_type *nft_expr_type_get(u8 family,
18891920

18901921
#ifdef CONFIG_MODULES
18911922
if (type == NULL) {
1892-
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1893-
request_module("nft-expr-%u-%.*s", family,
1894-
nla_len(nla), (char *)nla_data(nla));
1895-
nfnl_lock(NFNL_SUBSYS_NFTABLES);
1923+
nft_request_module(net, "nft-expr-%u-%.*s", family,
1924+
nla_len(nla), (char *)nla_data(nla));
18961925
if (__nft_expr_type_get(family, nla))
18971926
return ERR_PTR(-EAGAIN);
18981927

1899-
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1900-
request_module("nft-expr-%.*s",
1901-
nla_len(nla), (char *)nla_data(nla));
1902-
nfnl_lock(NFNL_SUBSYS_NFTABLES);
1928+
nft_request_module(net, "nft-expr-%.*s",
1929+
nla_len(nla), (char *)nla_data(nla));
19031930
if (__nft_expr_type_get(family, nla))
19041931
return ERR_PTR(-EAGAIN);
19051932
}
@@ -1968,7 +1995,7 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx,
19681995
if (err < 0)
19691996
return err;
19701997

1971-
type = nft_expr_type_get(ctx->family, tb[NFTA_EXPR_NAME]);
1998+
type = nft_expr_type_get(ctx->net, ctx->family, tb[NFTA_EXPR_NAME]);
19721999
if (IS_ERR(type))
19732000
return PTR_ERR(type);
19742001

@@ -2744,9 +2771,7 @@ nft_select_set_ops(const struct nft_ctx *ctx,
27442771

27452772
#ifdef CONFIG_MODULES
27462773
if (list_empty(&nf_tables_set_types)) {
2747-
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
2748-
request_module("nft-set");
2749-
nfnl_lock(NFNL_SUBSYS_NFTABLES);
2774+
nft_request_module(ctx->net, "nft-set");
27502775
if (!list_empty(&nf_tables_set_types))
27512776
return ERR_PTR(-EAGAIN);
27522777
}
@@ -4779,7 +4804,8 @@ static const struct nft_object_type *__nft_obj_type_get(u32 objtype)
47794804
return NULL;
47804805
}
47814806

4782-
static const struct nft_object_type *nft_obj_type_get(u32 objtype)
4807+
static const struct nft_object_type *
4808+
nft_obj_type_get(struct net *net, u32 objtype)
47834809
{
47844810
const struct nft_object_type *type;
47854811

@@ -4789,9 +4815,7 @@ static const struct nft_object_type *nft_obj_type_get(u32 objtype)
47894815

47904816
#ifdef CONFIG_MODULES
47914817
if (type == NULL) {
4792-
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
4793-
request_module("nft-obj-%u", objtype);
4794-
nfnl_lock(NFNL_SUBSYS_NFTABLES);
4818+
nft_request_module(net, "nft-obj-%u", objtype);
47954819
if (__nft_obj_type_get(objtype))
47964820
return ERR_PTR(-EAGAIN);
47974821
}
@@ -4843,7 +4867,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
48434867

48444868
nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
48454869

4846-
type = nft_obj_type_get(objtype);
4870+
type = nft_obj_type_get(net, objtype);
48474871
if (IS_ERR(type))
48484872
return PTR_ERR(type);
48494873

@@ -5339,7 +5363,8 @@ static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family)
53395363
return NULL;
53405364
}
53415365

5342-
static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family)
5366+
static const struct nf_flowtable_type *
5367+
nft_flowtable_type_get(struct net *net, u8 family)
53435368
{
53445369
const struct nf_flowtable_type *type;
53455370

@@ -5349,9 +5374,7 @@ static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family)
53495374

53505375
#ifdef CONFIG_MODULES
53515376
if (type == NULL) {
5352-
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
5353-
request_module("nf-flowtable-%u", family);
5354-
nfnl_lock(NFNL_SUBSYS_NFTABLES);
5377+
nft_request_module(net, "nf-flowtable-%u", family);
53555378
if (__nft_flowtable_type_get(family))
53565379
return ERR_PTR(-EAGAIN);
53575380
}
@@ -5431,7 +5454,7 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
54315454
goto err1;
54325455
}
54335456

5434-
type = nft_flowtable_type_get(family);
5457+
type = nft_flowtable_type_get(net, family);
54355458
if (IS_ERR(type)) {
54365459
err = PTR_ERR(type);
54375460
goto err2;

0 commit comments

Comments
 (0)