6.12.111-rc1 review
Subsystems (3)
Greg Kroah-Hartman
maintainerPATCH 1073/1102 ACPI: TAD: Split three functions to untangle runtime PM handling
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Rafael J. Wysocki" <[email protected]>
[ Upstream commit b14b77bbea0a82cb66f1538824783e63d4128510 ]
Move the core functionality of acpi_tad_get_real_time(), acpi_tad_wake_set(), and acpi_tad_wake_read() into separate functions called __acpi_tad_get_real_time(), __acpi_tad_wake_set(), and __acpi_tad_wake_read(), respectively, which can be called from code blocks following a single runtime resume of the device.
This will facilitate adding alarm support to the RTC class device interface of the driver going forward.
No intentional functional impact.
Stable-dep-of: a3df8bbe0a70 ("ACPI: TAD: Add locking around AML evaluations")
--- drivers/acpi/acpi_tad.c | 128 +++++++++++++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 44 deletions(-)
drivers/acpi/acpi_tad.c +84 -44
@@ -111,7 +111,7 @@ static int acpi_tad_set_real_time(structreturn 0 ; } -static int acpi_tad_get_real_time (struct device *dev,struct acpi_tad_rt *rt) +static int acpi_tad_evaluate_grt (struct device *dev,struct acpi_tad_rt *rt) {acpi_handle handle =ACPI_HANDLE (dev);struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER };
@@ -120,12 +120,7 @@ static int acpi_tad_get_real_time(structacpi_status status;int ret = -EIO ; -pm_runtime_get_sync (dev); - status =acpi_evaluate_object (handle,"_GRT" ,NULL , &output); - -pm_runtime_put_sync (dev); -if (ACPI_FAILURE (status)) goto out_free;
@@ -141,11 +136,6 @@ static int acpi_tad_get_real_time(struct goto out_free;memcpy (rt, data,sizeof (*rt)); -if (acpi_tad_rt_is_invalid (rt)) { - ret = -ENODATA ; - goto out_free; - } - ret =0 ; out_free:
@@ -153,6 +143,82 @@ out_free:return ret; } +static int __acpi_tad_get_real_time (struct device *dev,struct acpi_tad_rt *rt) +{ +int ret; + + ret =acpi_tad_evaluate_grt (dev, rt); +if (ret) +return ret; + +if (acpi_tad_rt_is_invalid (rt)) +return -ENODATA ; + +return 0 ; +} + +static int acpi_tad_get_real_time (struct device *dev,struct acpi_tad_rt *rt) +{ +int ret; + +pm_runtime_get_sync (dev); + + ret =__acpi_tad_get_real_time (dev, rt); + +pm_runtime_put_sync (dev); + +return ret; +} + +static int __acpi_tad_wake_set (struct device *dev,char *method,u32 timer_id, +u32 value) +{ +acpi_handle handle =ACPI_HANDLE (dev); +union acpi_object args[] = { + { .type =ACPI_TYPE_INTEGER , }, + { .type =ACPI_TYPE_INTEGER , }, + }; +struct acpi_object_list arg_list = { + .pointer = args, + .count =ARRAY_SIZE (args), + }; +unsigned long long retval; +acpi_status status; + + args[0 ].integer.value = timer_id; + args[1 ].integer.value = value; + + status =acpi_evaluate_integer (handle, method, &arg_list, &retval); +if (ACPI_FAILURE (status) || retval) +return -EIO ; + +return 0 ; +} + +static int __acpi_tad_wake_read (struct device *dev,char *method,u32 timer_id, +unsigned long long *retval) +{ +acpi_handle handle =ACPI_HANDLE (dev); +union acpi_object args[] = { + { .type =ACPI_TYPE_INTEGER , }, + }; +struct acpi_object_list arg_list = { + .pointer = args, + .count =ARRAY_SIZE (args), + }; +acpi_status status; + + args[0 ].integer.value = timer_id; + + status =acpi_evaluate_integer (handle, method, &arg_list, retval); +if (ACPI_FAILURE (status)) +return -EIO ; + +return 0 ; +} + +/* sysfs interface */ +static char *acpi_tad_rt_next_field (char *s,int *val) {char *p;
@@ -265,31 +331,15 @@ static const struct attribute_group acpistatic int acpi_tad_wake_set (struct device *dev,char *method,u32 timer_id,u32 value) { -acpi_handle handle =ACPI_HANDLE (dev); -union acpi_object args[] = { - { .type =ACPI_TYPE_INTEGER , }, - { .type =ACPI_TYPE_INTEGER , }, - }; -struct acpi_object_list arg_list = { - .pointer = args, - .count =ARRAY_SIZE (args), - }; -unsigned long long retval; -acpi_status status; - - args[0 ].integer.value = timer_id; - args[1 ].integer.value = value; +int ret;pm_runtime_get_sync (dev); - status =acpi_evaluate_integer (handle, method, &arg_list, &retval); + ret =__acpi_tad_wake_set (dev, method, timer_id, value);pm_runtime_put_sync (dev); -if (ACPI_FAILURE (status) || retval) -return -EIO ; - -return 0 ; +return ret; } static int acpi_tad_wake_write(struct device *dev, const char *buf, char *method,
@@ -315,27 +365,17 @@ static int acpi_tad_wake_write(struct destatic ssize_t acpi_tad_wake_read (struct device *dev,char *buf,char *method,u32 timer_id,const char *specval) { -acpi_handle handle =ACPI_HANDLE (dev); -union acpi_object args[] = { - { .type =ACPI_TYPE_INTEGER , }, - }; -struct acpi_object_list arg_list = { - .pointer = args, - .count =ARRAY_SIZE (args), - };unsigned long long retval; -acpi_status status; - - args[0 ].integer.value = timer_id; +int ret;pm_runtime_get_sync (dev); - status =acpi_evaluate_integer (handle, method, &arg_list, &retval); + ret =__acpi_tad_wake_read (dev, method, timer_id, &retval);pm_runtime_put_sync (dev); -if (ACPI_FAILURE (status)) -return -EIO ; +if (ret) +return ret;if ((u32 )retval ==ACPI_TAD_WAKE_DISABLED )return sprintf (buf,"%s\n" , specval);
Greg Kroah-Hartman
maintainerPATCH 1074/1102 ACPI: TAD: Add locking around AML evaluations
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Rafael J. Wysocki" <[email protected]>
[ Upstream commit a3df8bbe0a704fa5c1609b9666b594f350558fe0 ]
In the ACPI TAD driver, there are hidden assumptions that the ACPI control methods used by it will not be evaluated concurrently due to ACPICA namespace and interpreter locking.
However, that may not be the case since ACPICA may drop and re-acquire the namespace and interpreter locks during the evaluation of a given object in a few cases, including the one in which the AML in question sleeps causing acpi_ex_system_do_sleep() to be called. In that case, the evaluation of one control method may be started while the evaluation of another one is still in progress.
For this reason, add a global lock to the ACPI TAD driver and acquire it every time before evaluating an ACPI control method, except for the initial evaluation of _GCP in acpi_tad_probe().
--- drivers/acpi/acpi_tad.c | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-)
drivers/acpi/acpi_tad.c +29 -19
@@ -23,6 +23,7 @@#include <linux/acpi.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/suspend.h>
@@ -80,6 +81,8 @@ static bool acpi_tad_rt_is_invalid(struc rt->daylight >3 ; } +static DEFINE_MUTEX (acpi_tad_aml_lock); +static int acpi_tad_set_real_time (struct device *dev,struct acpi_tad_rt *rt) {acpi_handle handle =ACPI_HANDLE (dev);
@@ -101,6 +104,8 @@ static int acpi_tad_set_real_time(structpm_runtime_get_sync (dev); +guard (mutex)(&acpi_tad_aml_lock); + status =acpi_evaluate_integer (handle,"_SRT" , &arg_list, &retval);pm_runtime_put_sync (dev);
@@ -115,30 +120,27 @@ static int acpi_tad_evaluate_grt(struct {acpi_handle handle =ACPI_HANDLE (dev);struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER }; -union acpi_object *out_obj; -struct acpi_tad_rt *data;acpi_status status;int ret = -EIO ; - status =acpi_evaluate_object (handle,"_GRT" ,NULL , &output); -if (ACPI_FAILURE (status)) - goto out_free; - - out_obj = output.pointer; -if (out_obj->type !=ACPI_TYPE_BUFFER ) - goto out_free; - -if (out_obj->buffer.length !=sizeof (*rt)) - goto out_free; - - data = (struct acpi_tad_rt *)(out_obj->buffer.pointer); -if (!data->valid) - goto out_free; +guard (mutex)(&acpi_tad_aml_lock); -memcpy (rt, data,sizeof (*rt)); - ret =0 ; + status =acpi_evaluate_object (handle,"_GRT" ,NULL , &output); +if (ACPI_SUCCESS (status)) { +union acpi_object *out_obj; -out_free: + out_obj = output.pointer; +if (out_obj->type ==ACPI_TYPE_BUFFER && + out_obj->buffer.length ==sizeof (*rt)) { +struct acpi_tad_rt *data; + + data = (struct acpi_tad_rt *)(out_obj->buffer.pointer); +if (data->valid) { +memcpy (rt, data,sizeof (*rt)); + ret =0 ; + } + } + }ACPI_FREE (output.pointer);return ret; }
@@ -188,6 +190,8 @@ static int __acpi_tad_wake_set(struct de args[0 ].integer.value = timer_id; args[1 ].integer.value = value; +guard (mutex)(&acpi_tad_aml_lock); + status =acpi_evaluate_integer (handle, method, &arg_list, &retval);if (ACPI_FAILURE (status) || retval)return -EIO ;
@@ -210,6 +214,8 @@ static int __acpi_tad_wake_read(struct d args[0 ].integer.value = timer_id; +guard (mutex)(&acpi_tad_aml_lock); + status =acpi_evaluate_integer (handle, method, &arg_list, retval);if (ACPI_FAILURE (status))return -EIO ;
@@ -426,6 +432,8 @@ static int acpi_tad_clear_status(structpm_runtime_get_sync (dev); +guard (mutex)(&acpi_tad_aml_lock); + status =acpi_evaluate_integer (handle,"_CWS" , &arg_list, &retval);pm_runtime_put_sync (dev);
@@ -467,6 +475,8 @@ static ssize_t acpi_tad_status_read(strupm_runtime_get_sync (dev); +guard (mutex)(&acpi_tad_aml_lock); + status =acpi_evaluate_integer (handle,"_GWS" , &arg_list, &retval);pm_runtime_put_sync (dev);
Greg Kroah-Hartman
maintainerPATCH 1075/1102 cxl/ras: Fix cxl_rch_get_aer_severity() wrong severity register
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Terry Bowman <[email protected]>
[ Upstream commit 9d399526128bae184b153deab42b49f5f3eea2ed ]
cxl_rch_get_aer_severity() classifies RCH Downstream Port uncorrectable errors as fatal or non-fatal by ANDing uncorrectable status with PCI_ERR_ROOT_FATAL_RCV. This is wrong because PCI_ERR_ROOT_FATAL_RCV is a Root Error Status register bit (bit 6), not a severity bit. ANDing it against uncorrectable status tests a reserved bit and produces incorrect severity classification.
Fix by ANDing the unmasked uncor_status against uncor_severity. Per PCIe Base Spec r6.0 Section 7.8.4.4, each bit in the Uncorrectable Error Severity register indicates whether the corresponding error is fatal (1) or non-fatal (0).
--- drivers/cxl/core/ras_rch.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/cxl/core/ras_rch.c +5 -5
@@ -94,11 +94,11 @@ static bool cxl_rch_get_aer_info(void __static bool cxl_rch_get_aer_severity (struct aer_capability_regs *aer_regs,int *severity) { -if (aer_regs->uncor_status & ~aer_regs->uncor_mask) { -if (aer_regs->uncor_status &PCI_ERR_ROOT_FATAL_RCV ) - *severity =AER_FATAL ; -else - *severity =AER_NONFATAL ; +u32 uncor_status = aer_regs->uncor_status & ~aer_regs->uncor_mask; + +if (uncor_status) { + *severity = (uncor_status & aer_regs->uncor_severity) ? +AER_FATAL :AER_NONFATAL ;return true; }
Greg Kroah-Hartman
maintainerPATCH 1076/1102 ipv6: annotate data-races around devconf->rpl_seg_enabled
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yue Haibing <[email protected]>
[ Upstream commit 3a5f55500f3e93cf4d62351c753452279b088b4b ]
devconf->rpl_seg_enabled can be changed concurrently from /proc/sys/net/ipv6/conf, annotate lockless reads on it.
Stable-dep-of: f826df95332c ("ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()")
--- net/ipv6/exthdrs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
net/ipv6/exthdrs.c +2 -4
@@ -504,10 +504,8 @@ static int ipv6_rpl_srh_rcv(struct sk_bu idev =__in6_dev_get (skb->dev); - accept_rpl_seg = net->ipv6.devconf_all->rpl_seg_enabled; -if (accept_rpl_seg > idev->cnf.rpl_seg_enabled) - accept_rpl_seg = idev->cnf.rpl_seg_enabled; - + accept_rpl_seg =min (READ_ONCE (net->ipv6.devconf_all->rpl_seg_enabled), +READ_ONCE (idev->cnf.rpl_seg_enabled));if (!accept_rpl_seg) {kfree_skb (skb);return -1 ;
Greg Kroah-Hartman
maintainerPATCH 1077/1102 ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrea Mayer <[email protected]>
[ Upstream commit f826df95332c07380206dbd54178b6eefb311aba ]
ipv6_rpl_srh_rcv() dereferences idev from __in6_dev_get() without a NULL check when reading idev->cnf.rpl_seg_enabled.
When the device's MTU drops below IPV6_MIN_MTU, addrconf_ifdown() clears dev->ip6_ptr through RCU_INIT_POINTER(). A packet that passed the idev check in ip6_rcv_core() can then reach ipv6_rpl_srh_rcv() with dev->ip6_ptr already NULL.
Reproduced by flooding the receiving interface with ping6 traffic while flapping its MTU between 1500 and 1200:
BUG: KASAN: null-ptr-deref in ipv6_rpl_srh_rcv+0xb3/0x1070 Read of size 4 at addr 00000000000006b4 by task ping6/394 CPU: 2 UID: 0 PID: 394 Comm: ping6 Not tainted 7.2.0-rc7-micro-vm-dev-00095-g24ef02f934ee #240 PREEMPT(full) Call Trace: <IRQ> kasan_report+0xc6/0x100 ipv6_rpl_srh_rcv+0xb3/0x1070 ip6_protocol_deliver_rcu+0x759/0x9a0 ip6_input_finish+0xa8/0x1b0 ip6_input+0xe1/0x490 ipv6_rcv+0x33d/0x460 __netif_receive_skb_one_core+0xd6/0x130 process_backlog+0x2cc/0xa00 __napi_poll.constprop.0+0x56/0x270 net_rx_action+0x327/0x730 handle_softirqs+0x11e/0x630 do_softirq+0xb3/0xf0 </IRQ>
Both ipv6_rpl_srh_rcv() and ipv6_srh_rcv() are called only from ipv6_rthdr_rcv(), which already has an idev lookup.
Fix the NULL dereference on the RPL path by checking idev in ipv6_rthdr_rcv(), before it calls either function. The callees take idev as an argument and no longer call __in6_dev_get(), so the packet is now dropped in one place, with SKB_DROP_REASON_IPV6DISABLED on both paths.
--- net/ipv6/exthdrs.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-)
net/ipv6/exthdrs.c +12 -14
@@ -371,23 +371,16 @@ static void seg6_update_csum(struct sk_b (__be32 *)addr); } -static int ipv6_srh_rcv (struct sk_buff *skb) +static int ipv6_srh_rcv (struct sk_buff *skb,struct inet6_dev *idev) {struct inet6_skb_parm *opt =IP6CB (skb);struct net *net =dev_net (skb->dev);struct ipv6_sr_hdr *hdr; -struct inet6_dev *idev;struct in6_addr *addr;int accept_seg6; hdr = (struct ipv6_sr_hdr *)skb_transport_header (skb); - idev =__in6_dev_get (skb->dev); -if (!idev) { -kfree_skb (skb); -return -1 ; - } - accept_seg6 =min (READ_ONCE (net->ipv6.devconf_all->seg6_enabled),READ_ONCE (idev->cnf.seg6_enabled));
@@ -488,12 +481,11 @@ looped_back:return -1 ; } -static int ipv6_rpl_srh_rcv (struct sk_buff *skb) +static int ipv6_rpl_srh_rcv (struct sk_buff *skb,struct inet6_dev *idev) {struct ipv6_rpl_sr_hdr *hdr, *ohdr, *chdr;struct inet6_skb_parm *opt =IP6CB (skb);struct net *net =dev_net (skb->dev); -struct inet6_dev *idev;struct ipv6hdr *oldhdr;unsigned int chdr_len;unsigned char *buf;
@@ -502,8 +494,6 @@ static int ipv6_rpl_srh_rcv(struct sk_buu64 n =0 ;u32 r; - idev =__in6_dev_get (skb->dev); - accept_rpl_seg =min (READ_ONCE (net->ipv6.devconf_all->rpl_seg_enabled),READ_ONCE (idev->cnf.rpl_seg_enabled));if (!accept_rpl_seg) {
@@ -692,10 +682,14 @@ static int ipv6_rthdr_rcv(struct sk_buffswitch (hdr->type) {case IPV6_SRCRT_TYPE_4 :/* segment routing */ -return ipv6_srh_rcv (skb); +if (!idev) + goto disabled; +return ipv6_srh_rcv (skb, idev);case IPV6_SRCRT_TYPE_3 :/* rpl segment routing */ -return ipv6_rpl_srh_rcv (skb); +if (!idev) + goto disabled; +return ipv6_rpl_srh_rcv (skb, idev);default :break ; }
@@ -840,6 +834,10 @@ unknown_rh:icmpv6_param_prob (skb,ICMPV6_HDR_FIELD , (&hdr->type) -skb_network_header (skb));return -1 ; + +disabled: +kfree_skb_reason (skb,SKB_DROP_REASON_IPV6DISABLED ); +return -1 ; }static const struct inet6_protocol rthdr_protocol = {
Greg Kroah-Hartman
maintainerPATCH 1078/1102 ipv6: adopt skb_dst_dev() and skb_dst_dev_net[_rcu]() helpers
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 93d1cff35adc522a5d21e722eee1071f3f7dc716 ]
Use the new helpers as a step to deal with potential dst->dev races.
v2: fix typo in ipv6_rthdr_rcv() (kernel test robot <[email protected]>)
Stable-dep-of: e36ce6e78fe3 ("ip: orphan prefetched skbs before multicast forwarding")
--- include/net/inet6_hashtables.h | 2 +- include/net/ip6_tunnel.h | 2 +- net/ipv6/exthdrs.c | 8 ++++---- net/ipv6/ioam6.c | 17 +++++++++-------- net/ipv6/ip6_input.c | 6 ++++-- net/ipv6/ip6_output.c | 5 +++-- net/ipv6/ip6_tunnel.c | 2 +- net/ipv6/ip6_vti.c | 2 +- net/ipv6/netfilter.c | 4 ++-- net/ipv6/netfilter/nf_reject_ipv6.c | 2 +- net/ipv6/output_core.c | 2 +- net/ipv6/reassembly.c | 10 +++++----- net/ipv6/route.c | 4 ++-- net/ipv6/seg6_iptunnel.c | 6 +++--- net/ipv6/tcp_ipv6.c | 4 ++-- net/ipv6/xfrm6_output.c | 2 +- 16 files changed, 41 insertions(+), 37 deletions(-)
include/net/inet6_hashtables.h +1 -1
@@ -150,7 +150,7 @@ static inline struct sock *__inet6_looku int iif, int sdif, bool *refcounted) { - struct net *net = dev_net_rcu(skb_dst(skb)->dev); + struct net *net = skb_dst_dev_net_rcu(skb);const struct ipv6hdr *ip6h =ipv6_hdr (skb);struct sock *sk;
include/net/ip6_tunnel.h +1 -1
@@ -170,7 +170,7 @@ static inline void ip6tunnel_xmit(structmemset (skb->cb,0 ,sizeof (struct inet6_skb_parm )); pkt_len = skb->len -skb_inner_network_offset (skb); - err =ip6_local_out (dev_net (skb_dst (skb)->dev), sk, skb); + err =ip6_local_out (skb_dst_dev_net (skb), sk, skb);if (dev) {if (unlikely (net_xmit_eval (err)))
net/ipv6/exthdrs.c +4 -4
@@ -462,7 +462,7 @@ looped_back:return -1 ; } -if (skb_dst (skb)->dev->flags &IFF_LOOPBACK ) { +if (skb_dst_dev (skb)->flags &IFF_LOOPBACK ) {if (ipv6_hdr (skb)->hop_limit <=1 ) {__IP6_INC_STATS (net, idev,IPSTATS_MIB_INHDRERRORS ); icmpv6_send(skb, ICMPV6_TIME_EXCEED,
@@ -621,7 +621,7 @@ looped_back:return -1 ; } -if (skb_dst (skb)->dev->flags &IFF_LOOPBACK ) { +if (skb_dst_dev (skb)->flags &IFF_LOOPBACK ) {if (ipv6_hdr (skb)->hop_limit <=1 ) {__IP6_INC_STATS (net, idev,IPSTATS_MIB_INHDRERRORS ); icmpv6_send(skb, ICMPV6_TIME_EXCEED,
@@ -787,7 +787,7 @@ looped_back:kfree_skb (skb);return -1 ; } -if (!ipv6_chk_home_addr (dev_net (skb_dst (skb)->dev), addr)) { +if (!ipv6_chk_home_addr (skb_dst_dev_net (skb), addr)) {__IP6_INC_STATS (net, idev,IPSTATS_MIB_INADDRERRORS );kfree_skb (skb);return -1 ;
@@ -813,7 +813,7 @@ looped_back:return -1 ; } -if (skb_dst (skb)->dev->flags&IFF_LOOPBACK ) { +if (skb_dst_dev (skb)->flags &IFF_LOOPBACK ) {if (ipv6_hdr (skb)->hop_limit <=1 ) {__IP6_INC_STATS (net, idev,IPSTATS_MIB_INHDRERRORS ); icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
net/ipv6/ioam6.c +9 -8
@@ -714,6 +714,7 @@ static void __ioam6_fill_trace_data(strustruct ioam6_schema *sc, unsigned int sclen, bool is_input) { + struct net_device *dev = skb_dst_dev(skb);struct timespec64 ts;ktime_t tstamp;u64 raw64;
@@ -730,7 +731,7 @@ static void __ioam6_fill_trace_data(struif (is_input) byte--; - raw32 =dev_net (skb_dst (skb)->dev)->ipv6.sysctl.ioam6_id; + raw32 =dev_net (dev)->ipv6.sysctl.ioam6_id; *(__be32 *)data =cpu_to_be32 ((byte <<24 ) | raw32); data +=sizeof (__be32);
@@ -746,10 +747,10 @@ static void __ioam6_fill_trace_data(stru *(__be16 *)data =cpu_to_be16 (raw16); data +=sizeof (__be16); -if (skb_dst (skb)->dev->flags &IFF_LOOPBACK ) +if (dev->flags &IFF_LOOPBACK ) raw16 =IOAM6_U16_UNAVAILABLE ;else - raw16 = (__force u16 )READ_ONCE (__in6_dev_get (skb_dst (skb)->dev)->cnf.ioam6_id); + raw16 = (__force u16 )READ_ONCE (__in6_dev_get (dev)->cnf.ioam6_id); *(__be16 *)data =cpu_to_be16 (raw16); data +=sizeof (__be16);
@@ -801,10 +802,10 @@ static void __ioam6_fill_trace_data(strustruct Qdisc *qdisc;__u32 qlen, backlog; -if (skb_dst (skb)->dev->flags &IFF_LOOPBACK ) { +if (dev->flags &IFF_LOOPBACK ) { *(__be32 *)data =cpu_to_be32 (IOAM6_U32_UNAVAILABLE ); }else { - queue =skb_get_tx_queue (skb_dst (skb)->dev, skb); + queue =skb_get_tx_queue (dev, skb); qdisc =rcu_dereference (queue->qdisc);qdisc_qstats_qlen_backlog (qdisc, &qlen, &backlog);
@@ -825,7 +826,7 @@ static void __ioam6_fill_trace_data(struif (is_input) byte--; - raw64 =dev_net (skb_dst (skb)->dev)->ipv6.sysctl.ioam6_id_wide; + raw64 =dev_net (dev)->ipv6.sysctl.ioam6_id_wide; *(__be64 *)data =cpu_to_be64 (((u64 )byte <<56 ) | raw64); data +=sizeof (__be64);
@@ -841,10 +842,10 @@ static void __ioam6_fill_trace_data(stru *(__be32 *)data =cpu_to_be32 (raw32); data +=sizeof (__be32); -if (skb_dst (skb)->dev->flags &IFF_LOOPBACK ) +if (dev->flags &IFF_LOOPBACK ) raw32 =IOAM6_U32_UNAVAILABLE ;else - raw32 =READ_ONCE (__in6_dev_get (skb_dst (skb)->dev)->cnf.ioam6_id_wide); + raw32 =READ_ONCE (__in6_dev_get (dev)->cnf.ioam6_id_wide); *(__be32 *)data =cpu_to_be32 (raw32); data +=sizeof (__be32);
net/ipv6/ip6_input.c +4 -2
@@ -187,7 +187,9 @@ static struct sk_buff *ip6_rcv_core(stru* arrived via the sending interface (ethX), because of the * nature of scoping architecture. --yoshfuji */ -IP6CB (skb)->iif =skb_valid_dst (skb) ?ip6_dst_idev (skb_dst (skb))->dev->ifindex : dev->ifindex; +IP6CB (skb)->iif =skb_valid_dst (skb) ? +ip6_dst_idev (skb_dst (skb))->dev->ifindex : + dev->ifindex;if (unlikely (!pskb_may_pull (skb,sizeof (*hdr)))) goto err;
@@ -500,7 +502,7 @@ int ip6_mc_input(struct sk_buff *skb)struct net_device *dev;bool deliver; -__IP6_UPD_PO_STATS (dev_net (skb_dst (skb)->dev), +__IP6_UPD_PO_STATS (skb_dst_dev_net (skb),__in6_dev_get_safely (skb->dev),IPSTATS_MIB_INMCAST , skb->len);
net/ipv6/ip6_output.c +3 -2
@@ -234,8 +234,9 @@ static int ip6_finish_output(struct netint ip6_output (struct net *net,struct sock *sk,struct sk_buff *skb) { -struct net_device *dev =skb_dst (skb)->dev, *indev = skb->dev; -struct inet6_dev *idev =ip6_dst_idev (skb_dst (skb)); +struct dst_entry *dst =skb_dst (skb); +struct net_device *dev =dst_dev (dst), *indev = skb->dev; +struct inet6_dev *idev =ip6_dst_idev (dst); skb->protocol =htons (ETH_P_IPV6 ); skb->dev = dev;
net/ipv6/ip6_tunnel.c +1 -1
@@ -637,7 +637,7 @@ ip4ip6_err(struct sk_buff *skb, struct i }else {if (ip_route_input (skb2, eiph->daddr, eiph->saddr,ip4h_dscp (eiph), skb2->dev) || -skb_dst (skb2)->dev->type !=ARPHRD_TUNNEL6 ) +skb_dst_dev (skb2)->type !=ARPHRD_TUNNEL6 ) goto out; }
net/ipv6/ip6_vti.c +1 -1
@@ -531,7 +531,7 @@ vti6_xmit(struct sk_buff *skb, struct ne xmit:skb_scrub_packet (skb, !net_eq (t->net,dev_net (dev)));skb_dst_set (skb, dst); - skb->dev =skb_dst (skb)->dev; + skb->dev =dst_dev (dst); err =dst_output (t->net, skb->sk, skb);if (net_xmit_eval (err) ==0 )
net/ipv6/netfilter.c +2 -2
@@ -24,7 +24,7 @@ int ip6_route_me_harder(struct net *net, {const struct ipv6hdr *iph =ipv6_hdr (skb);struct sock *sk =sk_to_full_sk (sk_partial); -struct net_device *dev =skb_dst (skb)->dev; +struct net_device *dev =skb_dst_dev (skb);struct flow_keys flkeys;unsigned int hh_len;struct dst_entry *dst;
@@ -72,7 +72,7 @@ int ip6_route_me_harder(struct net *net,#endif /* Change in oif may mean change in hh_len. */ - hh_len =skb_dst (skb)->dev->hard_header_len; + hh_len =skb_dst_dev (skb)->hard_header_len;if (skb_headroom (skb) < hh_len &&pskb_expand_head (skb,HH_DATA_ALIGN (hh_len -skb_headroom (skb)),0 ,GFP_ATOMIC ))
net/ipv6/netfilter/nf_reject_ipv6.c +1 -1
@@ -330,7 +330,7 @@ void nf_send_reset6(struct net *net, strskb_dst_set (oldskb, dst); } - fl6.flowi6_oif =l3mdev_master_ifindex (skb_dst (oldskb)->dev); + fl6.flowi6_oif =l3mdev_master_ifindex (skb_dst_dev (oldskb)); fl6.flowi6_mark =IP6_REPLY_MARK (net, oldskb->mark);security_skb_classify_flow (oldskb,flowi6_to_flowi_common (&fl6)); dst =ip6_route_output (net,NULL , &fl6);
net/ipv6/output_core.c +1 -1
@@ -141,7 +141,7 @@ int __ip6_local_out(struct net *net, str skb->protocol =htons (ETH_P_IPV6 );return nf_hook (NFPROTO_IPV6 ,NF_INET_LOCAL_OUT , - net, sk, skb,NULL ,skb_dst (skb)->dev, + net, sk, skb,NULL ,skb_dst_dev (skb), dst_output); }EXPORT_SYMBOL_GPL (__ip6_local_out);
net/ipv6/reassembly.c +5 -5
@@ -104,11 +104,11 @@ fq_find(struct net *net, __be32 id, cons return container_of(q, struct frag_queue, q); } -static int ip6_frag_queue (struct frag_queue *fq,struct sk_buff *skb, +static int ip6_frag_queue (struct net *net, +struct frag_queue *fq,struct sk_buff *skb,struct frag_hdr *fhdr,int nhoff,u32 *prob_offset,int *refs) { -struct net *net =dev_net (skb_dst (skb)->dev);int offset, end, fragsize;struct sk_buff *prev_tail;struct net_device *dev;
@@ -324,10 +324,10 @@ out_fail:static int ipv6_frag_rcv (struct sk_buff *skb) { +const struct ipv6hdr *hdr =ipv6_hdr (skb); +struct net *net =skb_dst_dev_net (skb);struct frag_hdr *fhdr;struct frag_queue *fq; -const struct ipv6hdr *hdr =ipv6_hdr (skb); -struct net *net =dev_net (skb_dst (skb)->dev);u8 nexthdr;int iif;
@@ -384,7 +384,7 @@ static int ipv6_frag_rcv(struct sk_buffspin_lock (&fq->q.lock); fq->iif = iif; - ret =ip6_frag_queue (fq, skb, fhdr,IP6CB (skb)->nhoff, + ret =ip6_frag_queue (net, fq, skb, fhdr,IP6CB (skb)->nhoff, &prob_offset, &refs);spin_unlock (&fq->q.lock);
net/ipv6/route.c +2 -2
@@ -4602,7 +4602,7 @@ static int ip6_pkt_discard(struct sk_bufstatic int ip6_pkt_discard_out (struct net *net,struct sock *sk,struct sk_buff *skb) { - skb->dev =skb_dst (skb)->dev; + skb->dev =skb_dst_dev (skb);return ip6_pkt_drop (skb,ICMPV6_NOROUTE ,IPSTATS_MIB_OUTNOROUTES ); }
@@ -4613,7 +4613,7 @@ static int ip6_pkt_prohibit(struct sk_bustatic int ip6_pkt_prohibit_out (struct net *net,struct sock *sk,struct sk_buff *skb) { - skb->dev =skb_dst (skb)->dev; + skb->dev =skb_dst_dev (skb);return ip6_pkt_drop (skb,ICMPV6_ADM_PROHIBITED ,IPSTATS_MIB_OUTNOROUTES ); }
net/ipv6/seg6_iptunnel.c +3 -3
@@ -365,7 +365,7 @@ static int __seg6_do_srh_inline(struct s#ifdef CONFIG_IPV6_SEG6_HMAC if (sr_has_hmac (isrh)) { -struct net *net =dev_net (skb_dst (skb)->dev); +struct net *net =skb_dst_dev_net (skb); err =seg6_push_hmac (net, &hdr->saddr, isrh);if (unlikely (err))
@@ -540,7 +540,7 @@ drop:static int seg6_input_nf (struct sk_buff *skb) { -struct net_device *dev =skb_dst (skb)->dev; +struct net_device *dev =skb_dst_dev (skb);struct net *net =dev_net (skb->dev);switch (skb->protocol) {
@@ -626,7 +626,7 @@ drop:static int seg6_output_nf (struct net *net,struct sock *sk,struct sk_buff *skb) { -struct net_device *dev =skb_dst (skb)->dev; +struct net_device *dev =skb_dst_dev (skb);switch (skb->protocol) {case htons (ETH_P_IP ):
net/ipv6/tcp_ipv6.c +2 -2
@@ -863,7 +863,7 @@ static void tcp_v6_send_response(const s int oif, int rst, u8 tclass, __be32 label, u32 priority, u32 txhash, struct tcp_key *key) { - struct net *net = sk ? sock_net(sk) : dev_net_rcu(skb_dst(skb)->dev); + struct net *net = sk ? sock_net(sk) : skb_dst_dev_net_rcu(skb);unsigned int tot_len =sizeof (struct tcphdr );struct sock *ctl_sk = net->ipv6.tcp_sk;const struct tcphdr *th =tcp_hdr (skb);
@@ -1037,7 +1037,7 @@ static void tcp_v6_send_reset(const struif (!sk && !ipv6_unicast_destination (skb))return ; - net = sk ?sock_net (sk) :dev_net_rcu (skb_dst (skb)->dev); + net = sk ?sock_net (sk) :skb_dst_dev_net_rcu (skb);/* Invalid TCP option size or twice included auth */ if (tcp_parse_auth_options (th, &md5_hash_location, &aoh))return ;
net/ipv6/xfrm6_output.c +1 -1
@@ -106,7 +106,7 @@ skip_frag:int xfrm6_output (struct net *net,struct sock *sk,struct sk_buff *skb) {return NF_HOOK_COND (NFPROTO_IPV6 ,NF_INET_POST_ROUTING , - net, sk, skb, skb->dev,skb_dst (skb)->dev, + net, sk, skb, skb->dev,skb_dst_dev (skb), __xfrm6_output, !(IP6CB (skb)->flags &IP6SKB_REROUTED )); }
Greg Kroah-Hartman
maintainerPATCH 1079/1102 ipv6: ip6_mc_input() and ip6_mr_input() cleanups
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 46a94e44b9ec4d8d20108a1748c410d71a8dc759 ]
Both functions are always called under RCU.
We remove the extra rcu_read_lock()/rcu_read_unlock().
We use skb_dst_dev_net_rcu() instead of skb_dst_dev_net().
We use dev_net_rcu() instead of dev_net().
Stable-dep-of: e36ce6e78fe3 ("ip: orphan prefetched skbs before multicast forwarding")
--- net/ipv6/ip6_input.c | 29 +++++++++++------------------ net/ipv6/ip6mr.c | 9 ++++----- 2 files changed, 15 insertions(+), 23 deletions(-)
net/ipv6/ip6_input.c +11 -18
@@ -497,38 +497,32 @@ EXPORT_SYMBOL_GPL(ip6_input);int ip6_mc_input (struct sk_buff *skb) { +struct net_device *dev = skb->dev;int sdif =inet6_sdif (skb);const struct ipv6hdr *hdr; -struct net_device *dev;bool deliver; -__IP6_UPD_PO_STATS (skb_dst_dev_net (skb), -__in6_dev_get_safely (skb->dev),IPSTATS_MIB_INMCAST , - skb->len); +__IP6_UPD_PO_STATS (skb_dst_dev_net_rcu (skb), +__in6_dev_get_safely (dev),IPSTATS_MIB_INMCAST , + skb->len);/* skb->dev passed may be master dev for vrfs. */ if (sdif) { -rcu_read_lock (); - dev =dev_get_by_index_rcu (dev_net (skb->dev), sdif); + dev =dev_get_by_index_rcu (dev_net_rcu (dev), sdif);if (!dev) { -rcu_read_unlock ();kfree_skb (skb);return -ENODEV ; } - }else { - dev = skb->dev; } hdr =ipv6_hdr (skb); deliver =ipv6_chk_mcast_addr (dev, &hdr->daddr,NULL ); -if (sdif) -rcu_read_unlock ();#ifdef CONFIG_IPV6_MROUTE /* * IPv6 multicast router mode is now supported ;) */ -if (atomic_read (&dev_net (skb->dev)->ipv6.devconf_all->mc_forwarding) && +if (atomic_read (&dev_net_rcu (skb->dev)->ipv6.devconf_all->mc_forwarding) && !(ipv6_addr_type (&hdr->daddr) & (IPV6_ADDR_LOOPBACK |IPV6_ADDR_LINKLOCAL )) &&likely (!(IP6CB (skb)->flags &IP6SKB_FORWARDED ))) {
@@ -569,22 +563,21 @@ int ip6_mc_input(struct sk_buff *skb) /* unknown RA - process it normally */ } -if (deliver) +if (deliver) { skb2 =skb_clone (skb,GFP_ATOMIC ); -else { + }else { skb2 = skb; skb =NULL ; } -if (skb2) { +if (skb2)ip6_mr_input (skb2); - } } out: #endif -if (likely (deliver)) +if (likely (deliver)) {ip6_input (skb); -else { + }else {/* discard */ kfree_skb (skb); }
net/ipv6/ip6mr.c +4 -5
@@ -2222,21 +2222,20 @@ dont_forward:int ip6_mr_input (struct sk_buff *skb) { +struct net_device *dev = skb->dev; +struct net *net =dev_net_rcu (dev);struct mfc6_cache *cache; -struct net *net =dev_net (skb->dev);struct mr_table *mrt;struct flowi6 fl6 = { - .flowi6_iif = skb->dev->ifindex, + .flowi6_iif = dev->ifindex, .flowi6_mark = skb->mark, };int err; -struct net_device *dev;/* skb->dev passed in is the master dev for vrfs. * Get the proper interface that does have a vif associated with it. */ - dev = skb->dev; -if (netif_is_l3_master (skb->dev)) { +if (netif_is_l3_master (dev)) { dev =dev_get_by_index_rcu (net,IPCB (skb)->iif);if (!dev) {kfree_skb (skb);
Greg Kroah-Hartman
maintainerPATCH 1080/1102 ip: orphan prefetched skbs before multicast forwarding
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhiling Zou <[email protected]>
[ Upstream commit e36ce6e78fe3fc3c071a26750783b7ba081ce10d ]
IPv4 and IPv6 input preserve an skb->sk association installed by bpf_sk_assign() so that local delivery can use the selected socket under RCU. Both address families can also prefetch a socket in UDP early demux. In both paths (BPF and UDP early demux) a reference is not guaranteed to be held on the socket.
When a multicast packet is not locally deliverable, IPv6 hands the original skb to ip6_mr_input(). IPv4's ip_mr_input() similarly keeps the original skb when local delivery is not needed. Either path can put the skb on an unresolved multicast route queue or forward it after the receive-side RCU section ends.
After the prefetched socket is destroyed, a later skb free invokes sock_pfree() and dereferences the stale skb->sk. Orphan the skb before each non-local multicast forwarding path. Local delivery retains the original skb; the existing skb_clone() calls provide multicast forwarding with a socket-free clone.
--- net/ipv4/ipmr.c | 3 +++ net/ipv6/ip6_input.c | 1 + 2 files changed, 4 insertions(+)
net/ipv4/ipmr.c +3 -0
@@ -2140,6 +2140,9 @@ int ip_mr_input(struct sk_buff *skb)if (IPCB (skb)->flags &IPSKB_FORWARDED ) goto dont_forward; +if (!local) +skb_orphan (skb); + mrt =ipmr_rt_fib_lookup (net, skb);if (IS_ERR (mrt)) {kfree_skb (skb);
net/ipv6/ip6_input.c +1 -0
@@ -566,6 +566,7 @@ int ip6_mc_input(struct sk_buff *skb)if (deliver) { skb2 =skb_clone (skb,GFP_ATOMIC ); }else { +skb_orphan (skb); skb2 = skb; skb =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 1081/1102 SUNRPC: Introduce xdr_set_scratch_folio()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anna Schumaker <[email protected]>
[ Upstream commit c8a127596edc026e5364a7a609986dcd3999914c ]
This will replace xdr_set_scratch_page() when we switch pages to folios.
Stable-dep-of: c479bde671cb ("sunrpc: defer rq_argp and rq_resp free until after RCU grace period")
--- include/linux/sunrpc/xdr.h | 13 +++++++++++++ 1 file changed, 13 insertions(+)
include/linux/sunrpc/xdr.h +13 -0
@@ -318,6 +318,19 @@ xdr_set_scratch_page(struct xdr_stream * }/** +* xdr_set_scratch_folio - Attach a scratch buffer for decoding data +* @xdr: pointer to xdr_stream struct +* @page: an anonymous folio +* +* See xdr_set_scratch_buffer(). +*/ +static inline void +xdr_set_scratch_folio (struct xdr_stream *xdr,struct folio *folio) +{ +xdr_set_scratch_buffer (xdr,folio_address (folio),folio_size (folio)); +} + +/** * xdr_reset_scratch_buffer - Clear scratch buffer information * @xdr: pointer to xdr_stream struct *
Greg Kroah-Hartman
maintainerPATCH 1082/1102 SUNRPC: Update svcxdr_init_decode() to call xdr_set_scratch_folio()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anna Schumaker <[email protected]>
[ Upstream commit d57e43b72bf2071caac90da323849c3983a695f0 ]
The only snag here is that __folio_alloc_node() doesn't handle NUMA_NO_NODE, so I also need to update svc_pool_map_get_node() to return numa_mem_id() instead. I arrived at this approach by looking at what other users of __folio_alloc_node() do for this case.
Stable-dep-of: c479bde671cb ("sunrpc: defer rq_argp and rq_resp free until after RCU grace period")
--- include/linux/sunrpc/svc.h | 4 ++-- net/sunrpc/svc.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-)
include/linux/sunrpc/svc.h +2 -2
@@ -190,7 +190,7 @@ struct svc_rqst {struct xdr_buf rq_arg;struct xdr_stream rq_arg_stream;struct xdr_stream rq_res_stream; -struct page *rq_scratch_page; +struct folio *rq_scratch_folio;struct xdr_buf rq_res;struct page *rq_pages[RPCSVC_MAXPAGES +1 ];struct page * *rq_respages;/* points into rq_pages */
@@ -504,7 +504,7 @@ static inline void svcxdr_init_decode(st buf->len = buf->head->iov_len + buf->page_len + buf->tail->iov_len;xdr_init_decode (xdr, buf, argv->iov_base,NULL ); -xdr_set_scratch_page (xdr, rqstp->rq_scratch_page); +xdr_set_scratch_folio (xdr, rqstp->rq_scratch_folio); }/**
net/sunrpc/svc.c +5 -5
@@ -352,7 +352,7 @@ static int svc_pool_map_get_node(unsigneif (m->mode ==SVC_POOL_PERNODE )return m->pool_to[pidx]; } -return NUMA_NO_NODE ; +return numa_mem_id (); }/* * Set the given thread's cpus_allowed mask so that it
@@ -734,8 +734,8 @@ svc_rqst_free(struct svc_rqst *rqstp) {folio_batch_release (&rqstp->rq_fbatch);svc_release_buffer (rqstp); -if (rqstp->rq_scratch_page) -put_page (rqstp->rq_scratch_page); +if (rqstp->rq_scratch_folio) +folio_put (rqstp->rq_scratch_folio);kfree (rqstp->rq_resp);kfree (rqstp->rq_argp);kfree (rqstp->rq_auth_data);
@@ -756,8 +756,8 @@ svc_prepare_thread(struct svc_serv *serv rqstp->rq_server = serv; rqstp->rq_pool = pool; - rqstp->rq_scratch_page =alloc_pages_node (node,GFP_KERNEL ,0 ); -if (!rqstp->rq_scratch_page) + rqstp->rq_scratch_folio =__folio_alloc_node (GFP_KERNEL ,0 , node); +if (!rqstp->rq_scratch_folio) goto out_enomem; rqstp->rq_argp =kmalloc_node (serv->sv_xdrsize,GFP_KERNEL , node);
Greg Kroah-Hartman
maintainerPATCH 1083/1102 sunrpc: defer rq_argp and rq_resp free until after RCU grace period
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
[ Upstream commit c479bde671cbe2f9e152834a8b0eb7c3c295bbaf ]
svc_rqst_free() frees rqstp->rq_argp and rqstp->rq_resp synchronously via kfree(), but defers the rqstp struct free via kfree_rcu(). After svc_exit_thread() calls list_del_rcu() and svc_rqst_free(), there is a window where RCU readers that started before list_del_rcu() can still traverse the thread list and find the rqstp. These readers (e.g. nfsd_nl_rpc_status_get_dumpit()) dereference rqstp->rq_argp, which has already been freed — a use-after-free.
Fix this by moving the kfree of rq_argp and rq_resp into an explicit call_rcu() callback alongside the struct free. Resources not accessed by RCU readers (bvec, buffer pages, scratch folio, auth_data) remain synchronously freed.
--- net/sunrpc/svc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
net/sunrpc/svc.c +10 -3
@@ -729,6 +729,15 @@ svc_release_buffer(struct svc_rqst *rqstput_page (rqstp->rq_pages[i]); } +static void svc_rqst_free_rcu (struct rcu_head *head) +{ + struct svc_rqst *rqstp = container_of(head, struct svc_rqst, rq_rcu_head); + +kfree (rqstp->rq_resp); +kfree (rqstp->rq_argp); +kfree (rqstp); +} +static void svc_rqst_free (struct svc_rqst *rqstp) {
@@ -736,10 +745,8 @@ svc_rqst_free(struct svc_rqst *rqstp)svc_release_buffer (rqstp);if (rqstp->rq_scratch_folio)folio_put (rqstp->rq_scratch_folio); -kfree (rqstp->rq_resp); -kfree (rqstp->rq_argp);kfree (rqstp->rq_auth_data); -kfree_rcu (rqstp, rq_rcu_head); +call_rcu (&rqstp->rq_rcu_head, svc_rqst_free_rcu); } static struct svc_rqst *
Greg Kroah-Hartman
maintainerPATCH 1084/1102 SUNRPC: fix gssx_dec_option_array error path bugs
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Mason <[email protected]>
[ Upstream commit 5e9a94539b1ec17a89177d952badfd0d844d694a ]
Four coupled defects in the gssx XDR option-array decoder make the error paths unsafe: a NULL deref in the caller, a refcount leak on the decoded group_info, and a latent use-after-free that the leak fix would otherwise expose.
gssx_dec_option_array() sets oa->count = 1 before allocating oa->data. If that allocation fails, -ENOMEM is returned with oa->count == 1 and oa->data == NULL. All other error paths jump to free_oa: which frees oa->data and NULLs it but also leaves oa->count == 1. The caller trusts the count:
gssp_accept_sec_context_upcall()
gssx_dec_accept_sec_context()
gssx_dec_option_array() /* fails, count=1 data=NULL */
data = res.options.data[0].value /* NULL deref */
Independently, free_creds: releases the partially decoded svc_cred with a bare kfree(creds). gssx_dec_linux_creds() installs a groups_alloc() result into creds->cr_group_info; that object is kvmalloc-backed and refcounted, and only put_group_info() reaches kvfree(). A plain kfree(creds) drops the wrapper and leaks the group_info allocation.
The natural fix for the leak is to call free_svc_cred(creds) before kfree(creds), but free_svc_cred() invokes put_group_info() on creds->cr_group_info unconditionally when non-NULL. The existingout_free_groups: path in gssx_dec_linux_creds() already called groups_free() on that pointer without clearing it, so once free_svc_cred() is wired in, the subsequent put_group_info() would touch freed memory.
Fix all four together:
- Move the oa->count = 1 assignment below the oa->data allocation
so it is never set when oa->data is NULL.
- Reset oa->count to 0 at free_oa: so count and data stay coherent and the caller sees an empty option array.
- Call free_svc_cred(creds) before kfree(creds) at free_creds:
so the refcounted cr_group_info is released. free_svc_cred() either NULL-guards each field explicitly (cr_group_info has an if() check) or delegates to a helper that is NULL-safe itself (kfree for the string fields, gss_mech_put() which guards with if(gm) at gss_mech_switch.c:342), so it is safe to call on a partially decoded svc_cred where only cr_uid/cr_gid/cr_group_info have been written and everything else is zero from kzalloc.
- In gssx_dec_linux_creds()'s out_free_groups: path, release cr_group_info with put_group_info() rather than groups_free() so the teardown matches free_svc_cred()'s refcount-aware path, and clear the pointer so a later free_svc_cred() on the same creds does not release it a second time.
--- net/sunrpc/auth_gss/gss_rpc_xdr.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
net/sunrpc/auth_gss/gss_rpc_xdr.c +6 -3
@@ -222,7 +222,8 @@ static int gssx_dec_linux_creds(struct xreturn 0 ; out_free_groups: -groups_free (creds->cr_group_info); +put_group_info (creds->cr_group_info); + creds->cr_group_info =NULL ;return err; }
@@ -243,12 +244,12 @@ static int gssx_dec_option_array(structreturn 0 ;/* we recognize only 1 currently: CREDS_VALUE */ - oa->count =1 ; - oa->data =kmalloc (sizeof (struct gssx_option ),GFP_KERNEL );if (!oa->data)return -ENOMEM ; + oa->count =1 ; + creds =kzalloc (sizeof (struct svc_cred ),GFP_KERNEL );if (!creds) { err = -ENOMEM ;
@@ -300,8 +301,10 @@ static int gssx_dec_option_array(structreturn 0 ; free_creds: +free_svc_cred (creds);kfree (creds); free_oa: + oa->count =0 ;kfree (oa->data); oa->data =NULL ;return err;
Greg Kroah-Hartman
maintainerPATCH 1085/1102 rpc_populate(): lift cleanup into callers
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit 8be22c49646e47452e74aa0b97ea50fb04c271ed ]
rpc_populate() is called either from fill_super (where we don't need to remove any files on failure - rpc_kill_sb() will take them all out anyway) or from rpc_mkdir_populate(), where we need to remove the directory we'd been trying to populate along with whatever we'd put into it before we failed. Simpler to combine that into simple_recursive_removal() there.
Note that rpc_pipe is overlocking directories quite a bit - locked parent is no obstacle to finding a child in dcache, so keeping it locked won't prevent userland observing a partially built subtree.
All we need is to follow minimal VFS requirements; it's not as if clients used directory locking for exclusion - tree changes are serialized, but that's done on ->pipefs_sb_lock.
Stable-dep-of: 932a8cf6abb2 ("sunrpc: fix use-after-free in __rpc_clnt_handle_event and __rpc_clnt_remove_pipedir")
--- include/linux/sunrpc/rpc_pipe_fs.h | 2 +- net/sunrpc/clnt.c | 36 ++++++++++++++---------------------- net/sunrpc/rpc_pipe.c | 26 +++++++++++++------------- 3 files changed, 28 insertions(+), 36 deletions(-)
include/linux/sunrpc/rpc_pipe_fs.h +1 -1
@@ -98,7 +98,7 @@ static inline bool rpc_msg_is_inflight(c }struct rpc_clnt ; -extern struct dentry *rpc_create_client_dir (struct dentry *,const char *,struct rpc_clnt *); +extern int rpc_create_client_dir (struct dentry *,const char *,struct rpc_clnt *);extern int rpc_remove_client_dir (struct rpc_clnt *);extern void rpc_init_pipe_dir_head (struct rpc_pipe_dir_head *pdh);
net/sunrpc/clnt.c +14 -22
@@ -112,47 +112,46 @@ static void rpc_clnt_remove_pipedir(stru } } -static struct dentry *rpc_setup_pipedir_sb (struct super_block *sb, +static int rpc_setup_pipedir_sb (struct super_block *sb,struct rpc_clnt *clnt) {static uint32_t clntid;const char *dir_name = clnt->cl_program->pipe_dir_name;char name[15 ]; -struct dentry *dir, *dentry; +struct dentry *dir; +int err; dir =rpc_d_lookup_sb (sb, dir_name);if (dir ==NULL ) {pr_info ("RPC: pipefs directory doesn't exist: %s\n" , dir_name); -return dir; +return -ENOENT ; }for (;;) {snprintf (name,sizeof (name),"clnt%x" , (unsigned int )clntid++); name[sizeof (name) -1 ] ='\0' ; - dentry =rpc_create_client_dir (dir, name, clnt); -if (!IS_ERR (dentry)) + err =rpc_create_client_dir (dir, name, clnt); +if (!err)break ; -if (dentry ==ERR_PTR (-EEXIST )) +if (err == -EEXIST )continue ;printk (KERN_INFO "RPC: Couldn't create pipefs entry" -" %s/%s, error %ld\n" , - dir_name, name,PTR_ERR (dentry)); +" %s/%s, error %d\n" , + dir_name, name, err);break ; }dput (dir); -return dentry; +return err; }static int rpc_setup_pipedir (struct super_block *pipefs_sb,struct rpc_clnt *clnt) { -struct dentry *dentry; - clnt->pipefs_sb = pipefs_sb;if (clnt->cl_program->pipe_dir_name !=NULL ) { - dentry =rpc_setup_pipedir_sb (pipefs_sb, clnt); -if (IS_ERR (dentry)) -return PTR_ERR (dentry); +int err =rpc_setup_pipedir_sb (pipefs_sb, clnt); +if (err && err != -ENOENT ) +return err; }return 0 ; }
@@ -180,16 +179,9 @@ static int rpc_clnt_skip_event(struct rpstatic int __rpc_clnt_handle_event (struct rpc_clnt *clnt,unsigned long event,struct super_block *sb) { -struct dentry *dentry; -switch (event) {case RPC_PIPEFS_MOUNT : - dentry =rpc_setup_pipedir_sb (sb, clnt); -if (!dentry) -return -ENOENT ; -if (IS_ERR (dentry)) -return PTR_ERR (dentry); -break ; +return rpc_setup_pipedir_sb (sb, clnt);case RPC_PIPEFS_UMOUNT :__rpc_clnt_remove_pipedir (clnt);break ;
net/sunrpc/rpc_pipe.c +13 -13
@@ -725,7 +725,6 @@ static int rpc_populate(struct dentry *pinode_unlock (dir);return 0 ; out_bad: -__rpc_depopulate (parent, files, start, eof);inode_unlock (dir);printk (KERN_WARNING "%s: %s failed to populate directory %pd\n" , __FILE__, __func__, parent);
@@ -749,14 +748,15 @@ static struct dentry *rpc_mkdir_populate goto out_err;if (populate !=NULL ) { error =populate (dentry, args_populate); -if (error) - goto err_rmdir; +if (error) { +inode_unlock (dir); +simple_recursive_removal (dentry,NULL ); +return ERR_PTR (error); + } } out:inode_unlock (dir);return dentry; -err_rmdir: -__rpc_rmdir (dir, dentry); out_err: dentry =ERR_PTR (error); goto out;
@@ -1046,19 +1046,19 @@ static void rpc_clntdir_depopulate(struc* information about the client, together with any "pipes" that may * later be created using rpc_mkpipe(). */ -struct dentry *rpc_create_client_dir (struct dentry *dentry, -const char *name, -struct rpc_clnt *rpc_client) +int rpc_create_client_dir (struct dentry *dentry, +const char *name, +struct rpc_clnt *rpc_client) {struct dentry *ret; ret =rpc_mkdir_populate (dentry, name,0555 ,NULL , rpc_clntdir_populate, rpc_client); -if (!IS_ERR (ret)) { - rpc_client->cl_pipedir_objects.pdh_dentry = ret; -rpc_create_pipe_dir_objects (&rpc_client->cl_pipedir_objects); - } -return ret; +if (IS_ERR (ret)) +return PTR_ERR (ret); + rpc_client->cl_pipedir_objects.pdh_dentry = ret; +rpc_create_pipe_dir_objects (&rpc_client->cl_pipedir_objects); +return 0 ; }/**
Greg Kroah-Hartman
maintainerPATCH 1086/1102 rpc_mkpipe_dentry(): saner calling conventions
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit 19a6314a997f6adde0c100ecf9224d1ab43c9603 ]
Instead of returning a dentry or ERR_PTR(-E...), return 0 and store dentry into pipe->dentry on success and return -E... on failure.
Callers are happier that way...
NOTE: dummy rpc_pipe is getting ->dentry set; we never access that, since we
1) never call rpc_unlink() for it (dentry is taken out by
->kill_sb())
2) never call rpc_queue_upcall() for it (writing to that
sucker fails; no downcalls are ever submitted, so no replies are going to arrive)
IOW, having that ->dentry set (and left dangling) is harmless, if ugly; cleaner solution will take more massage.
Stable-dep-of: 932a8cf6abb2 ("sunrpc: fix use-after-free in __rpc_clnt_handle_event and __rpc_clnt_remove_pipedir")
--- fs/nfs/blocklayout/rpc_pipefs.c | 41 ++++++++++++++----------------------- fs/nfs/nfs4idmap.c | 8 ------- fs/nfsd/nfs4recover.c | 37 ++++++++++++--------------------- include/linux/sunrpc/rpc_pipe_fs.h | 2 - net/sunrpc/auth_gss/auth_gss.c | 7 ------ net/sunrpc/rpc_pipe.c | 31 ++++++++++++++------------- 6 files changed, 49 insertions(+), 77 deletions(-)
fs/nfs/blocklayout/rpc_pipefs.c +16 -25
@@ -141,17 +141,18 @@ static const struct rpc_pipe_ops bl_upca .destroy_msg = bl_pipe_destroy_msg, }; -static struct dentry *nfs4blocklayout_register_sb (struct super_block *sb, +static int nfs4blocklayout_register_sb (struct super_block *sb,struct rpc_pipe *pipe) { -struct dentry *dir, *dentry; +struct dentry *dir; +int err; dir =rpc_d_lookup_sb (sb,NFS_PIPE_DIRNAME );if (dir ==NULL ) -return ERR_PTR (-ENOENT ); - dentry =rpc_mkpipe_dentry (dir,"blocklayout" ,NULL , pipe); +return -ENOENT ; + err =rpc_mkpipe_dentry (dir,"blocklayout" ,NULL , pipe);dput (dir); -return dentry; +return err; } static void nfs4blocklayout_unregister_sb(struct super_block *sb,
@@ -167,7 +168,6 @@ static int rpc_pipefs_event(struct notifstruct super_block *sb = ptr;struct net *net = sb->s_fs_info;struct nfs_net *nn =net_generic (net, nfs_net_id); -struct dentry *dentry;int ret =0 ;if (!try_module_get (THIS_MODULE ))
@@ -180,12 +180,7 @@ static int rpc_pipefs_event(struct notifswitch (event) {case RPC_PIPEFS_MOUNT : - dentry =nfs4blocklayout_register_sb (sb, nn->bl_device_pipe); -if (IS_ERR (dentry)) { - ret =PTR_ERR (dentry); -break ; - } - nn->bl_device_pipe->dentry = dentry; + ret =nfs4blocklayout_register_sb (sb, nn->bl_device_pipe);break ;case RPC_PIPEFS_UMOUNT :if (nn->bl_device_pipe->dentry)
@@ -203,18 +198,17 @@ static struct notifier_block nfs4blockla .notifier_call = rpc_pipefs_event, }; -static struct dentry *nfs4blocklayout_register_net (struct net *net, -struct rpc_pipe *pipe) +static int nfs4blocklayout_register_net (struct net *net,struct rpc_pipe *pipe) {struct super_block *pipefs_sb; -struct dentry *dentry; +int ret; pipefs_sb =rpc_get_sb_net (net);if (!pipefs_sb) -return NULL ; - dentry =nfs4blocklayout_register_sb (pipefs_sb, pipe); +return 0 ; + ret =nfs4blocklayout_register_sb (pipefs_sb, pipe);rpc_put_sb_net (net); -return dentry; +return ret; } static void nfs4blocklayout_unregister_net(struct net *net,
@@ -232,20 +226,17 @@ static void nfs4blocklayout_unregister_nstatic int nfs4blocklayout_net_init (struct net *net) {struct nfs_net *nn =net_generic (net, nfs_net_id); -struct dentry *dentry; +int err;mutex_init (&nn->bl_mutex);init_waitqueue_head (&nn->bl_wq); nn->bl_device_pipe =rpc_mkpipe_data (&bl_upcall_ops,0 );if (IS_ERR (nn->bl_device_pipe))return PTR_ERR (nn->bl_device_pipe); - dentry =nfs4blocklayout_register_net (net, nn->bl_device_pipe); -if (IS_ERR (dentry)) { + err =nfs4blocklayout_register_net (net, nn->bl_device_pipe); +if (unlikely (err))rpc_destroy_pipe_data (nn->bl_device_pipe); -return PTR_ERR (dentry); - } - nn->bl_device_pipe->dentry = dentry; -return 0 ; +return err; }static void nfs4blocklayout_net_exit (struct net *net)
fs/nfs/nfs4idmap.c +1 -7
@@ -436,14 +436,8 @@ static int nfs_idmap_pipe_create(struct struct rpc_pipe_dir_object *pdo) {struct idmap *idmap = pdo->pdo_data; -struct rpc_pipe *pipe = idmap->idmap_pipe; -struct dentry *dentry; - dentry =rpc_mkpipe_dentry (dir,"idmap" , idmap, pipe); -if (IS_ERR (dentry)) -return PTR_ERR (dentry); - pipe->dentry = dentry; -return 0 ; +return rpc_mkpipe_dentry (dir,"idmap" , idmap, idmap->idmap_pipe); }static const struct rpc_pipe_dir_object_ops nfs_idmap_pipe_dir_object_ops = {
fs/nfsd/nfs4recover.c +14 -23
@@ -932,17 +932,18 @@ static const struct rpc_pipe_ops cld_upc .destroy_msg = cld_pipe_destroy_msg, }; -static struct dentry * +static int nfsd4_cld_register_sb (struct super_block *sb,struct rpc_pipe *pipe) { -struct dentry *dir, *dentry; +struct dentry *dir; +int err; dir =rpc_d_lookup_sb (sb,NFSD_PIPE_DIR );if (dir ==NULL ) -return ERR_PTR (-ENOENT ); - dentry =rpc_mkpipe_dentry (dir,NFSD_CLD_PIPE ,NULL , pipe); +return -ENOENT ; + err =rpc_mkpipe_dentry (dir,NFSD_CLD_PIPE ,NULL , pipe);dput (dir); -return dentry; +return err; } static void
@@ -952,18 +953,18 @@ nfsd4_cld_unregister_sb(struct rpc_piperpc_unlink (pipe->dentry); } -static struct dentry * +static int nfsd4_cld_register_net (struct net *net,struct rpc_pipe *pipe) {struct super_block *sb; -struct dentry *dentry; +int err; sb =rpc_get_sb_net (net);if (!sb) -return NULL ; - dentry =nfsd4_cld_register_sb (sb, pipe); +return 0 ; + err =nfsd4_cld_register_sb (sb, pipe);rpc_put_sb_net (net); -return dentry; +return err; } static void
@@ -983,7 +984,6 @@ static int __nfsd4_init_cld_pipe(struct net *net) {int ret; -struct dentry *dentry;struct nfsd_net *nn =net_generic (net, nfsd_net_id);struct cld_net *cn;
@@ -1004,13 +1004,10 @@ __nfsd4_init_cld_pipe(struct net *net)spin_lock_init (&cn->cn_lock);INIT_LIST_HEAD (&cn->cn_list); - dentry =nfsd4_cld_register_net (net, cn->cn_pipe); -if (IS_ERR (dentry)) { - ret =PTR_ERR (dentry); + ret =nfsd4_cld_register_net (net, cn->cn_pipe); +if (unlikely (ret)) goto err_destroy_data; - } - cn->cn_pipe->dentry = dentry;#ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING cn->cn_has_legacy = false;#endif
@@ -2157,7 +2154,6 @@ rpc_pipefs_event(struct notifier_block *struct net *net = sb->s_fs_info;struct nfsd_net *nn =net_generic (net, nfsd_net_id);struct cld_net *cn = nn->cld_net; -struct dentry *dentry;int ret =0 ;if (!try_module_get (THIS_MODULE ))
@@ -2170,12 +2166,7 @@ rpc_pipefs_event(struct notifier_block *switch (event) {case RPC_PIPEFS_MOUNT : - dentry =nfsd4_cld_register_sb (sb, cn->cn_pipe); -if (IS_ERR (dentry)) { - ret =PTR_ERR (dentry); -break ; - } - cn->cn_pipe->dentry = dentry; + ret =nfsd4_cld_register_sb (sb, cn->cn_pipe);break ;case RPC_PIPEFS_UMOUNT :if (cn->cn_pipe->dentry)
include/linux/sunrpc/rpc_pipe_fs.h +1 -1
@@ -127,7 +127,7 @@ extern void rpc_remove_cache_dir(structstruct rpc_pipe *rpc_mkpipe_data (const struct rpc_pipe_ops *ops,int flags);void rpc_destroy_pipe_data (struct rpc_pipe *pipe); -extern struct dentry *rpc_mkpipe_dentry (struct dentry *,const char *,void *, +extern int rpc_mkpipe_dentry (struct dentry *,const char *,void *,struct rpc_pipe *);extern int rpc_unlink (struct dentry *);extern int register_rpc_pipefs (void );
net/sunrpc/auth_gss/auth_gss.c +1 -6
@@ -902,13 +902,8 @@ static int gss_pipe_dentry_create(struct struct rpc_pipe_dir_object *pdo) {struct gss_pipe *p = pdo->pdo_data; -struct dentry *dentry; - dentry =rpc_mkpipe_dentry (dir, p->name, p->clnt, p->pipe); -if (IS_ERR (dentry)) -return PTR_ERR (dentry); - p->pipe->dentry = dentry; -return 0 ; +return rpc_mkpipe_dentry (dir, p->name, p->clnt, p->pipe); }static const struct rpc_pipe_dir_object_ops gss_pipe_dir_object_ops = {
net/sunrpc/rpc_pipe.c +16 -15
@@ -799,7 +799,7 @@ static int rpc_rmdir_depopulate(struct d* The @private argument passed here will be available to all these methods * from the file pointer, via RPC_I(file_inode(file))->private. */ -struct dentry *rpc_mkpipe_dentry (struct dentry *parent,const char *name, +int rpc_mkpipe_dentry (struct dentry *parent,const char *name,void *private,struct rpc_pipe *pipe) {struct dentry *dentry;
@@ -814,21 +814,19 @@ struct dentry *rpc_mkpipe_dentry(structinode_lock_nested (dir,I_MUTEX_PARENT ); dentry =__rpc_lookup_create_exclusive (parent, name); -if (IS_ERR (dentry)) - goto out; +if (IS_ERR (dentry)) { +inode_unlock (dir); +return PTR_ERR (dentry); + } err =__rpc_mkpipe_dentry (dir, dentry, umode, &rpc_pipe_fops, private, pipe); -if (err) - goto out_err; -out: +if (unlikely (err)) +pr_warn ("%s() failed to create pipe %pd/%s (errno = %d)\n" , + __func__, parent, name, err); +else + pipe->dentry = dentry;inode_unlock (dir); -return dentry; -out_err: - dentry =ERR_PTR (err); -printk (KERN_WARNING "%s: %s() failed to create pipe %pd/%s (errno = %d)\n" , - __FILE__, __func__, parent, name, - err); - goto out; +return err; }EXPORT_SYMBOL_GPL (rpc_mkpipe_dentry);
@@ -1326,10 +1324,13 @@ rpc_gssd_dummy_populate(struct dentry *r goto out; } - pipe_dentry =rpc_mkpipe_dentry (clnt_dentry,"gssd" ,NULL , pipe_data); -if (IS_ERR (pipe_dentry)) { + ret =rpc_mkpipe_dentry (clnt_dentry,"gssd" ,NULL , pipe_data); +if (ret) {__rpc_depopulate (clnt_dentry, gssd_dummy_info_file,0 ,1 );__rpc_depopulate (gssd_dentry, gssd_dummy_clnt_dir,0 ,1 ); + pipe_dentry =ERR_PTR (ret); + }else { + pipe_dentry = pipe_data->dentry; } out:dput (clnt_dentry);
Greg Kroah-Hartman
maintainerPATCH 1087/1102 rpc_pipe: dont overdo directory locking
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit 41a6b9e52b21544c334830bfe68fb78d6677caa0 ]
Don't try to hold directories locked more than VFS requires; lock just before getting a child to be made positive (using simple_start_creating()) and unlock as soon as the child is created. There's no benefit in keeping the parent locked while populating the child - it won't stop dcache lookups anyway.
Stable-dep-of: 932a8cf6abb2 ("sunrpc: fix use-after-free in __rpc_clnt_handle_event and __rpc_clnt_remove_pipedir")
--- net/sunrpc/rpc_pipe.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-)
net/sunrpc/rpc_pipe.c +12 -13
@@ -698,12 +698,14 @@ static int rpc_populate(struct dentry *pstruct dentry *dentry;int i, err; -inode_lock (dir);for (i = start; i < eof; i++) { +inode_lock (dir); dentry =__rpc_lookup_create_exclusive (parent, files[i].name); err =PTR_ERR (dentry); -if (IS_ERR (dentry)) +if (IS_ERR (dentry)) { +inode_unlock (dir); goto out_bad; + }switch (files[i].mode &S_IFMT ) {default :BUG ();
@@ -712,20 +714,20 @@ static int rpc_populate(struct dentry *p files[i].mode, files[i].i_fop, private); +inode_unlock (dir);break ;case S_IFDIR : err =__rpc_mkdir (dir, dentry, files[i].mode,NULL , private); +inode_unlock (dir); }if (err !=0 ) goto out_bad; } -inode_unlock (dir);return 0 ; out_bad: -inode_unlock (dir);printk (KERN_WARNING "%s: %s failed to populate directory %pd\n" , __FILE__, __func__, parent);return err;
@@ -741,25 +743,22 @@ static struct dentry *rpc_mkdir_populateinode_lock_nested (dir,I_MUTEX_PARENT ); dentry =__rpc_lookup_create_exclusive (parent, name); -if (IS_ERR (dentry)) - goto out; +if (IS_ERR (dentry)) { +inode_unlock (dir); +return dentry; + } error =__rpc_mkdir (dir, dentry, mode,NULL , private); +inode_unlock (dir);if (error !=0 ) - goto out_err; +return ERR_PTR (error);if (populate !=NULL ) { error =populate (dentry, args_populate);if (error) { -inode_unlock (dir);simple_recursive_removal (dentry,NULL );return ERR_PTR (error); } } -out: -inode_unlock (dir);return dentry; -out_err: - dentry =ERR_PTR (error); - goto out; } static int rpc_rmdir_depopulate(struct dentry *dentry,
Greg Kroah-Hartman
maintainerPATCH 1088/1102 sunrpc: fix use-after-free in __rpc_clnt_handle_event and __rpc_clnt_remove_pipedir
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luxiao Xu <[email protected]>
[ Upstream commit 932a8cf6abb2b2f8677b79153a823108d8861fe2 ]
Normal client creation goes through rpc_setup_pipedir(), which records clnt->pipefs_sb, but the mount-event path in __rpc_clnt_handle_event() calls rpc_setup_pipedir_sb() directly and never refreshes that field. The umount path also removes the directory without clearing clnt->pipefs_sb.
After a late pipefs mount or any remount, rpc_clnt_remove_pipedir() compares the current superblock against a stale pipefs_sb pointer and skips cleanup, leaving pipefs dentries whose inode private data still points at a freed rpc_clnt, leading to a potential use-after-free during subsequent rpc_info_open() or rpc_show_info() calls.
Fix this by properly updating clnt->pipefs_sb upon mount events and clearing it during unmount or failure paths.
--- net/sunrpc/clnt.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-)
net/sunrpc/clnt.c +17 -5
@@ -96,7 +96,10 @@ static void rpc_unregister_client(structstatic void __rpc_clnt_remove_pipedir (struct rpc_clnt *clnt) { -rpc_remove_client_dir (clnt); +if (clnt->pipefs_sb) { +rpc_remove_client_dir (clnt); + clnt->pipefs_sb =NULL ; + } }static void rpc_clnt_remove_pipedir (struct rpc_clnt *clnt)
@@ -177,19 +180,28 @@ static int rpc_clnt_skip_event(struct rp }static int __rpc_clnt_handle_event (struct rpc_clnt *clnt,unsigned long event, -struct super_block *sb) +struct super_block *sb) { +int err =0 ; +switch (event) {case RPC_PIPEFS_MOUNT : -return rpc_setup_pipedir_sb (sb, clnt); + clnt->pipefs_sb = sb; + err =rpc_setup_pipedir_sb (sb, clnt); +if (err) + clnt->pipefs_sb =NULL ; +break ;case RPC_PIPEFS_UMOUNT : -__rpc_clnt_remove_pipedir (clnt); +if (clnt->pipefs_sb == sb) { +__rpc_clnt_remove_pipedir (clnt); + clnt->pipefs_sb =NULL ; + }break ;default :printk (KERN_ERR "%s: unknown event: %ld\n" , __func__, event);return -ENOTSUPP ; } -return 0 ; +return err; } static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
Greg Kroah-Hartman
maintainerPATCH 1089/1102 rpcrdma: arm rn_done before publishing the notification
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 5b06f706374c37375bdff9d21cc10e61df925a92 ]
rpcrdma_rn_register() inserts @rn into rd_xa with xa_alloc() before storing the caller's callback in rn->rn_done. The xarray makes @rn reachable to rpcrdma_remove_one(), which walks rd_xa and invokes rn->rn_done(rn) for every registered notification. A device removal that races a fresh registration can therefore observe @rn with rn_done still NULL, because the notification objects are zero allocated by their owners, and call through a NULL function pointer.
Store rn->rn_done before xa_alloc() publishes @rn. The xarray's store-side and load-side ordering then guarantees that any CPU which finds @rn in rd_xa also observes the armed callback.
rpcrdma_rn_unregister() treats a non-NULL rn_done as the sentinel for a completed registration, so the early store must not survive a failed registration. Clear rn_done again when xa_alloc() fails. Were it left set, the failed-accept cleanup path would call rpcrdma_rn_unregister() on an @rn that was never inserted, erasing an unrelated rd_xa slot and underflowing rd_kref.
--- net/sunrpc/xprtrdma/ib_client.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
net/sunrpc/xprtrdma/ib_client.c +18 -6
@@ -52,8 +52,8 @@ static struct rpcrdma_device *rpcrdma_ge* is unregistered first. * * On failure, a negative errno is returned. rn->rn_done is left -* NULL on every failure path (it is assigned only after xa_alloc -* and kref_get have both succeeded), so the @rn may safely be +* NULL on every failure path (it is armed before xa_alloc but +* cleared again if xa_alloc fails), so the @rn may safely be * passed to rpcrdma_rn_unregister() without a separate * registered/unregistered flag in the caller. */
@@ -66,10 +66,21 @@ int rpcrdma_rn_register(struct ib_deviceif (!rd ||test_bit (RPCRDMA_RD_F_REMOVING , &rd->rd_flags))return -ENETUNREACH ; -if (xa_alloc (&rd->rd_xa, &rn->rn_index, rn, xa_limit_32b,GFP_KERNEL ) <0 ) +/* +* Arm rn_done before xa_alloc() publishes @rn: once @rn is +* visible in rd_xa, a concurrent rpcrdma_remove_one() can +* call rn->rn_done(), so the pointer must already be set. +* +* Restore NULL if xa_alloc() fails. rn_done doubles as the +* registration sentinel for rpcrdma_rn_unregister(); a stale +* value would unregister an @rn that was never inserted. +*/ + rn->rn_done = done; +if (xa_alloc (&rd->rd_xa, &rn->rn_index, rn, xa_limit_32b,GFP_KERNEL ) <0 ) { + rn->rn_done =NULL ;return -ENOMEM ; + }kref_get (&rd->rd_kref); - rn->rn_done = done;trace_rpcrdma_client_register (device, rn);return 0 ; }
@@ -102,8 +113,9 @@ void rpcrdma_rn_unregister(struct ib_dev/* * rn_done is the registration sentinel: rpcrdma_rn_register -* assigns it last, after xa_alloc and kref_get have both -* succeeded. A NULL rn_done means this notification was +* leaves it NULL on every failure path, clearing it again if +* xa_alloc fails, so a non-NULL rn_done marks a completed +* registration. A NULL rn_done means this notification was * never registered (or its registration failed) or has * already been unregistered, and the call is a no-op. * Without this guard, rn_index == 0 from a kzalloc'd
Greg Kroah-Hartman
maintainerPATCH 1090/1102 svcrdma: Release transport resources synchronously
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit bf94dea7fd4e6708d1a784be23db65eff84d82f1 ]
NFSD has always supported added network listeners. The new netlink protocol now enables the removal of listeners.
Olga noticed that if an RDMA listener is removed and immediately re-added, the deferred __svc_rdma_free() function might not have run yet, so some or all of the old listener's RDMA resources linger, which prevents a new listener on the same address from being created.
Also, svc_xprt_free() does a module_put() just after calling ->xpo_free(). That means if there is deferred work going on, the module could be unloaded before that work is even started, resulting in a UAF.
Neil asks:
Quoted 6 lines
What particular part of
__svc_rdma_free()needs to run in order for a subsequent registration to succeed?
Can that bit be run directory fromsvc_rdma_free()rather than be delayed?
(I know almost nothing about rdma so forgive me if the answers to these questions seems obvious)
The reasons I can recall are:
- Some of the transport tear-down work can sleep
- Releasing a cm_id is tricky and can deadlock
We might be able to mitigate the second issue with judicious application of transport reference counting.
Stable-dep-of: 4488e9129737 ("svcrdma: Reorder rpcrdma_rn_unregister before rdma_destroy_id")
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_transport.c +8 -11
@@ -613,12 +613,18 @@ static void svc_rdma_detach(struct svc_xrdma_disconnect (rdma->sc_cm_id); } -static void __svc_rdma_free (struct work_struct *work) +/** +* svc_rdma_free - Release class-specific transport resources +* @xprt: Generic svc transport object +*/ +static void svc_rdma_free (struct svc_xprt *xprt) {struct svcxprt_rdma *rdma = - container_of(work, struct svcxprt_rdma, sc_work); + container_of(xprt, struct svcxprt_rdma, sc_xprt);struct ib_device *device = rdma->sc_cm_id->device; +might_sleep (); +/* This blocks until the Completion Queues are empty */ if (rdma->sc_qp && !IS_ERR (rdma->sc_qp))ib_drain_qp (rdma->sc_qp);
@@ -651,15 +657,6 @@ static void __svc_rdma_free(struct work_kfree (rdma); } -static void svc_rdma_free (struct svc_xprt *xprt) -{ -struct svcxprt_rdma *rdma = - container_of(xprt, struct svcxprt_rdma, sc_xprt); - -INIT_WORK (&rdma->sc_work, __svc_rdma_free); -schedule_work (&rdma->sc_work); -} -static int svc_rdma_has_wspace (struct svc_xprt *xprt) { struct svcxprt_rdma *rdma =
Greg Kroah-Hartman
maintainerPATCH 1091/1102 svcrdma: Reorder rpcrdma_rn_unregister before rdma_destroy_id
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 4488e912973773d64368828acf3b8e39d93650ae ]
svc_rdma_free() caches rdma->sc_cm_id->device before teardown, then calls rdma_destroy_id(sc_cm_id) which frees the cm_id. rpcrdma_rn_unregister() follows, but between those two calls the transport's sc_rn entry is still installed in the device's rd_xa. A concurrent ib_unregister_device walk can dispatch svc_rdma_xprt_done() against the now-freed sc_cm_id.
Move rpcrdma_rn_unregister() before rdma_destroy_id() so the transport's notification entry is removed from the xarray before the cm_id it references is destroyed.
Also guard the sc_cm_id dereference with a NULL check: the following patches introduce paths that reach svc_rdma_free() with sc_cm_id == NULL (listener create failure, ADDR_CHANGE replacement failure).
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_transport.c +10 -3
@@ -621,10 +621,15 @@ static void svc_rdma_free(struct svc_xpr {struct svcxprt_rdma *rdma = container_of(xprt, struct svcxprt_rdma, sc_xprt); -struct ib_device *device = rdma->sc_cm_id->device; +struct ib_device *device;might_sleep (); +if (!rdma->sc_cm_id) + goto out_free; + + device = rdma->sc_cm_id->device; +/* This blocks until the Completion Queues are empty */ if (rdma->sc_qp && !IS_ERR (rdma->sc_qp))ib_drain_qp (rdma->sc_qp);
@@ -649,11 +654,13 @@ static void svc_rdma_free(struct svc_xprif (rdma->sc_pd && !IS_ERR (rdma->sc_pd))ib_dealloc_pd (rdma->sc_pd); +if (!test_bit (XPT_LISTENER , &rdma->sc_xprt.xpt_flags)) +rpcrdma_rn_unregister (device, &rdma->sc_rn); +/* Destroy the CM ID */ rdma_destroy_id (rdma->sc_cm_id); -if (!test_bit (XPT_LISTENER , &rdma->sc_xprt.xpt_flags)) -rpcrdma_rn_unregister (device, &rdma->sc_rn); +out_free:kfree (rdma); }
Greg Kroah-Hartman
maintainerPATCH 1092/1102 sunrpc: Add a helper to derive maxpages from sv_max_mesg
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit eff042ddf4b9587fa7394d502b93e06ec6015177 ]
This page count is to be used to allocate various arrays of pages and bio_vecs, replacing the fixed RPCSVC_MAXPAGES value.
The documenting comment is somewhat stale -- of course NFSv4 COMPOUND procedures may have multiple payloads.
Stable-dep-of: 9808eb765666 ("svcrdma: Reject Write/Reply chunks with segcount 0")
--- include/linux/sunrpc/svc.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
include/linux/sunrpc/svc.h +17 -0
@@ -163,6 +163,23 @@ extern u32 svc_max_payload(const struct#define RPCSVC_MAXPAGES ((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE \ + 2 + 1) +/** +* svc_serv_maxpages - maximum count of pages needed for one RPC message +* @serv: RPC service context +* +* Returns a count of pages or vectors that can hold the maximum +* size RPC message for @serv. +* +* Each request/reply pair can have at most one "payload", plus two +* pages, one for the request, and one for the reply. +* nfsd_splice_actor() might need an extra page when a READ payload +* is not page-aligned. +*/ +static inline unsigned long svc_serv_maxpages (const struct svc_serv *serv) +{ +return DIV_ROUND_UP (serv->sv_max_mesg,PAGE_SIZE ) +2 +1 ; +} +/* * The context of a single thread, including the request currently being * processed.
Greg Kroah-Hartman
maintainerPATCH 1094/1102 svcrdma: Reject Write/Reply chunks with segcount 0
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Mason <[email protected]>
[ Upstream commit 9808eb7656666acc7291bae9ab6b987bd16e47e0 ]
A peer can send a Write or Reply chunk whose segcount field is zero. xdr_check_write_chunk() only rejects segcount > rc_maxpages, so zero passes the range check, and xdr_inline_decode(stream, 0) returns the current (non-NULL) cursor without advancing. The function returns true and pcl_alloc_write() then links a struct svc_rdma_chunk with ch_segcount == 0 onto rc_write_pcl or rc_reply_pcl.
An earlier patch in this series made pcl_for_each_segment() safe for ch_segcount == 0, so this no longer drives the memory walk it used to. Rejecting the malformed frame at the decode boundary is still worthwhile as defense in depth: it keeps degenerate zero-segment chunks off the parsed chunk lists entirely, so any future consumer that walks ch_segments directly cannot observe one, and it makes the zero-floor easy to backport to trees where the macro change is more intrusive. RFC 8166 has no meaning for a Write/Reply chunk that describes no remote buffer, so no legitimate client is affected.
xdr_check_reply_chunk() funnels Reply chunks through xdr_check_write_chunk() and inherits the same rejection.
pcl_alloc_write() also links each chunk onto the parsed chunk list before filling its segment array. If a future change weakens the segcount-0 rejection, an incomplete chunk is visible to consumers during the fill loop. Reorder so that list_add_tail() follows the segment fill loop, ensuring only fully-populated chunks appear on the list.
--- net/sunrpc/xprtrdma/svc_rdma_pcl.c | 2 +- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_pcl.c +1 -1
@@ -213,7 +213,6 @@ bool pcl_alloc_write(struct svc_rdma_rec chunk =pcl_alloc_chunk (segcount,0 );if (!chunk)return false; -list_add_tail (&chunk->ch_list, &pcl->cl_chunks);for (j =0 ; j < segcount; j++) { segment = &chunk->ch_segments[j];
@@ -225,6 +224,7 @@ bool pcl_alloc_write(struct svc_rdma_rec chunk->ch_length += segment->rs_length; chunk->ch_segcount++; } +list_add_tail (&chunk->ch_list, &pcl->cl_chunks); }return true; }
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +6 -3
@@ -498,10 +498,13 @@ static bool xdr_check_write_chunk(structreturn false;/* Before trusting the segcount value enough to use it in -* a computation, perform a simple range check. This is an -* arbitrary but sensible limit (ie, not architectural). +* a computation, perform a simple range check. A zero +* segcount describes no remote buffer and is rejected so +* downstream consumers never see a degenerate ch_segcount==0 +* chunk. The upper bound is an arbitrary but sensible limit +* (ie, not architectural). */ -if (unlikely (segcount > rctxt->rc_maxpages)) +if (segcount ==0 ||unlikely (segcount > rctxt->rc_maxpages))return false; p = xdr_inline_decode(&rctxt->rc_stream,
Greg Kroah-Hartman
maintainerPATCH 1095/1102 sched_ext: Fix inverted ops.core_sched_before() invocation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
[ Upstream commit f7b6d128dd49a6eec09066ecfd29095f12588786 ]
scx_prio_less() implements prio_less() semantics - %true means that @a is the lower priority and should run after @b. ops.core_sched_before() is documented to return %true when @a should run before @b. scx_prio_less() returns the op's value as-is, inverting the documented semantics at runtime.
Call the op with the arguments swapped.
scx_qmap followed the wiring instead of the documentation and returned %true for the younger task, so the two inversions canceled out and it behaved as intended. Flip its comparison to match. scx_qmap is likely the only current user in or out of the kernel tree. Any scheduler written the same way needs the same flip, while schedulers following the documentation are fixed by this change.
--- kernel/sched/ext.c | 10 ++++++++-- tools/sched_ext/scx_qmap.bpf.c | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-)
kernel/sched/ext.c +8 -2
@@ -3173,19 +3173,25 @@ static struct task_struct *pick_task_scx* * When ops.core_sched_before() is enabled, @p->scx.core_sched_at is used to * implement FIFO ordering within each local DSQ. See pick_task_scx(). +* +* Return: %true if @a should run after @b. */ bool scx_prio_less (const struct task_struct *a,const struct task_struct *b,bool in_fi) {/* +* scx_prio_less() returns whether @a should run after @b while +* ops.core_sched_before() returns whether its first argument should run +* before the second. Swap the arguments. +* * The const qualifiers are dropped from task_struct pointers when * calling ops.core_sched_before(). Accesses are controlled by the * verifier. */ if (SCX_HAS_OP (core_sched_before) && !scx_rq_bypassing (task_rq (a)))return SCX_CALL_OP_2TASKS_RET (SCX_KF_REST , core_sched_before, - (struct task_struct *)a, - (struct task_struct *)b); + (struct task_struct *)b, + (struct task_struct *)a);else return time_after64 (a->scx.core_sched_at, b->scx.core_sched_at); }
tools/sched_ext/scx_qmap.bpf.c +1 -1
@@ -529,7 +529,7 @@ static s64 task_qdist(struct task_structbool BPF_STRUCT_OPS (qmap_core_sched_before ,struct task_struct *a,struct task_struct *b) { -return task_qdist (a) >task_qdist (b); +return task_qdist (a) <task_qdist (b); }void BPF_STRUCT_OPS (qmap_cpu_release ,s32 cpu,struct scx_cpu_release_args *args)
Greg Kroah-Hartman
maintainerPATCH 1096/1102 ocfs2: validate dx_root extent list fields during block read
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joseph Qi <[email protected]>
[ Upstream commit 775c17386a6fd695f999d4cda90e3931386570dd ]
Patch series "ocfs2: consolidate extent list validation into block read callbacks".
ocfs2 validates extent list fields (l_count, l_next_free_rec) at various points during extent tree traversal. This is fragile because each caller must remember to check for corrupted on-disk data before using it.
This series moves those checks into the block read validation callbacks (ocfs2_validate_dx_root and ocfs2_validate_extent_block), so corrupted fields are caught early at block read time. Redundant post-read checks are then removed.
This patch (of 4):
Move the extent list l_count validation from ocfs2_dx_dir_lookup_rec() into ocfs2_validate_dx_root(), so that corrupted on-disk fields are caught early at block read time rather than during directory lookups.
Additionally, add a l_next_free_rec <= l_count check to prevent out-of-bounds access when iterating over extent records.
Both checks are skipped for inline dx roots (OCFS2_DX_FLAG_INLINE), which use dr_entries instead of dr_list.
Stable-dep-of: bc70726ddad5 ("ocfs2: validate directory-index entry counts when reading metadata")
--- fs/ocfs2/dir.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
fs/ocfs2/dir.c +25 -1
@@ -580,7 +580,7 @@ static int ocfs2_validate_dx_root(structmlog (ML_ERROR ,"Checksum failed for dir index root block %llu\n" , (unsigned long long )bh->b_blocknr); -return ret; + goto bail; }if (!OCFS2_IS_VALID_DX_ROOT (dx_root)) {
@@ -588,8 +588,32 @@ static int ocfs2_validate_dx_root(struct"Dir Index Root # %llu has bad signature %.*s\n" , (unsigned long long )le64_to_cpu (dx_root->dr_blkno), 7, dx_root->dr_signature); + goto bail; } +if (!(dx_root->dr_flags &OCFS2_DX_FLAG_INLINE )) { +struct ocfs2_extent_list *el = &dx_root->dr_list; + +if (le16_to_cpu (el->l_count) !=ocfs2_extent_recs_per_dx_root (sb)) { + ret =ocfs2_error (sb, +"Dir Index Root # %llu has invalid l_count %u (expected %u)\n" , + (unsigned long long )le64_to_cpu (dx_root->dr_blkno), +le16_to_cpu (el->l_count), +ocfs2_extent_recs_per_dx_root (sb)); + goto bail; + } + +if (le16_to_cpu (el->l_next_free_rec) >le16_to_cpu (el->l_count)) { + ret =ocfs2_error (sb, +"Dir Index Root # %llu has invalid l_next_free_rec %u (l_count %u)\n" , + (unsigned long long )le64_to_cpu (dx_root->dr_blkno), +le16_to_cpu (el->l_next_free_rec), +le16_to_cpu (el->l_count)); + goto bail; + } + } + +bail:return ret; }
Greg Kroah-Hartman
maintainerPATCH 1097/1102 ocfs2: validate directory-index entry counts when reading metadata
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Doruk Tan Ozturk <[email protected]>
[ Upstream commit bc70726ddad53c7e9a9a85915bf2415b0d4f42f9 ]
ocfs2_validate_dx_leaf() and ocfs2_validate_dx_root() check the ECC and signature of an indexed-directory block before it reaches higher-level callers, but neither validator bounds the ocfs2_dx_entry_list counts against the capacity of the block that holds them.
ocfs2_dx_dir_search() then walks
for (i = 0; i < le16_to_cpu(entry_list->de_num_used); i++) dx_entry = &entry_list->de_entries[i];
over de_num_used entries with no bounds check. entry_list is either dx_leaf->dl_list (from ocfs2_read_dx_leaf) or, for an inline root, dx_root->dr_entries. A crafted on-disk image can set de_num_used (and de_count, which is the __counted_by_le() bound of de_entries) to 0xffff and make the walk read far past the end of the 4KB metadata block, giving a slab out-of-bounds read reachable from any path lookup, stat() or open() on an indexed directory once the image is mounted.
Commit 775c17386a6f ("ocfs2: validate dx_root extent list fields during block read") already bounds dr_list for the non-inline dx_root, but left the inline dr_entries path and the dx_leaf dl_list unchecked. Add the same read-time validation for both entry lists: de_count must equal the capacity of the block (ocfs2_dx_entries_per_leaf()/per_root()) and de_num_used must not exceed de_count, rejecting corrupted metadata with -EFSCORRUPTED before ocfs2_dx_dir_search() can walk an out-of-range entry array.
de_count is always written as exactly the block capacity when a leaf or inline root is formatted, so the equality check does not reject any valid image.
Found by 0sec automated security-research tooling (https://0sec.ai).
--- fs/ocfs2/dir.c | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-)
fs/ocfs2/dir.c +41 -4
@@ -611,6 +611,28 @@ static int ocfs2_validate_dx_root(struct le16_to_cpu(el->l_count)); goto bail; } + }else { +struct ocfs2_dx_entry_list *dl_list = &dx_root->dr_entries; + +if (le16_to_cpu (dl_list->de_count) != +ocfs2_dx_entries_per_root (sb)) { + ret =ocfs2_error (sb, +"Dir Index Root # %llu has invalid de_count %u (expected %u)\n" , + (unsigned long long )le64_to_cpu (dx_root->dr_blkno), +le16_to_cpu (dl_list->de_count), +ocfs2_dx_entries_per_root (sb)); + goto bail; + } + +if (le16_to_cpu (dl_list->de_num_used) > +le16_to_cpu (dl_list->de_count)) { + ret =ocfs2_error (sb, +"Dir Index Root # %llu has invalid de_num_used %u (de_count %u)\n" , + (unsigned long long )le64_to_cpu (dx_root->dr_blkno), +le16_to_cpu (dl_list->de_num_used), +le16_to_cpu (dl_list->de_count)); + goto bail; + } } bail:
@@ -650,10 +672,25 @@ static int ocfs2_validate_dx_leaf(structreturn ret; } -if (!OCFS2_IS_VALID_DX_LEAF (dx_leaf)) { - ret =ocfs2_error (sb,"Dir Index Leaf has bad signature %.*s\n" , -7 , dx_leaf->dl_signature); - } +if (!OCFS2_IS_VALID_DX_LEAF (dx_leaf)) +return ocfs2_error (sb,"Dir Index Leaf has bad signature %.*s\n" , +7 , dx_leaf->dl_signature); + +if (le16_to_cpu (dx_leaf->dl_list.de_count) != +ocfs2_dx_entries_per_leaf (sb)) +return ocfs2_error (sb, +"Dir Index Leaf # %llu has invalid de_count %u (expected %u)\n" , + (unsigned long long )le64_to_cpu (dx_leaf->dl_blkno), +le16_to_cpu (dx_leaf->dl_list.de_count), +ocfs2_dx_entries_per_leaf (sb)); + +if (le16_to_cpu (dx_leaf->dl_list.de_num_used) > +le16_to_cpu (dx_leaf->dl_list.de_count)) +return ocfs2_error (sb, +"Dir Index Leaf # %llu has invalid de_num_used %u (de_count %u)\n" , + (unsigned long long )le64_to_cpu (dx_leaf->dl_blkno), +le16_to_cpu (dx_leaf->dl_list.de_num_used), +le16_to_cpu (dx_leaf->dl_list.de_count));return ret; }
Greg Kroah-Hartman
maintainerPATCH 1098/1102 mm, hugetlb: increment the number of pages to be reset on HVO
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oscar Salvador <[email protected]>
commit 274fe92de2c4e50dbfd1b30070b4f6d8a27b388a upstream.
commit 4eeec8c89a0c ("mm: move hugetlb specific things in folio to page[3]") shifted hugetlb specific stuff, and now mapping overlaps _hugetlb_cgroup field.
Upon restoring the vmemmap for HVO, only the first two tail pages are reset, and this causes the check in free_tail_page_prepare() to fail as it finds an unexpected mapping value in some tails.
Increment the number of pages to be reset to 4 (head + 3 tail pages)
--- mm/hugetlb_vmemmap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
mm/hugetlb_vmemmap.c +3 -3
@@ -238,11 +238,11 @@ static void vmemmap_remap_pte(pte_t *pte* struct page, the special metadata (e.g. page->flags or page->mapping) * cannot copy to the tail struct page structs. The invalid value will be * checked in the free_tail_page_prepare(). In order to avoid the message -* of "corrupted mapping in tail page". We need to reset at least 3 (one -* head struct page struct and two tail struct page structs) struct page +* of "corrupted mapping in tail page". We need to reset at least 4 (one +* head struct page struct and three tail struct page structs) struct page * structs. */ -#define NR_RESET_STRUCT_PAGE 3 +#define NR_RESET_STRUCT_PAGE 4static inline void reset_struct_pages (struct page *start) {
Greg Kroah-Hartman
maintainerPATCH 1099/1102 net: cpsw: Execute ndo_set_rx_mode callback in a work queue
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kevin Hao <[email protected]>
commit 0b8c878d117319f2be34c8391a77e0f4d5c94d79 upstream.
Commit 1767bb2d47b7 ("ipv6: mcast: Don't hold RTNL for IPV6_ADD_MEMBERSHIP and MCAST_JOIN_GROUP.") removed the RTNL lock for IPV6_ADD_MEMBERSHIP and MCAST_JOIN_GROUP operations. However, this change triggered the following call trace on my BeagleBone Black board:
WARNING: net/8021q/vlan_core.c:236 at vlan_for_each+0x120/0x124, CPU#0: rpcbind/481 RTNL: assertion failed at net/8021q/vlan_core.c (236) Modules linked in: CPU: 0 UID: 997 PID: 481 Comm: rpcbind Not tainted 6.19.0-rc7-next-20260130-yocto-standard+ #35 PREEMPT Hardware name: Generic AM33XX (Flattened Device Tree) Call trace: unwind_backtrace from show_stack+0x28/0x2c show_stack from dump_stack_lvl+0x30/0x38 dump_stack_lvl from __warn+0xb8/0x11c __warn from warn_slowpath_fmt+0x130/0x194 warn_slowpath_fmt from vlan_for_each+0x120/0x124 vlan_for_each from cpsw_add_mc_addr+0x54/0x98 cpsw_add_mc_addr from __hw_addr_ref_sync_dev+0xc4/0xec __hw_addr_ref_sync_dev from __dev_mc_add+0x78/0x88 __dev_mc_add from igmp6_group_added+0x84/0xec igmp6_group_added from __ipv6_dev_mc_inc+0x1fc/0x2f0 __ipv6_dev_mc_inc from __ipv6_sock_mc_join+0x124/0x1b4 __ipv6_sock_mc_join from do_ipv6_setsockopt+0x84c/0x1168 do_ipv6_setsockopt from ipv6_setsockopt+0x88/0xc8 ipv6_setsockopt from do_sock_setsockopt+0xe8/0x19c do_sock_setsockopt from __sys_setsockopt+0x84/0xac __sys_setsockopt from ret_fast_syscall+0x0/0x54
This trace occurs because vlan_for_each() is called within cpsw_ndo_set_rx_mode(), which expects the RTNL lock to be held. Since modifying vlan_for_each() to operate without the RTNL lock is not straightforward, and because ndo_set_rx_mode() is invoked both with and without the RTNL lock across different code paths, simply adding rtnl_lock() in cpsw_ndo_set_rx_mode() is not a viable solution.
To resolve this issue, we opt to execute the actual processing within a work queue, following the approach used by the icssg-prueth driver.
Please note: To reproduce this issue, I manually reverted the changes to am335x-bone-common.dtsi from commit c477358e66a3 ("ARM: dts: am335x-bone:
switch to new cpsw switch drv") in order to revert to the legacy cpsw driver.
--- drivers/net/ethernet/ti/cpsw.c | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-)
drivers/net/ethernet/ti/cpsw.c +35 -6
@@ -305,12 +305,19 @@ static int cpsw_purge_all_mc(struct net_return 0 ; } -static void cpsw_ndo_set_rx_mode (struct net_device *ndev) +static void cpsw_ndo_set_rx_mode_work (struct work_struct *work) { -struct cpsw_priv *priv =netdev_priv (ndev); + struct cpsw_priv *priv = container_of(work, struct cpsw_priv, rx_mode_work);struct cpsw_common *cpsw = priv->cpsw; +struct net_device *ndev = priv->ndev;int slave_port =-1 ; +rtnl_lock (); +if (!netif_running (ndev)) + goto unlock_rtnl; + +netif_addr_lock_bh (ndev); +if (cpsw->data.dual_emac) slave_port = priv->emac_port +1 ;
@@ -318,7 +325,7 @@ static void cpsw_ndo_set_rx_mode(struct/* Enable promiscuous mode */ cpsw_set_promiscious (ndev, true);cpsw_ale_set_allmulti (cpsw->ale,IFF_ALLMULTI , slave_port); -return ; + goto unlock_addr; }else {/* Disable promiscuous mode */ cpsw_set_promiscious (ndev, false);
@@ -331,6 +338,18 @@ static void cpsw_ndo_set_rx_mode(struct/* add/remove mcast address either for real netdev or for vlan */ __hw_addr_ref_sync_dev (&ndev->mc, ndev, cpsw_add_mc_addr, cpsw_del_mc_addr); + +unlock_addr: +netif_addr_unlock_bh (ndev); +unlock_rtnl: +rtnl_unlock (); +} + +static void cpsw_ndo_set_rx_mode (struct net_device *ndev) +{ +struct cpsw_priv *priv =netdev_priv (ndev); + +schedule_work (&priv->rx_mode_work); }static unsigned int cpsw_rxbuf_total_len (unsigned int len)
@@ -1444,6 +1463,7 @@ static int cpsw_probe_dual_emac(struct c priv_sl2->ndev = ndev; priv_sl2->dev = &ndev->dev; priv_sl2->msg_enable =netif_msg_init (debug_level,CPSW_DEBUG ); +INIT_WORK (&priv_sl2->rx_mode_work, cpsw_ndo_set_rx_mode_work);if (is_valid_ether_addr (data->slave_data[1 ].mac_addr)) { memcpy(priv_sl2->mac_addr, data->slave_data[1].mac_addr,
@@ -1625,6 +1645,7 @@ static int cpsw_probe(struct platform_de priv->dev = dev; priv->msg_enable =netif_msg_init (debug_level,CPSW_DEBUG ); priv->emac_port =0 ; +INIT_WORK (&priv->rx_mode_work, cpsw_ndo_set_rx_mode_work);if (is_valid_ether_addr (data->slave_data[0 ].mac_addr)) {memcpy (priv->mac_addr, data->slave_data[0 ].mac_addr,ETH_ALEN );
@@ -1727,6 +1748,8 @@ clean_runtime_disable_ret:static void cpsw_remove (struct platform_device *pdev) {struct cpsw_common *cpsw =platform_get_drvdata (pdev); +struct net_device *ndev; +struct cpsw_priv *priv;int i, ret; ret =pm_runtime_resume_and_get (&pdev->dev);
@@ -1739,9 +1762,15 @@ static void cpsw_remove(struct platform_return ; } -for (i =0 ; i < cpsw->data.slaves; i++) -if (cpsw->slaves[i].ndev) -unregister_netdev (cpsw->slaves[i].ndev); +for (i =0 ; i < cpsw->data.slaves; i++) { + ndev = cpsw->slaves[i].ndev; +if (!ndev) +continue ; + + priv =netdev_priv (ndev); +unregister_netdev (ndev); +disable_work_sync (&priv->rx_mode_work); + }cpts_release (cpsw->cpts);cpdma_ctlr_destroy (cpsw->dma);
Greg Kroah-Hartman
maintainerPATCH 1100/1102 workqueue: Update documentation as per system_percpu_wq naming
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mallesh Koujalagi <[email protected]>
commit 4a91a33f15c634fb3477d122bdf1eef098d77ee3 upstream.
Update documentation to use "per-CPU workqueue" instead of "global workqueue" to match the system_wq to system_percpu_wq rename. The workqueue behavior remains unchanged; this just aligns terminology with the clearer naming.
--- include/linux/workqueue.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
include/linux/workqueue.h +8 -8
@@ -708,14 +708,14 @@ static inline bool schedule_work_on(int }/** -* schedule_work - put work task in global workqueue +* schedule_work - put work task in per-CPU workqueue * @work: job to be done * -* Returns %false if @work was already on the kernel-global workqueue and +* Returns %false if @work was already on the system per-CPU workqueue and * %true otherwise. * -* This puts a job in the kernel-global workqueue if it was not already -* queued and leaves it in the same position on the kernel-global +* This puts a job in the system per-CPU workqueue if it was not already +* queued and leaves it in the same position on the system per-CPU * workqueue otherwise. * * Shares the same memory-ordering properties of queue_work(), cf. the
@@ -792,12 +792,12 @@ extern void __warn_flushing_systemwide_w })/** -* schedule_delayed_work_on - queue work in global workqueue on CPU after delay +* schedule_delayed_work_on - queue work in per-CPU workqueue on CPU after delay * @cpu: cpu to use * @dwork: job to be done * @delay: number of jiffies to wait * -* After waiting for a given time this puts a job in the kernel-global +* After waiting for a given time this puts a job in the system per-CPU * workqueue on the specified CPU. */ static inline bool schedule_delayed_work_on(int cpu, struct delayed_work *dwork,
@@ -807,11 +807,11 @@ static inline bool schedule_delayed_work }/** -* schedule_delayed_work - put work task in global workqueue after delay +* schedule_delayed_work - put work task in per-CPU workqueue after delay * @dwork: job to be done * @delay: number of jiffies to wait or 0 for immediate execution * -* After waiting for a given time this puts a job in the kernel-global +* After waiting for a given time this puts a job in the system per-CPU * workqueue. */ static inline bool schedule_delayed_work(struct delayed_work *dwork,
Greg Kroah-Hartman
maintainerPATCH 1101/1102 SUNRPC: Restore NUMA_NO_NODE for svc thread allocations in global mode
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ameer Hamza <[email protected]>
commit 0574da29ae12be7714df217c4ce7ff6ba9b0c23b upstream.
Commit d57e43b72bf2 ("SUNRPC: Update svcxdr_init_decode() to call xdr_set_scratch_folio()") changed svc_pool_map_get_node() to return numa_mem_id() instead of NUMA_NO_NODE, because __folio_alloc_node() cannot accept NUMA_NO_NODE. That return value is not equivalent: it is evaluated in the context of the task creating the nfsd threads, once per thread created, and it is passed to kthread_create_on_node() and to the per-thread allocations in svc_prepare_thread().
Since commit d1a89197589c ("kthread: Default affine kthread to its preferred NUMA node"), the node argument of kthread_create_on_node() no longer only places the task structure and stack: a kthread created with a real node id normally affines itself to that node's CPUs when it is first woken to run its thread function. All nfsd threads are typically started together, by one task writing to /proc/fs/nfsd/threads, so under the default pool_mode=global each nfsd thread is now affined to the local-memory node of the CPU its creating iteration happened to run on - typically the same node for every thread. The CPUs of the other nodes are then unable to run nfsd at all, and the threads' allocations - svc_rqst structures, page pointer arrays, newly allocated task stacks, and the per-RPC pages allocated at run time - all prefer that one node.
Restore the NUMA_NO_NODE behaviour that global mode has had since commit 11fd165c68b7 ("sunrpc: use better NUMA affinities"), and handle NUMA_NO_NODE at the one call site that cannot take it by resolving it to numa_mem_id() there, exactly as alloc_pages_node() did for the scratch page before the conversion. The mapped percpu and pernode branches are unchanged. Unpooled services such as lockd and the NFS client callback service also take this fallback when no percpu or pernode map is active, restoring their thread placement in that case.
A bisect of a 2x NFS READ throughput regression between v6.17 and v6.18 converged on d57e43b72bf2. On the affected 4-node server every nfsd thread comes up with its CPU affinity restricted to the CPUs of a single node; with this change the threads are runnable on all CPUs again and the observed regression is resolved.
--- net/sunrpc/svc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/sunrpc/svc.c +4 -2
@@ -352,7 +352,7 @@ static int svc_pool_map_get_node(unsigneif (m->mode ==SVC_POOL_PERNODE )return m->pool_to[pidx]; } -return numa_mem_id (); +return NUMA_NO_NODE ; }/* * Set the given thread's cpus_allowed mask so that it
@@ -763,7 +763,9 @@ svc_prepare_thread(struct svc_serv *serv rqstp->rq_server = serv; rqstp->rq_pool = pool; - rqstp->rq_scratch_folio =__folio_alloc_node (GFP_KERNEL ,0 , node); + rqstp->rq_scratch_folio =__folio_alloc_node (GFP_KERNEL ,0 , + node ==NUMA_NO_NODE ? +numa_mem_id () : node);if (!rqstp->rq_scratch_folio) goto out_enomem;
Greg Kroah-Hartman
maintainerPATCH 1102/1102 sched/eevdf: Fix augmented max_slice
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vincent Guittot <[email protected]>
commit 9a8bc9bb4c3fb3218b4f151f98a722fbeb5b5c34 upstream.
Similarly to se->min_slice, init se->max_slice with se->slice before enqueueing the entity so the augmented callback computes it correctly at parent level.
--- kernel/sched/fair.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/sched/fair.c +2 -0
@@ -887,6 +887,8 @@ static void __enqueue_entity(struct cfs_avg_vruntime_add (cfs_rq, se); se->min_vruntime = se->vruntime; se->min_slice = se->slice; + se->max_slice = se->slice; +rb_add_augmented_cached (&se->run_node, &cfs_rq->tasks_timeline, __entity_less, &min_vruntime_cb); }
Hi Greg,
Am 17.09.2026 um 16:59 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.12.111 release. There are 1102 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
This rc1 kernel crashes on my 2-socket Ivy Bridge Xeon E5-2697v2 server when booting into it. Unfortunately, it does not seem to get to the point where it leaves something useful in the ERST, i.e. in /var/lib/systemd/pstore - nothing there...
So the only info I've got is a cell phone photo of the crash screen. I have put it here, in case anybody wants to have a look:
https://www.peters-netzplatz.de/download/IMG_20260917_204118_HDR.jpg
I have started to bisect between this rc1 and 6.12.110, which was fine. That might take me a day, though, so don't hold your breath.
Beste Grüße,
Peter Schneider
Signature · 8 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr. OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244 Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc https://keys.mailvelope.com/pks/lookup?op=get&[email protected] https://keys.mailvelope.com/pks/lookup?op=get&[email protected]
Hi!
Quoted 12 lines
Am 17.09.2026 um 16:59 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.12.111 release. There are 1102 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
This rc1 kernel crashes on my 2-socket Ivy Bridge Xeon E5-2697v2 server when booting into it. Unfortunately, it does not seem to get to the point where it leaves something useful in the ERST, i.e. in
/var/lib/systemd/pstore- nothing there...
Quoted 4 lines
So the only info I've got is a cell phone photo of the crash screen. I have put it here, in case anybody wants to have a look:
https://www.peters-netzplatz.de/download/IMG_20260917_204118_HDR.jpg
Seems to be identical / very similar to crash we see, and we have full log:
https://lava.ciplatform.org/scheduler/job/1510595
Best regards,
Pavel
Sasha Levin
maintainerQuoted 4 lines · Pavel Machek
Seems to be identical / very similar to crash we see, and we have full log:
It is the same one - the photo shows the same gather_bootmem_prealloc_parallel() fault as your LAVA log, and Peter's and Brett's bisects both land on it. Dropped from the 6.12 queue:
b1b7c045e808 ("mm/hugetlb: initialize gigantic bootmem hugepage
struct pages earlier")
Thanks both of you for correlating these - having the full oops next to the bisect made this a quick call.
Signature · 2 lines
Thanks, Sasha
Quoted 7 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.111 release. There are 1102 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 19 Sep 2026 15:13:49 +0000. Anything received after that time might be too late.
6.12.111-rc1 hangs on boot on this machine (AMD Ryzen 9 9950X).
Bisected:
git bisect start
# status: waiting for both 'good' and 'bad' commits
# bad: [18db24293f4d9b64614e0adf6dbe298073aa8860] Linux 6.12.111-rc1
git bisect bad 18db24293f4d9b64614e0adf6dbe298073aa8860
# status: waiting for 'good' commit(s), 'bad' commit known
# good: [fa5b06866b643cce7072a4e7c6be7ee3f0f1b95c] Linux 6.12.110
git bisect good fa5b06866b643cce7072a4e7c6be7ee3f0f1b95c
# good: [06d602e1997cdab008184b921c752f5b07fa16ef] Bluetooth: btintel: bound firmware ID by TLV length
git bisect good 06d602e1997cdab008184b921c752f5b07fa16ef
# good: [a126d69b9dd9f2cbd25d1672053851ae90ec549b] accel/ivpu: Limit firmware log name prints to field size git bisect good a126d69b9dd9f2cbd25d1672053851ae90ec549b
# good: [efe1f0c0257ae22c17fab4f1b55c1863a4d5bd98] ipv6: add some unlikely()/likely() clauses in ip6_output.c git bisect good efe1f0c0257ae22c17fab4f1b55c1863a4d5bd98
# bad: [8a1320dc29ad21696ba7f0aa99a3fabf295e74c5] NFSD: Prevent client use-after-free during delegation revoke git bisect bad 8a1320dc29ad21696ba7f0aa99a3fabf295e74c5
# bad: [5e4974a45323fd751aabfdd78c04457d231ac126] mm/slab: move and refactor __kmem_cache_alias()
git bisect bad 5e4974a45323fd751aabfdd78c04457d231ac126
# good: [562e14e2bbc8c9ad3c72c193a3afadc3a0cc1527] KVM: SEV: Track the GPA of the guest-controlled VMSA used for SNP guests git bisect good 562e14e2bbc8c9ad3c72c193a3afadc3a0cc1527
# good: [4eaf9e48d2a7b9a5067206d54ae260c0292d595f] mm/gup: fix always draining LRU caches in collect_longterm_unpinnable_folios() git bisect good 4eaf9e48d2a7b9a5067206d54ae260c0292d595f
# bad: [091b6f51c9330d9e2cacb8d6e4ab3e6e2e8d93fe] mm/mglru: reset page lru tier bits when activating
git bisect bad 091b6f51c9330d9e2cacb8d6e4ab3e6e2e8d93fe
# good: [8417718d642fbef80df65fb3369c3fc4b38cdbdd] pidfd: hold exec_update_lock around namespace ioctl
git bisect good 8417718d642fbef80df65fb3369c3fc4b38cdbdd
# bad: [22ae428b0045981bd19f8c75f700a67198062f32] mm/hugetlb: initialize gigantic bootmem hugepage struct pages earlier git bisect bad 22ae428b0045981bd19f8c75f700a67198062f32
# first 'bad' commit: [22ae428b0045981bd19f8c75f700a67198062f32] mm/hugetlb: initialize gigantic bootmem hugepage struct pages earlier
Brett
Am 17.09.2026 um 21:35 schrieb Brett A C Sheffield:
Quoted 1 line
# first 'bad' commit: [22ae428b0045981bd19f8c75f700a67198062f32] mm/hugetlb: initialize gigantic bootmem hugepage struct pages earlier
Yes, that's what I found, too.
When I revert 22ae428b0045981bd19f8c75f700a67198062f32 from rc1, the boot crash goes away and my machine boots successfully.
However, then I have another weirdo in the dmesg output:
[ 65.573304] ------------[ cut here ]------------ [ 65.573307] WARNING: CPU: 14 PID: 0 at kernel/sched/fair.c:5303 place_entity+0x13b/0x140 [ 65.573316] Modules linked in: uas usbhid usb_storage hid isci psmouse igb crc32_pclmul libsas aacraid serio_raw i2c_i801 ioatdma ahci ehci_pci i2c_mux ehci_hcd i2c_algo_bit libahci i2c_smbus scsi_transport_sas lpc_ich dca wmi [ 65.573336] CPU: 14 UID: 0 PID: 0 Comm: swapper/14 Not tainted 6.12.111-rc1+ #1 [ 65.573339] Hardware name: ASUSTeK COMPUTER INC. Z9PE-D16 Series/Z9PE-D16 Series, BIOS 5601 06/11/2015 [ 65.573342] RIP: 0010:place_entity+0x13b/0x140 [ 65.573345] Code: 41 5d 41 5e 5d 31 c0 31 d2 31 c9 31 f6 31 ff c3 cc cc cc cc be 02 00 00 00 48 c1 e9 0a 48 39 f1 48 0f 42 ce 48 8d 34 11 eb a9 <0f> 0b eb b6 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f [ 65.573347] RSP: 0018:ffffd09188287cd8 EFLAGS: 00010046 [ 65.573350] RAX: 0000000000000000 RBX: ffff8bc1cb32ce00 RCX: 00000000000003cb [ 65.573352] RDX: 0000000000000000 RSI: 00000000000003cb RDI: 00000000002d0e7f [ 65.573353] RBP: ffffd09188287cf8 R08: 0000000000000000 R09: 0000000000000000 [ 65.573355] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000037e492a9 [ 65.573356] R13: ffff8be13f337280 R14: 0000000000000000 R15: 0000000000000000 [ 65.573357] FS: 0000000000000000(0000) GS:ffff8be13f300000(0000) knlGS:0000000000000000 [ 65.573359] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 65.573361] CR2: 0000650f5b7d2118 CR3: 000000208ccca006 CR4: 00000000001706f0 [ 65.573363] Call Trace: [ 65.573366] <TASK> [ 65.573368] reweight_entity+0x1d2/0x200 [ 65.573372] update_cfs_group+0xb4/0xf0 [ 65.573374] enqueue_task_fair+0x285/0x8f0 [ 65.573377] enqueue_task+0x3b/0x220 [ 65.573383] ttwu_do_activate+0x75/0x270 [ 65.573386] sched_ttwu_pending+0xfe/0x1e0 [ 65.573389] __flush_smp_call_function_queue+0x155/0x440 [ 65.573394] flush_smp_call_function_queue+0x37/0x80 [ 65.573397] do_idle+0x15d/0x2c0 [ 65.573401] ? complete+0x6d/0x80 [ 65.573406] cpu_startup_entry+0x29/0x30 [ 65.573409] start_secondary+0x119/0x140 [ 65.573414] common_startup_64+0x13e/0x141 [ 65.573420] </TASK> [ 65.573421] ---[ end trace 0000000000000000 ]---
Beste Grüße,
Peter Schneider
Signature · 8 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr. OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244 Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc https://keys.mailvelope.com/pks/lookup?op=get&[email protected] https://keys.mailvelope.com/pks/lookup?op=get&[email protected]
Am 17.09.2026 um 22:19 schrieb Peter Schneider:
Quoted 34 lines
Am 17.09.2026 um 21:35 schrieb Brett A C Sheffield:
Quoted 1 line
# first 'bad' commit: [22ae428b0045981bd19f8c75f700a67198062f32] mm/hugetlb: initialize gigantic bootmem hugepage struct pages earlierYes, that's what I found, too.
When I revert
22ae428b0045981bd19f8c75f700a67198062f32from rc1, the boot crash goes away and my machine boots successfully.However, then I have another weirdo in the dmesg output:
[ 65.573304] ------------[ cut here ]------------
[ 65.573307] WARNING: CPU: 14 PID: 0 atkernel/sched/fair.c:5303place_entity+0x13b/0x140
[ 65.573316] Modules linked in: uas usbhidusb_storagehid isci psmouse igbcrc32_pclmullibsas aacraidserio_rawi2c_i801ioatdma ahciehci_pcii2c_muxehci_hcdi2c_algo_bitlibahcii2c_smbusscsi_transport_saslpc_ichdca wmi [ 65.573336] CPU: 14 UID: 0 PID: 0 Comm: swapper/14 Not tainted 6.12.111-rc1+ #1
[ 65.573339] Hardware name: ASUSTeK COMPUTER INC. Z9PE-D16 Series/Z9PE-D16 Series, BIOS 5601 06/11/2015
[ 65.573342] RIP: 0010:place_entity+0x13b/0x140
[ 65.573345] Code: 41 5d 41 5e 5d 31 c0 31 d2 31 c9 31 f6 31 ff c3 cc cc cc cc be 02 00 00 00 48 c1 e9 0a 48 39 f1 48 0f 42 ce 48 8d 34 11 eb a9 <0f> 0b eb b6 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f [ 65.573347] RSP: 0018:ffffd09188287cd8 EFLAGS: 00010046
[ 65.573350] RAX: 0000000000000000 RBX:ffff8bc1cb32ce00RCX:00000000000003cb
[ 65.573352] RDX: 0000000000000000 RSI:00000000000003cbRDI:00000000002d0e7f
[ 65.573353] RBP:ffffd09188287cf8R08: 0000000000000000 R09: 0000000000000000
[ 65.573355] R10: 0000000000000000 R11: 0000000000000000 R12:0000000037e492a9
[ 65.573356] R13:ffff8be13f337280R14: 0000000000000000 R15: 0000000000000000
[ 65.573357] FS: 0000000000000000(0000) GS:ffff8be13f300000(0000) knlGS:0000000000000000
[ 65.573359] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 65.573361] CR2:0000650f5b7d2118CR3:000000208ccca006CR4:00000000001706f0
[ 65.573363] Call Trace:
[ 65.573366] <TASK>
[ 65.573368]reweight_entity+0x1d2/0x200
[ 65.573372]update_cfs_group+0xb4/0xf0
[ 65.573374]enqueue_task_fair+0x285/0x8f0
[ 65.573377]enqueue_task+0x3b/0x220
[ 65.573383]ttwu_do_activate+0x75/0x270
[ 65.573386]sched_ttwu_pending+0xfe/0x1e0
[ 65.573389]__flush_smp_call_function_queue+0x155/0x440
Quoted 9 lines
[ 65.573394]
flush_smp_call_function_queue+0x37/0x80[ 65.573397]do_idle+0x15d/0x2c0
[ 65.573401] ?complete+0x6d/0x80
[ 65.573406]cpu_startup_entry+0x29/0x30
[ 65.573409]start_secondary+0x119/0x140
[ 65.573414]common_startup_64+0x13e/0x141[ 65.573420] </TASK>
[ 65.573421] ---[ end trace 0000000000000000 ]---
So I have bisected this warning, and the first bad commit is
[af5775004c9c02f37be06d2035a056b6abb1cb6c] sched/fair: Fix EEVDF entity placement bug causing scheduling lag
Trying to revert this from 6.12.111-rc1 however resulted in some conflicts I was unable to resolve. There are other dependencies like:
Stable-dep-of: 51b0e68cfa0a ("sched/eevdf: Fix rb augmented with multi fields"), which is [09cd469c733035b01b445a6f916e8ea425330c45] in linux-next-rc) and also [3bc70680c7ab333ed00a5e1fe33ed669c44d5544] ("sched/fair: Fix lag clamp").
This is my bisect log:
root@linus:/usr/src/linux-stable-rc# cat my_bisect.log git bisect start # Status: warte auf guten und schlechten Commit # bad: [ae53f4b7c7f60eca321af54b4ada3f24082c242e] Revert "mm/hugetlb: initialize gigantic bootmem hugepage struct pages earlier" git bisect bad ae53f4b7c7f60eca321af54b4ada3f24082c242e # Status: warte auf gute(n) Commit(s), schlechter Commit bekannt # good: [fa5b06866b643cce7072a4e7c6be7ee3f0f1b95c] Linux 6.12.110 git bisect good fa5b06866b643cce7072a4e7c6be7ee3f0f1b95c # good: [0b70c4d3654f89b7fdfcae684ea7371fbc7de72c] Bluetooth: hci_core: Fix race condition during device registration git bisect good 0b70c4d3654f89b7fdfcae684ea7371fbc7de72c # bad: [818d7fa0a53b82f2e8db56aac615d08d3da72548] ASoC: sprd: validate compress buffer sizes against fixed allocations git bisect bad 818d7fa0a53b82f2e8db56aac615d08d3da72548 # good: [56c7ca9d7037acb880cad9eae68c479cc4d6f200] net/mlx5: E-Switch: fix use-after-free in mlx5_eswitch_termtbl_put git bisect good 56c7ca9d7037acb880cad9eae68c479cc4d6f200 # good: [03d4a3b6610bc9f86d8ec4d9a75a2d5376b47bb7] net: ks8851: Fix receiver error in 100BASE-TX mode following software power-down git bisect good 03d4a3b6610bc9f86d8ec4d9a75a2d5376b47bb7 # bad: [1d8ee4f560be8b347173dc7c07fd41e4baa318d7] net: stmmac: add stmmac_tso_header_size() git bisect bad 1d8ee4f560be8b347173dc7c07fd41e4baa318d7 # bad: [af5775004c9c02f37be06d2035a056b6abb1cb6c] sched/fair: Fix EEVDF entity placement bug causing scheduling lag git bisect bad af5775004c9c02f37be06d2035a056b6abb1cb6c # good: [7b6988750feec0bd3da256e9fe80244fa358ab74] net: stmmac: initialize ptp_lock at probe time git bisect good 7b6988750feec0bd3da256e9fe80244fa358ab74 # good: [52080cefeb2f454cdb14fb7a052d35566609c1ad] perf/core: Check sample_type in perf_sample_save_callchain git bisect good 52080cefeb2f454cdb14fb7a052d35566609c1ad # good: [edeca3f32161462596e6e03e69a3443dd80c5603] perf/x86/intel/ds: Remove redundant assignments to sample.period git bisect good edeca3f32161462596e6e03e69a3443dd80c5603 # good: [fc602eb1451422bf0e4798ac68f8c15904e0b7aa] perf/x86/intel: Correct pt_regs->flags update for PEBS path git bisect good fc602eb1451422bf0e4798ac68f8c15904e0b7aa # first bad commit: [af5775004c9c02f37be06d2035a056b6abb1cb6c] sched/fair: Fix EEVDF entity placement bug causing scheduling lag
Beste Grüße,
Peter Schneider
Signature · 3 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr.
Sasha Levin
maintainerQuoted 4 lines · Peter Schneider
So I have bisected this warning, and the first bad commit is
[
af5775004c9c02f37be06d2035a056b6abb1cb6c] sched/fair: Fix EEVDF entity placement bug causing scheduling lag
Thank you - a second bisect on top of a reverted tree is real work, and it was the right call. Dropped from the 6.12 queue:
6d71a9c61604 ("sched/fair: Fix EEVDF entity placement bug causing
scheduling lag")
Quoted 2 lines
Trying to revert this from 6.12.111-rc1 however resulted in some conflicts I was unable to resolve. There are other dependencies like:
Right, which is why the three patches stacked on top of it came out at the same time:
6e3c0a4e1ad1 ("sched/fair: Fix lag clamp") 51b0e68cfa0a ("sched/eevdf: Fix rb augmented with multi fields") 9a8bc9bb4c3f ("sched/eevdf: Fix augmented max_slice")
Some background on why this only bites 6.12: the WARN_ON_ONCE(!load) you hit needs 4423af84b297 ("sched/fair: optimize the PLACE_LAG when se->vlag is zero") and c70fc32f4443 ("sched/fair: Adhere to place_entity() constraints", which is a Fixes: for exactly this commit) to be shut up, and 6.12 has neither. More to the point, upstream has since reverted 6d71a9c61604 outright - 101f3498b4bd ("sched/fair: Revert 6d71a9c61604 ...") from January, which concludes the original commit "was wrong!" because avg_vruntime() already accounts for cfs_rq->curr when it is on_rq. 6.12 only ever picked it up as a dependency of the eevdf fixes above, so carrying placement math that mainline has disowned is not something we want here.
Signature · 2 lines
Thanks, Sasha
Am 18.09.2026 um 17:54 schrieb Sasha Levin:
Quoted 15 lines · Peter Schneider
Quoted 4 lines
So I have bisected this warning, and the first bad commit is
[
af5775004c9c02f37be06d2035a056b6abb1cb6c] sched/fair: Fix EEVDF entity placement bug causing scheduling lagThank you - a second bisect on top of a reverted tree is real work, and it was the right call. Dropped from the 6.12 queue:
6d71a9c61604("sched/fair: Fix EEVDF entity placement bug causing
scheduling lag")Quoted 2 lines
Trying to revert this from 6.12.111-rc1 however resulted in some conflicts I was unable to resolve. There are other dependencies like:
Quoted 6 lines
Right, which is why the three patches stacked on top of it came out at the same time:
6e3c0a4e1ad1("sched/fair: Fix lag clamp")51b0e68cfa0a("sched/eevdf: Fix rb augmented with multi fields")9a8bc9bb4c3f("sched/eevdf: Fix augmentedmax_slice")
Ah ok, that third one I missed, so it didn't work out for me.
Quoted 10 lines
Some background on why this only bites 6.12: the
WARN_ON_ONCE(!load)you hit needs4423af84b297("sched/fair: optimize thePLACE_LAGwhense->vlagis zero") andc70fc32f4443("sched/fair: Adhere toplace_entity()constraints", which is a Fixes: for exactly this commit) to be shut up, and 6.12 has neither. More to the point, upstream has since reverted6d71a9c61604outright -101f3498b4bd("sched/fair: Revert6d71a9c61604...") from January, which concludes the original commit "was wrong!" becauseavg_vruntime()already accounts forcfs_rq->currwhen it ison_rq. 6.12 only ever picked it up as a dependency of the eevdf fixes above, so carrying placement math that mainline has disowned is not something we want here.
Sounds complicated; no wonder I was unable to figure this out on my own.
Beste Grüße,
Peter Schneider
Signature · 8 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr. OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244 Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc https://keys.mailvelope.com/pks/lookup?op=get&[email protected] https://keys.mailvelope.com/pks/lookup?op=get&[email protected]
Sasha Levin
maintainerQuoted 2 lines · Peter Schneider
When I revert
22ae428b0045981bd19f8c75f700a67198062f32from rc1, the boot crash goes away and my machine boots successfully.
Thanks for confirming, and for the crash photo from the Ivy Bridge box in your earlier mail - that is the same bug. Dropped from the 6.12 queue:
b1b7c045e808 ("mm/hugetlb: initialize gigantic bootmem hugepage
struct pages earlier")
The backport relocates gather_bootmem_prealloc() into page_alloc_init_late(), which on 6.12 runs before anything has initialized the per-node huge_boot_pages[] list heads - upstream that is done unconditionally in hugetlb_bootmem_alloc() since v6.15, which 6.12 does not have. Any CONFIG_HUGETLB_PAGE=y kernel booted without hugepagesz=/hugepages= walks an all-zero list head and faults.
Quoted 3 lines
However, then I have another weirdo in the dmesg output:
[ 65.573307] WARNING: CPU: 14 PID: 0 at kernel/sched/fair.c:5303
place_entity+0x13b/0x140
That one is a separate 6.12 problem and your follow-up bisect nailed it - I've replied there with what was dropped for it.
Signature · 2 lines
Thanks, Sasha
Sasha Levin
maintainerQuoted 1 line · Brett A C Sheffield
6.12.111-rc1 hangs on boot on this machine (AMD Ryzen 9 9950X).
[...]
Quoted 2 lines
# first 'bad' commit: [22ae428b0045981bd19f8c75f700a67198062f32] mm/hugetlb: initialize gigantic bootmem hugepage struct pages earlier
Thanks for the bisect, it lands exactly on the problem. Dropped from the 6.12 queue:
b1b7c045e808 ("mm/hugetlb: initialize gigantic bootmem hugepage
struct pages earlier")
For the record, why it breaks only on 6.12: the backport moves gather_bootmem_prealloc() out of hugetlb_init() (a subsys_initcall) into page_alloc_init_late(), which runs well before do_basic_setup(). Upstream that reordering is safe because since v6.15 the per-node huge_boot_pages[] list heads are initialized unconditionally and very early in hugetlb_bootmem_alloc(). 6.12 has neither that function nor the commits that added it, so the only INIT_LIST_HEAD() of those lists is the lazy loop in hugetlb_hstate_alloc_pages(), reached early only when a gigantic hugepage is requested on the command line. Boot a CONFIG_HUGETLB_PAGE=y kernel without hugepagesz=/hugepages= and the relocated code walks an all-zero list head, so the first iteration dereferences NULL.
Nothing else in the queue depended on it, so it comes out on its own.
Signature · 2 lines
Thanks, Sasha
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.12.111 release. There are 1102 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
We get build errors here and some runtime failures here:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6.12.y
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/jobs/16571866335drivers/net/ethernet/ti/cpsw.c seems to have compile problem:
In file included from ./include/linux/container_of.h:5,
from ./include/linux/kernel.h:22,
from drivers/net/ethernet/ti/cpsw.c:9:drivers/net/ethernet/ti/cpsw.c: In function 'cpsw_ndo_set_rx_mode_work':./include/linux/container_of.h:20:54: error: 'struct cpsw_priv' has no member named 'rx_mode_work'
I don't have good diagnostic for runtime problem on arm. Example is here:
Working FDT set to baeea000
Starting kernel ...
(hang)
https://lava.ciplatform.org/scheduler/job/1510588
It is better on x86:
ogin-action: kernel 'oops'
L323[login-action] Waiting for messages, (timeout 00:01:59) L324Waiting using forced prompt support (timeout 00:01:00)
L325[ 0.264887] Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI L326[ 0.264887] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.111-rc1+ #1 L327[ 0.264887] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1~bpo13+1 04/01/2014 L328[ 0.264887] RIP: 0010:gather_bootmem_prealloc_parallel+0x117/0x250 L329[ 0.264887] Code: ec 0f 84 f3 00 00 00 4c 89 ff 41 b8 00 00 00 80 4d 01 e0 0f 82 30 01 00 00 48 c7 c0 00 00 00 80 48 2b 05 84 d2 66 ff 49 01 c0 <4d> 8b 7c 24 10 49 c1 e8 0c 49 c1 e0 06 4c 03 05 5d d2 66 ff 4d 89 L330[ 0.264887] RSP: 0018:ffffa93040013d70 EFLAGS: 00010206 L331[ 0.264887] RAX: 0000701800000000 RBX: 0000000000000001 RCX: 0000000000000001 L332[ 0.264887] RDX: ffffa93040013d80 RSI: 0000000000000001 RDI: 0000000000000000 L333[ 0.264887] RBP: 0000000000000000 R08: 0000701880000000 R09: 0000000000000001 L334[ 0.264887] R10: ffffa93040013ef8 R11: 0000000000000100 R12: 0000000000000000 L335[ 0.264887] R13: ffffffff9354ec20 R14: 0000000000000000 R15: 0000000000000000 L336[ 0.264887] FS: 0000000000000000(0000) GS:ffff8fe7bec00000(0000) knlGS:0000000000000000 L337[ 0.264887] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 L338[ 0.264887] CR2: 0000000000000010 CR3: 0000000016e2e000 CR4: 0000000000750ef0 L339[ 0.264887] PKRU: 55555554 L340[ 0.264887] Call Trace: L341[ 0.264887] <TASK> L342[ 0.264887] padata_do_multithreaded+0x332/0x370 L343[ 0.264887] hugetlb_bootmem_struct_page_init+0x6f/0x90 L344[ 0.264887] ? __pfx_gather_bootmem_prealloc_parallel+0x10/0x10 L345[ 0.264887] page_alloc_init_late+0xf/0x300 L346[ 0.264887] kernel_init_freeable+0xef/0x2d0 L347[ 0.264887] ? __pfx_kernel_init+0x10/0x10 L348[ 0.264887] kernel_init+0x15/0x1b0 L349[ 0.264887] ret_from_fork+0x2f/0x50 L350[ 0.264887] ? __pfx_kernel_init+0x10/0x10 L351[ 0.264887] ret_from_fork_asm+0x1a/0x30 L352[ 0.264887] </TASK>
https://lava.ciplatform.org/scheduler/job/1510595
Best regards,
Pavel
Quoted 11 lines · Pavel Machek
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.12.111 release. There are 1102 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
We get build errors here and some runtime failures here:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6.12.y
Quoted 8 lines
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/jobs/16571866335
drivers/net/ethernet/ti/cpsw.cseems to have compile problem:In file included from
./include/linux/container_of.h:5,from ./include/linux/kernel.h:22, from drivers/net/ethernet/ti/cpsw.c:9:
drivers/net/ethernet/ti/cpsw.c: In function 'cpsw_ndo_set_rx_mode_work':./include/linux/container_of.h:20:54: error: 'structcpsw_priv' has no member named 'rx_mode_work'
FWIW, I am seeing the same build error for ARM.
Jon
Signature · 1 line
nvpublic
Sasha Levin
maintainerQuoted 1 line · Jon Hunter
FWIW, I am seeing the same build error for ARM.
Thanks for the confirmation. Dropped from the 6.12 and 6.6 queues:
0b8c878d1173 ("net: cpsw: Execute ndo_set_rx_mode callback in a work
queue")
The patch only touches drivers/net/ethernet/ti/cpsw.c, but the 'struct work_struct rx_mode_work' member it dereferences is added to cpsw_priv.h by a separate commit, c0b5dc73a38f ("net: cpsw_new: Execute ndo_set_rx_mode callback in a work queue"), which is not queued anywhere. 6.6 also lacks disable_work_sync(), so it had a second reason to fail there.
Signature · 2 lines
Thanks, Sasha
Sasha Levin
maintainerQuoted 3 lines · Pavel Machek
drivers/net/ethernet/ti/cpsw.c: In function 'cpsw_ndo_set_rx_mode_work':./include/linux/container_of.h:20:54: error: 'structcpsw_priv' has no member named 'rx_mode_work'
Dropped from the 6.12 and 6.6 queues:
0b8c878d1173 ("net: cpsw: Execute ndo_set_rx_mode callback in a work
queue")
It only touches drivers/net/ethernet/ti/cpsw.c, but the 'struct work_struct rx_mode_work' member it uses is added to cpsw_priv.h by a different commit, c0b5dc73a38f ("net: cpsw_new: Execute ndo_set_rx_mode callback in a work queue"), which isn't queued anywhere. 6.6 additionally lacks disable_work_sync(), so it could not have built there either.
Quoted 5 lines
I don't have good diagnostic for runtime problem on arm. Example is here:
(hang)It is better on x86:
L328[ 0.264887] RIP: 0010:gather_bootmem_prealloc_parallel+0x117/0x250
[...]
Quoted 1 line
L343[ 0.264887]
hugetlb_bootmem_struct_page_init+0x6f/0x90
That one is a second, independent problem, also dropped from the 6.12 queue:
b1b7c045e808 ("mm/hugetlb: initialize gigantic bootmem hugepage
struct pages earlier")
The backport moves gather_bootmem_prealloc() into page_alloc_init_late(), which on 6.12 runs before anything initializes the per-node huge_boot_pages[] list heads - upstream that happens unconditionally in hugetlb_bootmem_alloc() since v6.15, which 6.12 does not have. Without hugepagesz=/hugepages= on the command line the list head is still all zeroes, so the first list_for_each_entry() iteration yields NULL and m->hstate faults - which matches your log exactly (CR2 0000000000000010, 'mov r15,[r12+0x10]' with r12 == 0, .hstate sitting at offset 0x10 in struct huge_bootmem_page).
Two independent bisects from Brett Sheffield and Peter Schneider landed on the same commit.
Signature · 2 lines
Thanks, Sasha
Re: [PATCH 6.18 0000/1250] 6.18.53-rc1 review
In reply to Greg Kroah-HartmanBuild tested in our x86,arm64,loongarch,riscv config successfully without error.
Best Regards
Wentao Guan
Log:
Linux version 6.18.53-rc1-g644a9858f3fc (guanwentao@uos-PC) (aarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #2 SMP PREEMPT_DYNAMIC Fri Sep 18 05:42:43 CST 2026 Linux version 6.18.53-rc1-g644a9858f3fc (guanwentao@uos-PC) (loongarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #3 SMP PREEMPT_DYNAMIC Fri Sep 18 06:00:26 CST 2026 Linux version 6.18.53-rc1+ (guanwentao@uos-PC) (riscv64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #4 SMP PREEMPT Fri Sep 18 06:17:35 CST 2026 Linux version 6.18.53-rc1-g644a9858f3fc (guanwentao@uos-PC) (gcc (Deepin 12.3.0-17deepin18) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #1 SMP PREEMPT_DYNAMIC Fri Sep 18 05:18:12 CST 2026
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.111 release. There are 1102 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 19 Sep 2026 15:13:49 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.111-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.thanks,
greg k-h
I tested 6.12.110 + up-to-date stable-queue as of this writing, commit 01b20bb84b994fdcda64fd07a66ba84c85d0168f, on my Lenovo ThinkPad T14 Gen 1. (If necessary, I can explain later how my workflow ends up giving this kernel the version number "6.12.111-pre158", but hopefully that detail won't be relevant.)
I'm seeing different kernel warnings than the other ones that have been posted in this thread so far. Here is one of them; I can reproduce this with the following steps:
1. Boot
2. Log in
3. Wait 30 seconds or so
4. Close the laptop lid and wait for it to suspend
5. Open the laptop lid and unlock my desktop
6. Check dmesg and see if there's a warning there. If so, I'm done. If not, repeat steps 4 and 5.
Sometimes the warning appears after only 1 suspend/wake cycle, but it always shows up no later than the second suspend/wake cycle.
I'll verify that this still reproduces with a more minimal config, then I'll go ahead and bisect...
(On this ThinkPad I'm running Debian trixie and GNOME, in case it matters.)
[ 98.363836] ------------[ cut here ]------------ [ 98.363843] RTNL: assertion failed at net/ipv6/mcast.c (1014) [ 98.363896] WARNING: CPU: 6 PID: 961 at net/ipv6/mcast.c:1014 __ipv6_dev_mc_dec+0x17b/0x190 [ipv6] [ 98.363977] Modules linked in: sd_mod scsi_mod scsi_common snd_seq_dummy snd_hrtimer snd_seq snd_seq_device rfcomm algif_hash algif_skcipher af_alg qrtr bnep snd_soc_skl_hda_dsp snd_soc_intel_sof_board_helpers snd_sof_probes snd_soc_intel_hda_dsp_common intel_uncore_frequency intel_uncore_frequency_common binfmt_misc intel_pmc_core_pltdrv intel_pmc_core intel_vsec pmt_telemetry pmt_class x86_pkg_temp_thermal nls_ascii nls_cp437 snd_hda_codec_realtek vfat fat snd_hda_codec_generic snd_hda_scodec_component snd_soc_dmic snd_sof_pci_intel_cnl snd_sof_intel_hda_generic soundwire_intel soundwire_cadence snd_sof_intel_hda_common snd_soc_hdac_hda intel_powerclamp snd_sof_intel_hda_mlink coretemp snd_sof_intel_hda snd_hda_codec_hdmi snd_sof_pci kvm_intel snd_sof_xtensa_dsp snd_sof snd_sof_utils snd_soc_acpi_intel_match kvm soundwire_generic_allocation snd_soc_acpi soundwire_bus iwlmvm snd_soc_avs irqbypass snd_soc_hda_codec snd_hda_ext_core crct10dif_pclmul mac80211 snd_soc_core ghash_clmulni_intel mei_wdt mei_hdcp [ 98.364043] sha512_ssse3 intel_rapl_msr sha256_ssse3 mei_pxp sha1_ssse3 uvcvideo snd_compress snd_pcm_dmaengine aesni_intel libarc4 snd_hda_intel uvc crypto_simd videobuf2_vmalloc snd_intel_dspcfg cryptd btusb videobuf2_memops videobuf2_v4l2 btrtl snd_intel_sdw_acpi btintel rapl btbcm snd_hda_codec videodev intel_cstate iwlwifi btmtk processor_thermal_device_pci_legacy snd_hda_core videobuf2_common rmi_smbus processor_thermal_device intel_uncore snd_ctl_led pcspkr processor_thermal_wt_hint mc bluetooth rmi_core processor_thermal_rfim snd_hwdep processor_thermal_rapl cfg80211 think_lmi intel_wmi_thunderbolt snd_pcm intel_rapl_common firmware_attributes_class thinkpad_acpi ee1004 snd_timer processor_thermal_wt_req crc16 mei_me nvram wmi_bmof processor_thermal_power_floor platform_profile mei processor_thermal_mbox snd intel_soc_dts_iosf intel_pch_thermal int3403_thermal joydev soundcore int340x_thermal_zone ac int3400_thermal intel_hid acpi_thermal_rel sparse_keymap button acpi_pad evdev msr i2c_dev parport_pc ppdev lp [ 98.364124] parport dm_mod nvme_fabrics efi_pstore configfs nfnetlink ip_tables x_tables ipv6 autofs4 xfs btrfs blake2b_generic raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor raid6_pq libcrc32c crc32c_generic raid1 raid0 linear md_mod hid_multitouch hid_generic usbhid hid i915 drm_buddy i2c_algo_bit iTCO_wdt drm_display_helper intel_pmc_bxt iTCO_vendor_support rtsx_pci_sdmmc watchdog ucsi_acpi mmc_core psmouse i2c_i801 cec typec_ucsi xhci_pci nvme video crc32_pclmul rc_core thunderbolt xhci_hcd e1000e crc32c_intel serio_raw roles nvme_core ttm i2c_smbus rtsx_pci typec battery wmi efivarfs [ 98.364208] CPU: 6 UID: 105 PID: 961 Comm: avahi-daemon Not tainted 6.12.111-pre158 #3 [ 98.364214] Hardware name: LENOVO 20S1S6D700/20S1S6D700, BIOS N2XET46W (1.36 ) 06/02/2026 [ 98.364217] RIP: 0010:__ipv6_dev_mc_dec+0x17b/0x190 [ipv6] [ 98.364291] Code: 88 f5 02 00 00 0f 85 c4 fe ff ff ba f6 03 00 00 48 c7 c6 30 8f 3b c1 48 c7 c7 58 7b 3b c1 c6 05 68 f5 02 00 01 e8 95 fd f5 e4 <0f> 0b e9 9e fe ff ff 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 90 [ 98.364296] RSP: 0018:ffffd3da8074b8c0 EFLAGS: 00010246 [ 98.364301] RAX: 0000000000000000 RBX: ffff8e5e03638800 RCX: 0000000000000000 [ 98.364304] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 [ 98.364307] RBP: ffff8e5e09238540 R08: 0000000000000000 R09: 0000000000000000 [ 98.364311] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8e5e2088ae80 [ 98.364314] R13: ffff8e5e03638800 R14: ffff8e5e03638a70 R15: 0000000000000000 [ 98.364318] FS: 00007f6719a89840(0000) GS:ffff8e652c500000(0000) knlGS:0000000000000000 [ 98.364322] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 98.364326] CR2: 00007f38ae7fcd58 CR3: 000000010b64c004 CR4: 00000000003726f0 [ 98.364329] Call Trace: [ 98.364334] <TASK> [ 98.364339] ipv6_sock_mc_drop+0x122/0x1e0 [ipv6] [ 98.364409] do_ipv6_setsockopt+0xb9b/0x1a30 [ipv6] [ 98.364479] ? __wake_up_sync_key+0x3b/0x60 [ 98.364486] ? sock_def_readable+0x42/0xc0 [ 98.364490] ? unix_dgram_sendmsg+0x5d5/0x9c0 [ 98.364499] ipv6_setsockopt+0x5e/0xa0 [ipv6] [ 98.364570] do_sock_setsockopt+0xb9/0x190 [ 98.364578] __sys_setsockopt+0x94/0xe0 [ 98.364584] __x64_sys_setsockopt+0x1f/0x40 [ 98.364589] do_syscall_64+0x82/0x1b0 [ 98.364595] ? syscall_exit_to_user_mode+0x32/0x190 [ 98.364601] ? do_syscall_64+0x8e/0x1b0 [ 98.364607] ? file_update_time+0x1b/0x90 [ 98.364615] ? pipe_write+0x424/0x670 [ 98.364623] ? vfs_write+0x3b6/0x450 [ 98.364630] ? arch_exit_to_user_mode_prepare.isra.0+0x1e/0x100 [ 98.364636] ? syscall_exit_to_user_mode+0x32/0x190 [ 98.364643] ? do_syscall_64+0x8e/0x1b0 [ 98.364649] ? do_syscall_64+0x8e/0x1b0 [ 98.364655] ? arch_exit_to_user_mode_prepare.isra.0+0x1e/0x100 [ 98.364661] ? syscall_exit_to_user_mode+0x32/0x190 [ 98.364667] ? do_syscall_64+0x8e/0x1b0 [ 98.364675] ? __sys_sendmsg+0x87/0xf0 [ 98.364681] ? arch_exit_to_user_mode_prepare.isra.0+0x1e/0x100 [ 98.364686] ? syscall_exit_to_user_mode+0x32/0x190 [ 98.364692] ? do_syscall_64+0x8e/0x1b0 [ 98.364698] ? do_syscall_64+0x8e/0x1b0 [ 98.364703] ? arch_exit_to_user_mode_prepare.isra.0+0x1e/0x100 [ 98.364708] ? syscall_exit_to_user_mode+0x32/0x190 [ 98.364714] ? do_syscall_64+0x8e/0x1b0 [ 98.364719] ? clear_bhb_loop+0x70/0xc0 [ 98.364726] ? clear_bhb_loop+0x70/0xc0 [ 98.364732] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 98.364738] RIP: 0033:0x7f6719c8fffa [ 98.364763] Code: 48 83 ec 10 48 63 c9 48 63 ff 45 89 c9 6a 2c e8 dc d3 f7 ff 48 83 c4 18 c3 0f 1f 80 00 00 00 00 49 89 ca b8 36 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 06 c3 0f 1f 44 00 00 48 8b 15 e1 2d 0d 00 f7 [ 98.364767] RSP: 002b:00007ffc2ea2ab08 EFLAGS: 00000246 ORIG_RAX: 0000000000000036 [ 98.364773] RAX: ffffffffffffffda RBX: 000000000000000d RCX: 00007f6719c8fffa [ 98.364777] RDX: 0000000000000015 RSI: 0000000000000029 RDI: 000000000000000d [ 98.364781] RBP: 0000000000000002 R08: 0000000000000014 R09: 00000000fffffff9 [ 98.364784] R10: 00007ffc2ea2ab10 R11: 0000000000000246 R12: 0000000000000000 [ 98.364787] R13: 000055cc8f2201a0 R14: 0000000000000000 R15: 000055cc8f21dec0 [ 98.364795] </TASK> [ 98.364797] ---[ end trace 0000000000000000 ]---
Signature · 1 line
-Barry K. Nathan <[email protected]>
(Added Kuniyuki Iwashima and Eric Dumazet because they were tagged on the commit that I bisected this to.)
Quoted 37 lines · Barry K. Nathan
Quoted 14 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.111 release. There are 1102 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 19 Sep 2026 15:13:49 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.111-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.12.y and the diffstat can be found below.Quoted 3 lines
thanks,
greg k-h
I tested 6.12.110 + up-to-date stable-queue as of this writing, commit
01b20bb84b994fdcda64fd07a66ba84c85d0168f, on my Lenovo ThinkPad T14 Gen 1. (If necessary, I can explain later how my workflow ends up giving this kernel the version number "6.12.111-pre158", but hopefully that detail won't be relevant.)I'm seeing different kernel warnings than the other ones that have been posted in this thread so far. Here is one of them; I can reproduce this with the following steps:
1. Boot
2. Log in
3. Wait 30 seconds or so
4. Close the laptop lid and wait for it to suspend
5. Open the laptop lid and unlock my desktop
6. Check dmesg and see if there's a warning there. If so, I'm done. If not, repeat steps 4 and 5.
Quoted 2 lines
Sometimes the warning appears after only 1 suspend/wake cycle, but it always shows up no later than the second suspend/wake cycle.
Now that I've done more testing, it sometimes doesn't happen until a third suspend/wake cycle. (It also happens within 15 seconds of boot fairlyoften, though, so maybe I could have tried rebooting several times instead of doing suspend/wake.)
Quoted 62 lines
I'll verify that this still reproduces with a more minimal config, then I'll go ahead and bisect...
(On this ThinkPad I'm running Debian trixie and GNOME, in case it matters.)
[ 98.363836] ------------[ cut here ]------------
[ 98.363843] RTNL: assertion failed atnet/ipv6/mcast.c(1014)
[ 98.363896] WARNING: CPU: 6 PID: 961 atnet/ipv6/mcast.c:1014__ipv6_dev_mc_dec+0x17b/0x190[ipv6]
[ 98.363977] Modules linked in:sd_modscsi_modscsi_commonsnd_seq_dummysnd_hrtimersnd_seqsnd_seq_devicerfcommalgif_hashalgif_skcipheraf_algqrtr bnepsnd_soc_skl_hda_dspsnd_soc_intel_sof_board_helperssnd_sof_probessnd_soc_intel_hda_dsp_commonintel_uncore_frequencyintel_uncore_frequency_commonbinfmt_miscintel_pmc_core_pltdrvintel_pmc_coreintel_vsecpmt_telemetrypmt_classx86_pkg_temp_thermalnls_asciinls_cp437snd_hda_codec_realtekvfat fatsnd_hda_codec_genericsnd_hda_scodec_componentsnd_soc_dmicsnd_sof_pci_intel_cnlsnd_sof_intel_hda_genericsoundwire_intelsoundwire_cadencesnd_sof_intel_hda_commonsnd_soc_hdac_hdaintel_powerclampsnd_sof_intel_hda_mlinkcoretempsnd_sof_intel_hdasnd_hda_codec_hdmisnd_sof_pcikvm_intelsnd_sof_xtensa_dspsnd_sofsnd_sof_utilssnd_soc_acpi_intel_matchkvmsoundwire_generic_allocationsnd_soc_acpisoundwire_busiwlmvmsnd_soc_avsirqbypasssnd_soc_hda_codecsnd_hda_ext_corecrct10dif_pclmulmac80211snd_soc_coreghash_clmulni_intelmei_wdtmei_hdcp[ 98.364043]sha512_ssse3intel_rapl_msrsha256_ssse3mei_pxpsha1_ssse3uvcvideosnd_compresssnd_pcm_dmaengineaesni_intellibarc4snd_hda_inteluvccrypto_simdvideobuf2_vmallocsnd_intel_dspcfgcryptd btusbvideobuf2_memopsvideobuf2_v4l2btrtlsnd_intel_sdw_acpibtintel rapl btbcmsnd_hda_codecvideodevintel_cstateiwlwifi btmtkprocessor_thermal_device_pci_legacysnd_hda_corevideobuf2_commonrmi_smbusprocessor_thermal_deviceintel_uncoresnd_ctl_ledpcspkrprocessor_thermal_wt_hintmc bluetoothrmi_coreprocessor_thermal_rfimsnd_hwdepprocessor_thermal_raplcfg80211think_lmiintel_wmi_thunderboltsnd_pcmintel_rapl_commonfirmware_attributes_classthinkpad_acpiee1004snd_timerprocessor_thermal_wt_reqcrc16mei_menvramwmi_bmofprocessor_thermal_power_floorplatform_profilemeiprocessor_thermal_mboxsndintel_soc_dts_iosfintel_pch_thermalint3403_thermaljoydev soundcoreint340x_thermal_zoneacint3400_thermalintel_hidacpi_thermal_relsparse_keymapbuttonacpi_padevdev msri2c_devparport_pcppdev lp [ 98.364124] parportdm_modnvme_fabricsefi_pstoreconfigfs nfnetlinkip_tablesx_tablesipv6 autofs4 xfs btrfsblake2b_genericraid10 raid456async_raid6_recovasync_memcpyasync_pqasync_xorasync_txxorraid6_pqlibcrc32ccrc32c_genericraid1 raid0 linearmd_modhid_multitouchhid_genericusbhid hid i915drm_buddyi2c_algo_bitiTCO_wdtdrm_display_helperintel_pmc_bxtiTCO_vendor_supportrtsx_pci_sdmmcwatchdogucsi_acpimmc_corepsmousei2c_i801cectypec_ucsixhci_pcinvme videocrc32_pclmulrc_corethunderboltxhci_hcde1000ecrc32c_intelserio_rawrolesnvme_corettmi2c_smbusrtsx_pcitypec battery wmi efivarfs
[ 98.364208] CPU: 6 UID: 105 PID: 961 Comm: avahi-daemon Not tainted 6.12.111-pre158 #3
[ 98.364214] Hardware name: LENOVO 20S1S6D700/20S1S6D700, BIOS N2XET46W (1.36 ) 06/02/2026
[ 98.364217] RIP: 0010:__ipv6_dev_mc_dec+0x17b/0x190 [ipv6]
[ 98.364291] Code: 88 f5 02 00 00 0f 85 c4 fe ff ff ba f6 03 00 00 48 c7 c6 30 8f 3b c1 48 c7 c7 58 7b 3b c1 c6 05 68 f5 02 00 01 e8 95 fd f5 e4 <0f> 0b e9 9e fe ff ff 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 90
[ 98.364296] RSP: 0018:ffffd3da8074b8c0 EFLAGS: 00010246
[ 98.364301] RAX: 0000000000000000 RBX:ffff8e5e03638800RCX: 0000000000000000
[ 98.364304] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[ 98.364307] RBP:ffff8e5e09238540R08: 0000000000000000 R09: 0000000000000000
[ 98.364311] R10: 0000000000000000 R11: 0000000000000000 R12:ffff8e5e2088ae80
[ 98.364314] R13:ffff8e5e03638800R14:ffff8e5e03638a70R15: 0000000000000000
[ 98.364318] FS: 00007f6719a89840(0000) GS:ffff8e652c500000(0000) knlGS:0000000000000000
[ 98.364322] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 98.364326] CR2:00007f38ae7fcd58CR3:000000010b64c004CR4:00000000003726f0
[ 98.364329] Call Trace:
[ 98.364334] <TASK>
[ 98.364339]ipv6_sock_mc_drop+0x122/0x1e0[ipv6]
[ 98.364409]do_ipv6_setsockopt+0xb9b/0x1a30[ipv6]
[ 98.364479] ?__wake_up_sync_key+0x3b/0x60
[ 98.364486] ?sock_def_readable+0x42/0xc0
[ 98.364490] ?unix_dgram_sendmsg+0x5d5/0x9c0
[ 98.364499]ipv6_setsockopt+0x5e/0xa0[ipv6]
[ 98.364570]do_sock_setsockopt+0xb9/0x190
[ 98.364578]__sys_setsockopt+0x94/0xe0
[ 98.364584]__x64_sys_setsockopt+0x1f/0x40
[ 98.364589]do_syscall_64+0x82/0x1b0
[ 98.364595] ?syscall_exit_to_user_mode+0x32/0x190
[ 98.364601] ?do_syscall_64+0x8e/0x1b0
[ 98.364607] ?file_update_time+0x1b/0x90
[ 98.364615] ?pipe_write+0x424/0x670
[ 98.364623] ?vfs_write+0x3b6/0x450
[ 98.364630] ? arch_exit_to_user_mode_prepare.isra.0+0x1e/0x100
[ 98.364636] ?syscall_exit_to_user_mode+0x32/0x190
[ 98.364643] ?do_syscall_64+0x8e/0x1b0
[ 98.364649] ?do_syscall_64+0x8e/0x1b0
[ 98.364655] ? arch_exit_to_user_mode_prepare.isra.0+0x1e/0x100
[ 98.364661] ?syscall_exit_to_user_mode+0x32/0x190
[ 98.364667] ?do_syscall_64+0x8e/0x1b0
[ 98.364675] ?__sys_sendmsg+0x87/0xf0
[ 98.364681] ? arch_exit_to_user_mode_prepare.isra.0+0x1e/0x100
[ 98.364686] ?syscall_exit_to_user_mode+0x32/0x190
[ 98.364692] ?do_syscall_64+0x8e/0x1b0
[ 98.364698] ?do_syscall_64+0x8e/0x1b0
[ 98.364703] ? arch_exit_to_user_mode_prepare.isra.0+0x1e/0x100
[ 98.364708] ?syscall_exit_to_user_mode+0x32/0x190
[ 98.364714] ?do_syscall_64+0x8e/0x1b0
[ 98.364719] ?clear_bhb_loop+0x70/0xc0
[ 98.364726] ?clear_bhb_loop+0x70/0xc0
[ 98.364732]entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 98.364738] RIP: 0033:0x7f6719c8fffa
[ 98.364763] Code: 48 83 ec 10 48 63 c9 48 63 ff 45 89 c9 6a 2c e8 dc d3 f7 ff 48 83 c4 18 c3 0f 1f 80 00 00 00 00 49 89 ca b8 36 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 06 c3 0f 1f 44 00 00 48 8b 15 e1 2d 0d 00 f7
Quoted 9 lines
[ 98.364767] RSP: 002b:00007ffc2ea2ab08 EFLAGS: 00000246
ORIG_RAX: 0000000000000036 [ 98.364773] RAX: ffffffffffffffda RBX:000000000000000dRCX:00007f6719c8fffa[ 98.364777] RDX: 0000000000000015 RSI: 0000000000000029 RDI:000000000000000d[ 98.364781] RBP: 0000000000000002 R08: 0000000000000014 R09:00000000fffffff9[ 98.364784] R10:00007ffc2ea2ab10R11: 0000000000000246 R12: 0000000000000000 [ 98.364787] R13:000055cc8f2201a0R14: 0000000000000000 R15:000055cc8f21dec0[ 98.364795] </TASK>
[ 98.364797] ---[ end trace 0000000000000000 ]---
I bisected it to this patch:
ipv6-mcast-don-t-hold-rtnl-for-ipv6_drop_membership-.patch.
With that patch, the warning happens, without it, it doesn't.
If I take 6.12.110, apply the current stable-queue (as of commit 01b20bb84b994fdcda64fd07a66ba84c85d0168f), then revert the following patches:
ipv6-mcast-don-t-hold-rtnl-for-ipv6_drop_membership-.patch ipv6-mcast-don-t-hold-rtnl-for-mcast_-socket-options.patch ipv6-mcast-use-copy-on-write-rcu-updates-in-ip6_mc_s.patch
then the resulting kernel no longer shows these warnings at all.
Signature · 1 line
-Barry K. Nathan <[email protected]>
Sasha Levin
maintainerQuoted 5 lines · Barry K. Nathan
Quoted 2 lines
[ 98.363843] RTNL: assertion failed at
net/ipv6/mcast.c(1014)
[ 98.363896] WARNING: CPU: 6 PID: 961 atnet/ipv6/mcast.c:1014__ipv6_dev_mc_dec+0x17b/0x190[ipv6]I bisected it to this patch:
ipv6-mcast-don-t-hold-rtnl-for-ipv6_drop_membership-.patch.
Your bisect is right, and thanks for chasing it all the way down -- the splat is real and the patch you landed on is the trigger.
I've dropped the ipv6 mcast RTNL conversion patches from the 6.12, 6.6 and 5.15 queues.
Quoted 9 lines
If I take 6.12.110, apply the current stable-queue (as of commit
01b20bb84b994fdcda64fd07a66ba84c85d0168f), then revert the following patches:ipv6-mcast-don-t-hold-rtnl-for-ipv6_drop_membership-.patch ipv6-mcast-don-t-hold-rtnl-for-mcast_-socket-options.patch ipv6-mcast-use-copy-on-write-rcu-updates-in-ip6_mc_s.patch
then the resulting kernel no longer shows these warnings at all.
The root cause is a prerequisite we never picked up, rather than anything wrong with the patches themselves. Upstream commit e01b193e0b50a ("ipv6: mcast: Use in6_dev_get() in ipv6_dev_mc_dec().") is the commit in that series which deletes the now-stale ASSERT_RTNL() from __ipv6_dev_mc_dec(), and it was never backported to 6.12.y, 6.6.y or 5.15.y. So we took the patches that stop holding RTNL across the setsockopt paths while the assertion they were meant to retire was still sitting there -- hence net/ipv6/mcast.c:1014 firing on every IPV6_DROP_MEMBERSHIP. The queued patches are byte-identical cherry-picks of the upstream commits; this is a series-ordering gap on our side, not a botched backport.
7.2 and 6.18 carry the whole series, including e01b193e0b50a, so they are not affected and keep their copies.
One difference from your experiment: I removed four patches rather than the three you reverted. The extra one is 1767bb2d47b7 ("ipv6: mcast: Don't hold RTNL for IPV6_ADD_MEMBERSHIP and MCAST_JOIN_GROUP."), which is a pure refactor of the join path and was only ever queued as a dependency of the others. It is harmless on its own so consistent with you not needing to revert it, but with the rest gone there is no reason to keep it, and dropping it keeps the series intact for a clean requeue.
The plan is to requeue the complete ordered set, e01b193e0b50a included, once this RC is out.
Signature · 2 lines
Thanks, Sasha
Barry K. Nathan
Tested-byQuoted 45 lines · Sasha Levin
Quoted 5 lines · Barry K. Nathan
Quoted 2 lines
[ 98.363843] RTNL: assertion failed at
net/ipv6/mcast.c(1014)
[ 98.363896] WARNING: CPU: 6 PID: 961 atnet/ipv6/mcast.c:1014__ipv6_dev_mc_dec+0x17b/0x190[ipv6]I bisected it to this patch:
ipv6-mcast-don-t-hold-rtnl-for-ipv6_drop_membership-.patch.Your bisect is right, and thanks for chasing it all the way down -- the splat is real and the patch you landed on is the trigger.
I've dropped the ipv6 mcast RTNL conversion patches from the 6.12, 6.6 and 5.15 queues.
Quoted 9 lines
If I take 6.12.110, apply the current stable-queue (as of commit
01b20bb84b994fdcda64fd07a66ba84c85d0168f), then revert the following patches:ipv6-mcast-don-t-hold-rtnl-for-ipv6_drop_membership-.patch ipv6-mcast-don-t-hold-rtnl-for-mcast_-socket-options.patch ipv6-mcast-use-copy-on-write-rcu-updates-in-ip6_mc_s.patch
then the resulting kernel no longer shows these warnings at all.
The root cause is a prerequisite we never picked up, rather than anything wrong with the patches themselves. Upstream commit
e01b193e0b50a("ipv6: mcast: Usein6_dev_get()inipv6_dev_mc_dec().") is the commit in that series which deletes the now-staleASSERT_RTNL()from__ipv6_dev_mc_dec(), and it was never backported to 6.12.y, 6.6.y or 5.15.y. So we took the patches that stop holding RTNL across the setsockopt paths while the assertion they were meant to retire was still sitting there -- hencenet/ipv6/mcast.c:1014firing on everyIPV6_DROP_MEMBERSHIP. The queued patches are byte-identical cherry-picks of the upstream commits; this is a series-ordering gap on our side, not a botched backport.7.2 and 6.18 carry the whole series, including
e01b193e0b50a, so they are not affected and keep their copies.One difference from your experiment: I removed four patches rather than the three you reverted. The extra one is
1767bb2d47b7("ipv6: mcast: Don't hold RTNL forIPV6_ADD_MEMBERSHIPandMCAST_JOIN_GROUP."), which is a pure refactor of the join path and was only ever queued as a dependency of the others. It is harmless on its own so consistent with you not needing to revert it, but with the rest gone there is no reason to keep it, and dropping it keeps the series intact for a clean requeue.
Quoted 2 lines
The plan is to requeue the complete ordered set,
e01b193e0b50aincluded, once this RC is out.
Thanks for taking care of this!
I have now retested with 6.12.110 + stable-queue as of commit afa3d2e7536e9034a4917d4b6e228a99d5bd7aa6 on my ThinkPad T14 Gen 1. I can no longer reproduce this kernel warning (as expected with the patches being dropped for now), and it's working well, and I have not observed any other regressions.
Signature · 1 line
-Barry K. Nathan <[email protected]>
Sasha Levin
maintainerQuoted 7 lines
I have now retested with 6.12.110 + stable-queue as of commit
afa3d2e7536e9034a4917d4b6e228a99d5bd7aa6on my ThinkPad T14 Gen 1. I can no longer reproduce this kernel warning (as expected with the patches being dropped for now), and it's working well, and I have not observed any other regressions.Tested-by Barry K. Nathan <[email protected]>
Thanks for retesting so quickly.
The complete ordered set is back in the 6.12 queue, with the missing prerequisite in front this time, so the assertion is retired before the patches that stop taking RTNL land.
6.6 and 5.15 are held for now. The conversion needs the two TI cpsw follow-ups that fix the ndo_set_rx_mode path, and those need disable_work_sync(), which neither tree has, so they need adapted backports first. I have asked Kevin Hao for them.
Signature · 2 lines
Thanks, Sasha
Quoted 8 lines · On Thu, 17 Sep 2026 15:59:03 +0100 Greg Kroah-Hartman…
This is the start of the stable review cycle for the 6.12.111 release. There are 1102 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 19 Sep 2026 15:13:49 +0000. Anything received after that time might be too late.
Boot-tested under QEMU for Rust x86_64, arm64 and riscv64; built-tested for loongarch64:
I am also seeing the gather_bootmem_prealloc() issue.
Thanks!
Cheers,
Miguel