From: Greg Kroah-Hartman Date: Thu, 29 May 2025 11:40:50 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v5.4.294~46 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b2df445d07228008bbbdc3813bd9abe620796ebc;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: drm-i915-gvt-fix-unterminated-string-initialization-warning.patch netfilter-nf_tables-do-not-defer-rule-destruction-via-call_rcu.patch netfilter-nf_tables-pass-nft_chain-to-destroy-function-not-nft_ctx.patch netfilter-nf_tables-wait-for-rcu-grace-period-on-net_device-removal.patch --- diff --git a/queue-5.4/drm-i915-gvt-fix-unterminated-string-initialization-warning.patch b/queue-5.4/drm-i915-gvt-fix-unterminated-string-initialization-warning.patch new file mode 100644 index 0000000000..522cb65756 --- /dev/null +++ b/queue-5.4/drm-i915-gvt-fix-unterminated-string-initialization-warning.patch @@ -0,0 +1,63 @@ +From 604141c490f8e7591a80b27dba1000cceadb35c9 Mon Sep 17 00:00:00 2001 +From: Jani Nikula +Date: Thu, 27 Mar 2025 14:47:39 +0200 +Subject: drm/i915/gvt: fix unterminated-string-initialization warning + +From: Jani Nikula + +commit 2e43ae7dd71cd9bb0d1bce1d3306bf77523feb81 upstream. + +Initializing const char opregion_signature[16] = OPREGION_SIGNATURE +(which is "IntelGraphicsMem") drops the NUL termination of the +string. This is intentional, but the compiler doesn't know this. + +Switch to initializing header->signature directly from the string +litaral, with sizeof destination rather than source. We don't treat the +signature as a string other than for initialization; it's really just a +blob of binary data. + +Add a static assert for good measure to cross-check the sizes. + +Reported-by: Kees Cook +Closes: https://lore.kernel.org/r/20250310222355.work.417-kees@kernel.org +Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13934 +Tested-by: Nicolas Chauvet +Tested-by: Damian Tometzki +Cc: stable@vger.kernel.org +Reviewed-by: Zhenyu Wang +Link: https://lore.kernel.org/r/20250327124739.2609656-1-jani.nikula@intel.com +Signed-off-by: Jani Nikula +(cherry picked from commit 4f8207469094bd04aad952258ceb9ff4c77b6bfa) +Signed-off-by: Jani Nikula +[nathan: Move static_assert() to top of function to avoid instance of + -Wdeclaration-after-statement due to lack of b5ec6fd286df] +Signed-off-by: Nathan Chancellor +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/gvt/opregion.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/gvt/opregion.c ++++ b/drivers/gpu/drm/i915/gvt/opregion.c +@@ -223,7 +223,8 @@ int intel_vgpu_init_opregion(struct inte + u8 *buf; + struct opregion_header *header; + struct vbt v; +- const char opregion_signature[16] = OPREGION_SIGNATURE; ++ ++ static_assert(sizeof(header->signature) == sizeof(OPREGION_SIGNATURE) - 1); + + gvt_dbg_core("init vgpu%d opregion\n", vgpu->id); + vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_KERNEL | +@@ -237,8 +238,9 @@ int intel_vgpu_init_opregion(struct inte + /* emulated opregion with VBT mailbox only */ + buf = (u8 *)vgpu_opregion(vgpu)->va; + header = (struct opregion_header *)buf; +- memcpy(header->signature, opregion_signature, +- sizeof(opregion_signature)); ++ ++ memcpy(header->signature, OPREGION_SIGNATURE, sizeof(header->signature)); ++ + header->size = 0x8; + header->opregion_ver = 0x02000000; + header->mboxes = MBOX_VBT; diff --git a/queue-5.4/netfilter-nf_tables-do-not-defer-rule-destruction-via-call_rcu.patch b/queue-5.4/netfilter-nf_tables-do-not-defer-rule-destruction-via-call_rcu.patch new file mode 100644 index 0000000000..ee6a78a4a2 --- /dev/null +++ b/queue-5.4/netfilter-nf_tables-do-not-defer-rule-destruction-via-call_rcu.patch @@ -0,0 +1,152 @@ +From pablo@netfilter.org Thu May 29 11:11:54 2025 +From: Pablo Neira Ayuso +Date: Thu, 29 May 2025 11:11:44 +0200 +Subject: netfilter: nf_tables: do not defer rule destruction via call_rcu +To: netfilter-devel@vger.kernel.org +Cc: gregkh@linuxfoundation.org, sashal@kernel.org, stable@vger.kernel.org +Message-ID: <20250529091144.118355-4-pablo@netfilter.org> + +From: Florian Westphal + +commit b04df3da1b5c6f6dc7cdccc37941740c078c4043 upstream. + +nf_tables_chain_destroy can sleep, it can't be used from call_rcu +callbacks. + +Moreover, nf_tables_rule_release() is only safe for error unwinding, +while transaction mutex is held and the to-be-desroyed rule was not +exposed to either dataplane or dumps, as it deactives+frees without +the required synchronize_rcu() in-between. + +nft_rule_expr_deactivate() callbacks will change ->use counters +of other chains/sets, see e.g. nft_lookup .deactivate callback, these +must be serialized via transaction mutex. + +Also add a few lockdep asserts to make this more explicit. + +Calling synchronize_rcu() isn't ideal, but fixing this without is hard +and way more intrusive. As-is, we can get: + +WARNING: .. net/netfilter/nf_tables_api.c:5515 nft_set_destroy+0x.. +Workqueue: events nf_tables_trans_destroy_work +RIP: 0010:nft_set_destroy+0x3fe/0x5c0 +Call Trace: + + nf_tables_trans_destroy_work+0x6b7/0xad0 + process_one_work+0x64a/0xce0 + worker_thread+0x613/0x10d0 + +In case the synchronize_rcu becomes an issue, we can explore alternatives. + +One way would be to allocate nft_trans_rule objects + one nft_trans_chain +object, deactivate the rules + the chain and then defer the freeing to the +nft destroy workqueue. We'd still need to keep the synchronize_rcu path as +a fallback to handle -ENOMEM corner cases though. + +Reported-by: syzbot+b26935466701e56cfdc2@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/67478d92.050a0220.253251.0062.GAE@google.com/T/ +Fixes: c03d278fdf35 ("netfilter: nf_tables: wait for rcu grace period on net_device removal") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + include/net/netfilter/nf_tables.h | 3 --- + net/netfilter/nf_tables_api.c | 31 ++++++++++++++----------------- + 2 files changed, 14 insertions(+), 20 deletions(-) + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -899,7 +899,6 @@ struct nft_chain { + u8 flags:6, + genmask:2; + char *name; +- struct rcu_head rcu_head; + + /* Only used during control plane commit phase: */ + struct nft_rule **rules_next; +@@ -1016,7 +1015,6 @@ static inline void nft_use_inc_restore(u + * @sets: sets in the table + * @objects: stateful objects in the table + * @flowtables: flow tables in the table +- * @net: netnamespace this table belongs to + * @hgenerator: handle generator state + * @handle: table handle + * @use: number of chain references to this table +@@ -1032,7 +1030,6 @@ struct nft_table { + struct list_head sets; + struct list_head objects; + struct list_head flowtables; +- possible_net_t net; + u64 hgenerator; + u64 handle; + u32 use; +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -1109,7 +1109,6 @@ static int nf_tables_newtable(struct net + INIT_LIST_HEAD(&table->sets); + INIT_LIST_HEAD(&table->objects); + INIT_LIST_HEAD(&table->flowtables); +- write_pnet(&table->net, net); + table->family = family; + table->flags = flags; + table->handle = ++table_handle; +@@ -2824,6 +2823,8 @@ static void nf_tables_rule_destroy(const + static void nf_tables_rule_release(const struct nft_ctx *ctx, + struct nft_rule *rule) + { ++ lockdep_commit_lock_is_held(ctx->net); ++ + nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE); + nf_tables_rule_destroy(ctx, rule); + } +@@ -4172,6 +4173,8 @@ void nf_tables_deactivate_set(const stru + struct nft_set_binding *binding, + enum nft_trans_phase phase) + { ++ lockdep_commit_lock_is_held(ctx->net); ++ + switch (phase) { + case NFT_TRANS_PREPARE_ERROR: + nft_set_trans_unbind(ctx, set); +@@ -8228,19 +8231,6 @@ static void __nft_release_basechain_now( + nf_tables_chain_destroy(ctx->chain); + } + +-static void nft_release_basechain_rcu(struct rcu_head *head) +-{ +- struct nft_chain *chain = container_of(head, struct nft_chain, rcu_head); +- struct nft_ctx ctx = { +- .family = chain->table->family, +- .chain = chain, +- .net = read_pnet(&chain->table->net), +- }; +- +- __nft_release_basechain_now(&ctx); +- put_net(ctx.net); +-} +- + int __nft_release_basechain(struct nft_ctx *ctx) + { + struct nft_rule *rule; +@@ -8255,11 +8245,18 @@ int __nft_release_basechain(struct nft_c + nft_chain_del(ctx->chain); + nft_use_dec(&ctx->table->use); + +- if (maybe_get_net(ctx->net)) +- call_rcu(&ctx->chain->rcu_head, nft_release_basechain_rcu); +- else ++ if (!maybe_get_net(ctx->net)) { + __nft_release_basechain_now(ctx); ++ return 0; ++ } ++ ++ /* wait for ruleset dumps to complete. Owning chain is no longer in ++ * lists, so new dumps can't find any of these rules anymore. ++ */ ++ synchronize_rcu(); + ++ __nft_release_basechain_now(ctx); ++ put_net(ctx->net); + return 0; + } + EXPORT_SYMBOL_GPL(__nft_release_basechain); diff --git a/queue-5.4/netfilter-nf_tables-pass-nft_chain-to-destroy-function-not-nft_ctx.patch b/queue-5.4/netfilter-nf_tables-pass-nft_chain-to-destroy-function-not-nft_ctx.patch new file mode 100644 index 0000000000..693f7ddc2a --- /dev/null +++ b/queue-5.4/netfilter-nf_tables-pass-nft_chain-to-destroy-function-not-nft_ctx.patch @@ -0,0 +1,88 @@ +From pablo@netfilter.org Thu May 29 11:11:52 2025 +From: Pablo Neira Ayuso +Date: Thu, 29 May 2025 11:11:42 +0200 +Subject: netfilter: nf_tables: pass nft_chain to destroy function, not nft_ctx +To: netfilter-devel@vger.kernel.org +Cc: gregkh@linuxfoundation.org, sashal@kernel.org, stable@vger.kernel.org +Message-ID: <20250529091144.118355-2-pablo@netfilter.org> + +From: Florian Westphal + +commit 8965d42bcf54d42cbc72fe34a9d0ec3f8527debd upstream. + +It would be better to not store nft_ctx inside nft_trans object, +the netlink ctx strucutre is huge and most of its information is +never needed in places that use trans->ctx. + +Avoid/reduce its usage if possible, no runtime behaviour change +intended. + +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/nf_tables_api.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -1675,10 +1675,8 @@ static void nf_tables_chain_free_chain_r + kvfree(chain->rules_next); + } + +-static void nf_tables_chain_destroy(struct nft_ctx *ctx) ++void nf_tables_chain_destroy(struct nft_chain *chain) + { +- struct nft_chain *chain = ctx->chain; +- + if (WARN_ON(chain->use > 0)) + return; + +@@ -1929,7 +1927,7 @@ err2: + err_use: + nf_tables_unregister_hook(net, table, chain); + err1: +- nf_tables_chain_destroy(ctx); ++ nf_tables_chain_destroy(chain); + + return err; + } +@@ -6905,7 +6903,7 @@ static void nft_commit_release(struct nf + kfree(nft_trans_chain_name(trans)); + break; + case NFT_MSG_DELCHAIN: +- nf_tables_chain_destroy(&trans->ctx); ++ nf_tables_chain_destroy(trans->ctx.chain); + break; + case NFT_MSG_DELRULE: + nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); +@@ -7582,7 +7580,7 @@ static void nf_tables_abort_release(stru + nf_tables_table_destroy(&trans->ctx); + break; + case NFT_MSG_NEWCHAIN: +- nf_tables_chain_destroy(&trans->ctx); ++ nf_tables_chain_destroy(trans->ctx.chain); + break; + case NFT_MSG_NEWRULE: + nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); +@@ -8233,7 +8231,7 @@ int __nft_release_basechain(struct nft_c + } + nft_chain_del(ctx->chain); + nft_use_dec(&ctx->table->use); +- nf_tables_chain_destroy(ctx); ++ nf_tables_chain_destroy(ctx->chain); + + return 0; + } +@@ -8300,10 +8298,9 @@ static void __nft_release_table(struct n + nft_obj_destroy(&ctx, obj); + } + list_for_each_entry_safe(chain, nc, &table->chains, list) { +- ctx.chain = chain; + nft_chain_del(chain); + nft_use_dec(&table->use); +- nf_tables_chain_destroy(&ctx); ++ nf_tables_chain_destroy(chain); + } + list_del(&table->list); + nf_tables_table_destroy(&ctx); diff --git a/queue-5.4/netfilter-nf_tables-wait-for-rcu-grace-period-on-net_device-removal.patch b/queue-5.4/netfilter-nf_tables-wait-for-rcu-grace-period-on-net_device-removal.patch new file mode 100644 index 0000000000..4d14b5a903 --- /dev/null +++ b/queue-5.4/netfilter-nf_tables-wait-for-rcu-grace-period-on-net_device-removal.patch @@ -0,0 +1,149 @@ +From pablo@netfilter.org Thu May 29 11:11:54 2025 +From: Pablo Neira Ayuso +Date: Thu, 29 May 2025 11:11:43 +0200 +Subject: netfilter: nf_tables: wait for rcu grace period on net_device removal +To: netfilter-devel@vger.kernel.org +Cc: gregkh@linuxfoundation.org, sashal@kernel.org, stable@vger.kernel.org +Message-ID: <20250529091144.118355-3-pablo@netfilter.org> + +From: Pablo Neira Ayuso + +commit c03d278fdf35e73dd0ec543b9b556876b9d9a8dc upstream. + +8c873e219970 ("netfilter: core: free hooks with call_rcu") removed +synchronize_net() call when unregistering basechain hook, however, +net_device removal event handler for the NFPROTO_NETDEV was not updated +to wait for RCU grace period. + +Note that 835b803377f5 ("netfilter: nf_tables_netdev: unregister hooks +on net_device removal") does not remove basechain rules on device +removal, I was hinted to remove rules on net_device removal later, see +5ebe0b0eec9d ("netfilter: nf_tables: destroy basechain and rules on +netdevice removal"). + +Although NETDEV_UNREGISTER event is guaranteed to be handled after +synchronize_net() call, this path needs to wait for rcu grace period via +rcu callback to release basechain hooks if netns is alive because an +ongoing netlink dump could be in progress (sockets hold a reference on +the netns). + +Note that nf_tables_pre_exit_net() unregisters and releases basechain +hooks but it is possible to see NETDEV_UNREGISTER at a later stage in +the netns exit path, eg. veth peer device in another netns: + + cleanup_net() + default_device_exit_batch() + unregister_netdevice_many_notify() + notifier_call_chain() + nf_tables_netdev_event() + __nft_release_basechain() + +In this particular case, same rule of thumb applies: if netns is alive, +then wait for rcu grace period because netlink dump in the other netns +could be in progress. Otherwise, if the other netns is going away then +no netlink dump can be in progress and basechain hooks can be released +inmediately. + +While at it, turn WARN_ON() into WARN_ON_ONCE() for the basechain +validation, which should not ever happen. + +Fixes: 835b803377f5 ("netfilter: nf_tables_netdev: unregister hooks on net_device removal") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + include/net/netfilter/nf_tables.h | 3 ++ + net/netfilter/nf_tables_api.c | 41 +++++++++++++++++++++++++++++++------- + 2 files changed, 37 insertions(+), 7 deletions(-) + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -899,6 +899,7 @@ struct nft_chain { + u8 flags:6, + genmask:2; + char *name; ++ struct rcu_head rcu_head; + + /* Only used during control plane commit phase: */ + struct nft_rule **rules_next; +@@ -1015,6 +1016,7 @@ static inline void nft_use_inc_restore(u + * @sets: sets in the table + * @objects: stateful objects in the table + * @flowtables: flow tables in the table ++ * @net: netnamespace this table belongs to + * @hgenerator: handle generator state + * @handle: table handle + * @use: number of chain references to this table +@@ -1030,6 +1032,7 @@ struct nft_table { + struct list_head sets; + struct list_head objects; + struct list_head flowtables; ++ possible_net_t net; + u64 hgenerator; + u64 handle; + u32 use; +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -1109,6 +1109,7 @@ static int nf_tables_newtable(struct net + INIT_LIST_HEAD(&table->sets); + INIT_LIST_HEAD(&table->objects); + INIT_LIST_HEAD(&table->flowtables); ++ write_pnet(&table->net, net); + table->family = family; + table->flags = flags; + table->handle = ++table_handle; +@@ -8216,22 +8217,48 @@ int nft_data_dump(struct sk_buff *skb, i + } + EXPORT_SYMBOL_GPL(nft_data_dump); + +-int __nft_release_basechain(struct nft_ctx *ctx) ++static void __nft_release_basechain_now(struct nft_ctx *ctx) + { + struct nft_rule *rule, *nr; + +- if (WARN_ON(!nft_is_base_chain(ctx->chain))) +- return 0; +- +- nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain); + list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) { + list_del(&rule->list); +- nft_use_dec(&ctx->chain->use); + nf_tables_rule_release(ctx, rule); + } ++ nf_tables_chain_destroy(ctx->chain); ++} ++ ++static void nft_release_basechain_rcu(struct rcu_head *head) ++{ ++ struct nft_chain *chain = container_of(head, struct nft_chain, rcu_head); ++ struct nft_ctx ctx = { ++ .family = chain->table->family, ++ .chain = chain, ++ .net = read_pnet(&chain->table->net), ++ }; ++ ++ __nft_release_basechain_now(&ctx); ++ put_net(ctx.net); ++} ++ ++int __nft_release_basechain(struct nft_ctx *ctx) ++{ ++ struct nft_rule *rule; ++ ++ if (WARN_ON_ONCE(!nft_is_base_chain(ctx->chain))) ++ return 0; ++ ++ nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain); ++ list_for_each_entry(rule, &ctx->chain->rules, list) ++ nft_use_dec(&ctx->chain->use); ++ + nft_chain_del(ctx->chain); + nft_use_dec(&ctx->table->use); +- nf_tables_chain_destroy(ctx->chain); ++ ++ if (maybe_get_net(ctx->net)) ++ call_rcu(&ctx->chain->rcu_head, nft_release_basechain_rcu); ++ else ++ __nft_release_basechain_now(ctx); + + return 0; + } diff --git a/queue-5.4/series b/queue-5.4/series index c4a471ca2a..50a58957c8 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -182,3 +182,7 @@ memcg-always-call-cond_resched-after-fn.patch mm-page_alloc.c-avoid-infinite-retries-caused-by-cpuset-race.patch spi-spi-fsl-dspi-restrict-register-range-for-regmap-.patch kbuild-disable-wdefault-const-init-unsafe.patch +netfilter-nf_tables-pass-nft_chain-to-destroy-function-not-nft_ctx.patch +netfilter-nf_tables-wait-for-rcu-grace-period-on-net_device-removal.patch +netfilter-nf_tables-do-not-defer-rule-destruction-via-call_rcu.patch +drm-i915-gvt-fix-unterminated-string-initialization-warning.patch