Skip to content

Commit 005e528

Browse files
author
Paolo Abeni
committed
Merge tag 'nf-24-03-28' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: Patch #1 reject destroy chain command to delete device hooks in netdev family, hence, only delchain commands are allowed. Patch #2 reject table flag update interference with netdev basechain hook updates, this can leave hooks in inconsistent registration/unregistration state. Patch #3 do not unregister netdev basechain hooks if table is dormant. Otherwise, splat with double unregistration is possible. Patch #4 fixes Kconfig to allow to restore IP_NF_ARPTABLES, from Kuniyuki Iwashima. There are a more fixes still in progress on my side that need more work. * tag 'nf-24-03-28' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: arptables: Select NETFILTER_FAMILY_ARP when building arp_tables.c netfilter: nf_tables: skip netdev hook unregistration if table is dormant netfilter: nf_tables: reject table flag and netdev basechain updates netfilter: nf_tables: reject destroy command to remove basechain hooks ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 7e6f4b2 + 15fba56 commit 005e528

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

net/ipv4/netfilter/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ config NFT_COMPAT_ARP
329329
config IP_NF_ARPFILTER
330330
tristate "arptables-legacy packet filtering support"
331331
select IP_NF_ARPTABLES
332+
select NETFILTER_FAMILY_ARP
332333
depends on NETFILTER_XTABLES
333334
help
334335
ARP packet filtering defines a table `filter', which has a series of

net/netfilter/nf_tables_api.c

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,25 @@ static void nf_tables_table_disable(struct net *net, struct nft_table *table)
12001200
__NFT_TABLE_F_WAS_AWAKEN | \
12011201
__NFT_TABLE_F_WAS_ORPHAN)
12021202

1203+
static bool nft_table_pending_update(const struct nft_ctx *ctx)
1204+
{
1205+
struct nftables_pernet *nft_net = nft_pernet(ctx->net);
1206+
struct nft_trans *trans;
1207+
1208+
if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
1209+
return true;
1210+
1211+
list_for_each_entry(trans, &nft_net->commit_list, list) {
1212+
if ((trans->msg_type == NFT_MSG_NEWCHAIN ||
1213+
trans->msg_type == NFT_MSG_DELCHAIN) &&
1214+
trans->ctx.table == ctx->table &&
1215+
nft_trans_chain_update(trans))
1216+
return true;
1217+
}
1218+
1219+
return false;
1220+
}
1221+
12031222
static int nf_tables_updtable(struct nft_ctx *ctx)
12041223
{
12051224
struct nft_trans *trans;
@@ -1226,7 +1245,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
12261245
return -EOPNOTSUPP;
12271246

12281247
/* No dormant off/on/off/on games in single transaction */
1229-
if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
1248+
if (nft_table_pending_update(ctx))
12301249
return -EINVAL;
12311250

12321251
trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE,
@@ -2631,6 +2650,13 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
26312650
}
26322651
}
26332652

2653+
if (table->flags & __NFT_TABLE_F_UPDATE &&
2654+
!list_empty(&hook.list)) {
2655+
NL_SET_BAD_ATTR(extack, attr);
2656+
err = -EOPNOTSUPP;
2657+
goto err_hooks;
2658+
}
2659+
26342660
if (!(table->flags & NFT_TABLE_F_DORMANT) &&
26352661
nft_is_base_chain(chain) &&
26362662
!list_empty(&hook.list)) {
@@ -2860,6 +2886,9 @@ static int nft_delchain_hook(struct nft_ctx *ctx,
28602886
struct nft_trans *trans;
28612887
int err;
28622888

2889+
if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
2890+
return -EOPNOTSUPP;
2891+
28632892
err = nft_chain_parse_hook(ctx->net, basechain, nla, &chain_hook,
28642893
ctx->family, chain->flags, extack);
28652894
if (err < 0)
@@ -2944,7 +2973,8 @@ static int nf_tables_delchain(struct sk_buff *skb, const struct nfnl_info *info,
29442973
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, chain, nla);
29452974

29462975
if (nla[NFTA_CHAIN_HOOK]) {
2947-
if (chain->flags & NFT_CHAIN_HW_OFFLOAD)
2976+
if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYCHAIN ||
2977+
chain->flags & NFT_CHAIN_HW_OFFLOAD)
29482978
return -EOPNOTSUPP;
29492979

29502980
if (nft_is_base_chain(chain)) {
@@ -10182,9 +10212,11 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
1018210212
if (nft_trans_chain_update(trans)) {
1018310213
nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN,
1018410214
&nft_trans_chain_hooks(trans));
10185-
nft_netdev_unregister_hooks(net,
10186-
&nft_trans_chain_hooks(trans),
10187-
true);
10215+
if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT)) {
10216+
nft_netdev_unregister_hooks(net,
10217+
&nft_trans_chain_hooks(trans),
10218+
true);
10219+
}
1018810220
} else {
1018910221
nft_chain_del(trans->ctx.chain);
1019010222
nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN,
@@ -10460,9 +10492,11 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
1046010492
break;
1046110493
case NFT_MSG_NEWCHAIN:
1046210494
if (nft_trans_chain_update(trans)) {
10463-
nft_netdev_unregister_hooks(net,
10464-
&nft_trans_chain_hooks(trans),
10465-
true);
10495+
if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT)) {
10496+
nft_netdev_unregister_hooks(net,
10497+
&nft_trans_chain_hooks(trans),
10498+
true);
10499+
}
1046610500
free_percpu(nft_trans_chain_stats(trans));
1046710501
kfree(nft_trans_chain_name(trans));
1046810502
nft_trans_destroy(trans);

0 commit comments

Comments
 (0)