mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-01-17 16:37:41 -05:00
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/20240328031855.2063-1-pablo@netfilter.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@@ -329,6 +329,7 @@ config NFT_COMPAT_ARP
|
||||
config IP_NF_ARPFILTER
|
||||
tristate "arptables-legacy packet filtering support"
|
||||
select IP_NF_ARPTABLES
|
||||
select NETFILTER_FAMILY_ARP
|
||||
depends on NETFILTER_XTABLES
|
||||
help
|
||||
ARP packet filtering defines a table `filter', which has a series of
|
||||
|
||||
@@ -1200,6 +1200,25 @@ static void nf_tables_table_disable(struct net *net, struct nft_table *table)
|
||||
__NFT_TABLE_F_WAS_AWAKEN | \
|
||||
__NFT_TABLE_F_WAS_ORPHAN)
|
||||
|
||||
static bool nft_table_pending_update(const struct nft_ctx *ctx)
|
||||
{
|
||||
struct nftables_pernet *nft_net = nft_pernet(ctx->net);
|
||||
struct nft_trans *trans;
|
||||
|
||||
if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
|
||||
return true;
|
||||
|
||||
list_for_each_entry(trans, &nft_net->commit_list, list) {
|
||||
if ((trans->msg_type == NFT_MSG_NEWCHAIN ||
|
||||
trans->msg_type == NFT_MSG_DELCHAIN) &&
|
||||
trans->ctx.table == ctx->table &&
|
||||
nft_trans_chain_update(trans))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int nf_tables_updtable(struct nft_ctx *ctx)
|
||||
{
|
||||
struct nft_trans *trans;
|
||||
@@ -1226,7 +1245,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* No dormant off/on/off/on games in single transaction */
|
||||
if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
|
||||
if (nft_table_pending_update(ctx))
|
||||
return -EINVAL;
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
if (table->flags & __NFT_TABLE_F_UPDATE &&
|
||||
!list_empty(&hook.list)) {
|
||||
NL_SET_BAD_ATTR(extack, attr);
|
||||
err = -EOPNOTSUPP;
|
||||
goto err_hooks;
|
||||
}
|
||||
|
||||
if (!(table->flags & NFT_TABLE_F_DORMANT) &&
|
||||
nft_is_base_chain(chain) &&
|
||||
!list_empty(&hook.list)) {
|
||||
@@ -2860,6 +2886,9 @@ static int nft_delchain_hook(struct nft_ctx *ctx,
|
||||
struct nft_trans *trans;
|
||||
int err;
|
||||
|
||||
if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = nft_chain_parse_hook(ctx->net, basechain, nla, &chain_hook,
|
||||
ctx->family, chain->flags, extack);
|
||||
if (err < 0)
|
||||
@@ -2944,7 +2973,8 @@ static int nf_tables_delchain(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, chain, nla);
|
||||
|
||||
if (nla[NFTA_CHAIN_HOOK]) {
|
||||
if (chain->flags & NFT_CHAIN_HW_OFFLOAD)
|
||||
if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYCHAIN ||
|
||||
chain->flags & NFT_CHAIN_HW_OFFLOAD)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (nft_is_base_chain(chain)) {
|
||||
@@ -10182,9 +10212,11 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
||||
if (nft_trans_chain_update(trans)) {
|
||||
nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN,
|
||||
&nft_trans_chain_hooks(trans));
|
||||
nft_netdev_unregister_hooks(net,
|
||||
&nft_trans_chain_hooks(trans),
|
||||
true);
|
||||
if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT)) {
|
||||
nft_netdev_unregister_hooks(net,
|
||||
&nft_trans_chain_hooks(trans),
|
||||
true);
|
||||
}
|
||||
} else {
|
||||
nft_chain_del(trans->ctx.chain);
|
||||
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)
|
||||
break;
|
||||
case NFT_MSG_NEWCHAIN:
|
||||
if (nft_trans_chain_update(trans)) {
|
||||
nft_netdev_unregister_hooks(net,
|
||||
&nft_trans_chain_hooks(trans),
|
||||
true);
|
||||
if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT)) {
|
||||
nft_netdev_unregister_hooks(net,
|
||||
&nft_trans_chain_hooks(trans),
|
||||
true);
|
||||
}
|
||||
free_percpu(nft_trans_chain_stats(trans));
|
||||
kfree(nft_trans_chain_name(trans));
|
||||
nft_trans_destroy(trans);
|
||||
|
||||
Reference in New Issue
Block a user