diff options
| author | Patrick McHardy <kaber@trash.net> | 2014-01-09 13:42:36 -0500 |
|---|---|---|
| committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-01-09 14:17:14 -0500 |
| commit | 93b0806f006b8b3ecb7a6183fcad21e88f39904f (patch) | |
| tree | 14877bc234ea4ebbb3f36fa1d0f0b91d4f74c9eb /net | |
| parent | 88ce65a71c39901494eb2f1393856bff8ba0158d (diff) | |
netfilter: nf_tables: replay request after dropping locks to load chain type
To avoid races, we need to replay to request after dropping the nfnl_mutex
to auto-load the chain type module.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
| -rw-r--r-- | net/netfilter/nf_tables_api.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index d913fb0ab0aa..7d6a2264ae0a 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -147,16 +147,20 @@ nf_tables_chain_type_lookup(const struct nft_af_info *afi, | |||
| 147 | struct nf_chain_type *type; | 147 | struct nf_chain_type *type; |
| 148 | 148 | ||
| 149 | type = __nf_tables_chain_type_lookup(afi->family, nla); | 149 | type = __nf_tables_chain_type_lookup(afi->family, nla); |
| 150 | if (type != NULL) | ||
| 151 | return type; | ||
| 150 | #ifdef CONFIG_MODULES | 152 | #ifdef CONFIG_MODULES |
| 151 | if (type == NULL && autoload) { | 153 | if (autoload) { |
| 152 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); | 154 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); |
| 153 | request_module("nft-chain-%u-%*.s", afi->family, | 155 | request_module("nft-chain-%u-%*.s", afi->family, |
| 154 | nla_len(nla)-1, (const char *)nla_data(nla)); | 156 | nla_len(nla)-1, (const char *)nla_data(nla)); |
| 155 | nfnl_lock(NFNL_SUBSYS_NFTABLES); | 157 | nfnl_lock(NFNL_SUBSYS_NFTABLES); |
| 156 | type = __nf_tables_chain_type_lookup(afi->family, nla); | 158 | type = __nf_tables_chain_type_lookup(afi->family, nla); |
| 159 | if (type != NULL) | ||
| 160 | return ERR_PTR(-EAGAIN); | ||
| 157 | } | 161 | } |
| 158 | #endif | 162 | #endif |
| 159 | return type; | 163 | return ERR_PTR(-ENOENT); |
| 160 | } | 164 | } |
| 161 | 165 | ||
| 162 | static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = { | 166 | static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = { |
| @@ -906,8 +910,8 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 906 | type = nf_tables_chain_type_lookup(afi, | 910 | type = nf_tables_chain_type_lookup(afi, |
| 907 | nla[NFTA_CHAIN_TYPE], | 911 | nla[NFTA_CHAIN_TYPE], |
| 908 | create); | 912 | create); |
| 909 | if (type == NULL) | 913 | if (IS_ERR(type)) |
| 910 | return -ENOENT; | 914 | return PTR_ERR(type); |
| 911 | } | 915 | } |
| 912 | 916 | ||
| 913 | err = nla_parse_nested(ha, NFTA_HOOK_MAX, nla[NFTA_CHAIN_HOOK], | 917 | err = nla_parse_nested(ha, NFTA_HOOK_MAX, nla[NFTA_CHAIN_HOOK], |
