5.15.199-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainerPATCH 149/206 gpiolib: acpi: use BIT_ULL() for u64 mask in address space handler
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Denis Sergeev <[email protected]>
[ Upstream commit c0ae43d303e45764918fa8c1dc13d6a5db59c479 ]
The BIT() macro uses unsigned long, which is 32 bits on 32-bit architectures. When iterating over GPIO pins with index >= 32, the expression (*value & BIT(i)) causes undefined behavior due to shifting by a value >= type width.
Since 'value' is a pointer to u64, use BIT_ULL() to ensure correct 64-bit mask on all architectures.
Found by Linux Verification Center (linuxtesting.org) with Svace.
--- drivers/gpio/gpiolib-acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/gpiolib-acpi.c +1 -1
@@ -1173,7 +1173,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,mutex_unlock (&achip->conn_lock);if (function ==ACPI_WRITE ) -gpiod_set_raw_value_cansleep (desc, !!(*value &BIT (i))); +gpiod_set_raw_value_cansleep (desc, !!(*value &BIT_ULL (i)));else *value |= (u64 )gpiod_get_raw_value_cansleep (desc) << i; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 150/206 dma/pool: distinguish between missing and exhausted atomic pools
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sai Sree Kartheek Adivi <[email protected]>
[ Upstream commit 56c430c7f06d838fe3b2077dbbc4cc0bf992312b ]
Currently, dma_alloc_from_pool() unconditionally warns and dumps a stack trace when an allocation fails, with the message "Failed to get suitable pool".
This conflates two distinct failure modes:
1. Configuration error: No atomic pool is available for the requested DMA mask (a fundamental system setup issue)
2. Resource Exhaustion: A suitable pool exists but is currently full (a recoverable runtime state)
This lack of distinction prevents drivers from using __GFP_NOWARN to suppress error messages during temporary pressure spikes, such as when awaiting synchronous reclaim of descriptors.
Refactor the error handling to distinguish these cases:
- If no suitable pool is found, keep the unconditional WARN regarding the missing pool.
- If a pool was found but is exhausted, respect __GFP_NOWARN and update the warning message to explicitly state "DMA pool exhausted".
--- kernel/dma/pool.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
kernel/dma/pool.c +6 -1
@@ -268,15 +268,20 @@ struct page *dma_alloc_from_pool(struct device *dev, size_t size, {struct gen_pool *pool =NULL ;struct page *page; +bool pool_found = false;while ((pool =dma_guess_pool (pool, gfp))) { + pool_found = true; page =__dma_alloc_from_pool (dev, size, pool, cpu_addr, phys_addr_ok);if (page)return page; } -WARN (1 ,"Failed to get suitable pool for %s\n" ,dev_name (dev)); +if (pool_found) +WARN (!(gfp & __GFP_NOWARN),"DMA pool exhausted for %s\n" ,dev_name (dev)); +else +WARN (1 ,"Failed to get suitable pool for %s\n" ,dev_name (dev));return NULL ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 151/206 ASoC: fsl: imx-card: Do not force slot width to sample width
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fabio Estevam <[email protected]>
commit 9210f5ff6318163835d9e42ee68006be4da0f531 upstream.
imx-card currently sets the slot width to the physical sample width for I2S links. This breaks controllers that use fixed-width slots (e.g. 32-bit FIFO words), causing the unused bits in the slot to contain undefined data when playing 16-bit streams.
Do not override the slot width in the machine driver and let the CPU DAI select an appropriate default instead. This matches the behavior of simple-audio-card and avoids embedding controller-specific policy in the machine driver.
On an i.MX8MP-based board using SAI as the I2S master with 32-bit slots, playing 16-bit audio resulted in spurious frequencies and an incorrect SAI data waveform, as the slot width was forced to 16 bits. After this change, audio artifacts are eliminated and the 16-bit samples correctly occupy the first half of the 32-bit slot, with the remaining bits padded with zeroes.
--- sound/soc/fsl/imx-card.c | 1 - 1 file changed, 1 deletion(-)
sound/soc/fsl/imx-card.c +0 -1
@@ -314,7 +314,6 @@ static int imx_aif_hw_params(struct snd_SND_SOC_DAIFMT_PDM ; }else { slots =2 ; - slot_width =params_physical_width (params); fmt = (rtd->dai_link->dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK ) |SND_SOC_DAIFMT_I2S ; }
Greg Kroah-Hartman
maintainerPATCH 152/206 scsi: be2iscsi: Fix a memory leak in beiscsi_boot_get_sinfo()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit 4747bafaa50115d9667ece446b1d2d4aba83dc7f upstream.
If nonemb_cmd->va fails to be allocated, free the allocation previously made by alloc_mcc_wrb().
--- drivers/scsi/be2iscsi/be_mgmt.c | 1 + 1 file changed, 1 insertion(+)
drivers/scsi/be2iscsi/be_mgmt.c +1 -0
@@ -1025,6 +1025,7 @@ unsigned int beiscsi_boot_get_sinfo(stru &nonemb_cmd->dma, GFP_KERNEL);if (!nonemb_cmd->va) { +free_mcc_wrb (ctrl, tag);mutex_unlock (&ctrl->mbox_lock);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 153/206 scsi: qla2xxx: edif: Fix dma_free_coherent() size
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Fourier <[email protected]>
commit 56bd3c0f749f45793d1eae1d0ddde4255c749bf6 upstream.
Earlier in the function, the ha->flt buffer is allocated with size sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE but freed in the error path with size SFP_DEV_SIZE.
--- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_os.c +1 -1
@@ -4431,7 +4431,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha fail_elsrej:dma_pool_destroy (ha->purex_dma_pool); fail_flt: -dma_free_coherent (&ha->pdev->dev,SFP_DEV_SIZE , +dma_free_coherent (&ha->pdev->dev,sizeof (struct qla_flt_header ) +FLT_REGIONS_SIZE , ha->flt, ha->flt_dma); fail_flt_buffer:
Greg Kroah-Hartman
maintainerPATCH 154/206 mptcp: only reset subflow errors when propagated
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit dccf46179ddd6c04c14be8ed584dc54665f53f0e upstream.
Some subflow socket errors need to be reported to the MPTCP socket: the initial subflow connect (MP_CAPABLE), and the ones from the fallback sockets. The others are not propagated.
The issue is that sock_error() was used to retrieve the error, which was also resetting the sk_err field. Because of that, when notifying the userspace about subflow close events later on from the MPTCP worker, the ssk->sk_err field was always 0.
Now, the error (sk_err) is only reset when propagating it to the msk.
--- net/mptcp/protocol.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
net/mptcp/protocol.c +5 -4
@@ -736,11 +736,8 @@ static bool __mptcp_ofo_queue(struct mptstatic bool __mptcp_subflow_error_report (struct sock *sk,struct sock *ssk) { -int err =sock_error (ssk);int ssk_state; - -if (!err) -return false; +int err;/* only propagate errors on fallen-back sockets or * on MPC connect
@@ -748,6 +745,10 @@ static bool __mptcp_subflow_error_reportif (sk->sk_state !=TCP_SYN_SENT && !__mptcp_check_fallback (mptcp_sk (sk)))return false; + err =sock_error (ssk); +if (!err) +return false; +/* We need to propagate only transition to CLOSE state. * Orphaned socket will see such state change via * subflow_sched_work_if_closed() and that path will properly
Greg Kroah-Hartman
maintainerPATCH 155/206 net: Add locking to protect skb->dev access in ip_output
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sharath Chandra Vurukala <[email protected]>
commit 1dbf1d590d10a6d1978e8184f8dfe20af22d680a upstream.
In ip_output() skb->dev is updated from the skb_dst(skb)->dev this can become invalid when the interface is unregistered and freed,
Introduced new skb_dst_dev_rcu() function to be used instead of skb_dst_dev() within rcu_locks in ip_output.This will ensure that all the skb's associated with the dev being deregistered will be transnmitted out first, before freeing the dev.
Given that ip_output() is called within an rcu_read_lock() critical section or from a bottom-half context, it is safe to introduce an RCU read-side critical section within it.
Multiple panic call stacks were observed when UL traffic was run in concurrency with device deregistration from different functions, pasting one sample for reference.
[496733.627565][T13385] Call trace: [496733.627570][T13385] bpf_prog_ce7c9180c3b128ea_cgroupskb_egres+0x24c/0x7f0 [496733.627581][T13385] __cgroup_bpf_run_filter_skb+0x128/0x498 [496733.627595][T13385] ip_finish_output+0xa4/0xf4 [496733.627605][T13385] ip_output+0x100/0x1a0 [496733.627613][T13385] ip_send_skb+0x68/0x100 [496733.627618][T13385] udp_send_skb+0x1c4/0x384 [496733.627625][T13385] udp_sendmsg+0x7b0/0x898 [496733.627631][T13385] inet_sendmsg+0x5c/0x7c [496733.627639][T13385] __sys_sendto+0x174/0x1e4 [496733.627647][T13385] __arm64_sys_sendto+0x28/0x3c [496733.627653][T13385] invoke_syscall+0x58/0x11c [496733.627662][T13385] el0_svc_common+0x88/0xf4 [496733.627669][T13385] do_el0_svc+0x2c/0xb0 [496733.627676][T13385] el0_svc+0x2c/0xa4 [496733.627683][T13385] el0t_64_sync_handler+0x68/0xb4 [496733.627689][T13385] el0t_64_sync+0x1a4/0x1a8
Changes in v3:
- Replaced WARN_ON() with WARN_ON_ONCE(), as suggested by Willem de Bruijn.
- Dropped legacy lines mistakenly pulled in from an outdated branch.
Changes in v2:
- Addressed review comments from Eric Dumazet
- Used READ_ONCE() to prevent potential load/store tearing
- Added skb_dst_dev_rcu() and used along with rcu_read_lock() in ip_output
--- include/net/dst.h | 12 ++++++++++++ net/ipv4/ip_output.c | 16 +++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-)
include/net/dst.h +12 -0
@@ -554,6 +554,18 @@ static inline void skb_dst_update_pmtu_n dst->ops->update_pmtu (dst,NULL , skb, mtu, false); } +static inline struct net_device *dst_dev_rcu (const struct dst_entry *dst) +{ +/* In the future, use rcu_dereference(dst->dev) */ +WARN_ON_ONCE (!rcu_read_lock_held ()); +return READ_ONCE (dst->dev); +} + +static inline struct net_device *skb_dst_dev_rcu (const struct sk_buff *skb) +{ +return dst_dev_rcu (skb_dst (skb)); +} +struct dst_entry *dst_blackhole_check (struct dst_entry *dst,u32 cookie);void dst_blackhole_update_pmtu (struct dst_entry *dst,struct sock *sk,struct sk_buff *skb,u32 mtu,bool confirm_neigh);
net/ipv4/ip_output.c +11 -5
@@ -420,17 +420,23 @@ int ip_mc_output(struct net *net, structint ip_output (struct net *net,struct sock *sk,struct sk_buff *skb) { -struct net_device *dev =skb_dst (skb)->dev, *indev = skb->dev; +struct net_device *dev, *indev = skb->dev; +int ret_val; + +rcu_read_lock (); + dev =skb_dst_dev_rcu (skb);IP_UPD_PO_STATS (net,IPSTATS_MIB_OUT , skb->len); skb->dev = dev; skb->protocol =htons (ETH_P_IP ); -return NF_HOOK_COND (NFPROTO_IPV4 ,NF_INET_POST_ROUTING , - net, sk, skb, indev, dev, - ip_finish_output, - !(IPCB (skb)->flags &IPSKB_REROUTED )); + ret_val =NF_HOOK_COND (NFPROTO_IPV4 ,NF_INET_POST_ROUTING , + net, sk, skb, indev, dev, + ip_finish_output, + !(IPCB (skb)->flags &IPSKB_REROUTED )); +rcu_read_unlock (); +return ret_val; }EXPORT_SYMBOL (ip_output);
Greg Kroah-Hartman
maintainerPATCH 156/206 tls: Use __sk_dst_get() and dst_dev_rcu() in get_netdev_for_sock().
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
commit c65f27b9c3be2269918e1cbad6d8884741f835c5 upstream.
get_netdev_for_sock() is called during setsockopt(), so not under RCU.
Using sk_dst_get(sk)->dev could trigger UAF.
Let's use __sk_dst_get() and dst_dev_rcu().
Note that the only ->ndo_sk_get_lower_dev() user is bond_sk_get_lower_dev(), which uses RCU.
--- net/tls/tls_device.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
net/tls/tls_device.c +10 -8
@@ -110,17 +110,19 @@ static void tls_device_queue_ctx_destruc/* We assume that the socket is already connected */ static struct net_device *get_netdev_for_sock (struct sock *sk) { -struct dst_entry *dst =sk_dst_get (sk); -struct net_device *netdev =NULL ; +struct net_device *dev, *lowest_dev =NULL ; +struct dst_entry *dst; -if (likely (dst)) { - netdev =netdev_sk_get_lowest_dev (dst->dev, sk); -dev_hold (netdev); +rcu_read_lock (); + dst =__sk_dst_get (sk); + dev = dst ?dst_dev_rcu (dst) :NULL ; +if (likely (dev)) { + lowest_dev =netdev_sk_get_lowest_dev (dev, sk); +dev_hold (lowest_dev); } +rcu_read_unlock (); -dst_release (dst); - -return netdev; +return lowest_dev; }static void destroy_record (struct tls_record_info *record)
Greg Kroah-Hartman
maintainerPATCH 157/206 comedi: Fix getting range information for subdevices 16 to 255
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Abbott <[email protected]>
commit 10d28cffb3f6ec7ad67f0a4cd32c2afa92909452 upstream.
The COMEDI_RANGEINFO ioctl does not work properly for subdevice indices above 15. Currently, the only in-tree COMEDI drivers that support more than 16 subdevices are the "8255" driver and the "comedi_bond" driver. Making the ioctl work for subdevice indices up to 255 is achievable. It needs minor changes to the handling of the COMEDI_RANGEINFO and COMEDI_CHANINFO ioctls that should be mostly harmless to user-space, apart from making them less broken. Details follow...
The COMEDI_RANGEINFO ioctl command gets the list of supported ranges (usually with units of volts or milliamps) for a COMEDI subdevice or channel. (Only some subdevices have per-channel range tables, indicated by the SDF_RANGETYPE flag in the subdevice information.) It uses a range_type value and a user-space pointer, both supplied by user-space, but the range_type value should match what was obtained using the COMEDI_CHANINFO ioctl (if the subdevice has per-channel range tables) or COMEDI_SUBDINFO ioctl (if the subdevice uses a single range table for all channels). Bits 15 to 0 of the range_type value contain the length of the range table, which is the only part that user-space should care about (so it can use a suitably sized buffer to fetch the range table). Bits 23 to 16 store the channel index, which is assumed to be no more than 255 if the subdevice has per-channel range tables, and is set to 0 if the subdevice has a single range table. For range_type values produced by the COMEDI_SUBDINFO ioctl, bits 31 to 24 contain the subdevice index, which is assumed to be no more than 255. But for range_type values produced by the COMEDI_CHANINFO ioctl, bits 27 to 24 contain the subdevice index, which is assumed to be no more than 15, and bits 31 to 28 contain the COMEDI device's minor device number for some unknown reason lost in the mists of time. The COMEDI_RANGEINFO ioctl extract the length from bits 15 to 0 of the user-supplied range_type value, extracts the channel index from bits 23 to 16 (only used if the subdevice has per-channel range tables), extracts the subdevice index from bits 27 to 24, and ignores bits 31 to
28. So for subdevice indices 16 to 255, the COMEDI_SUBDINFO or COMEDI_CHANINFO ioctl will report a range_type value that doesn't work with the COMEDI_RANGEINFO ioctl. It will either get the range table for the subdevice index modulo 16, or will fail with -EINVAL.
To fix this, always use bits 31 to 24 of the range_type value to hold the subdevice index (assumed to be no more than 255). This affects the COMEDI_CHANINFO and COMEDI_RANGEINFO ioctls. There should not be anything in user-space that depends on the old, broken usage, although it may now see different values in bits 31 to 28 of the range_type values reported by the COMEDI_CHANINFO ioctl for subdevices that have per-channel subdevices. User-space should not be trying to decode bits 31 to 16 of the range_type values anyway.
--- drivers/comedi/comedi.h | 2 +- drivers/comedi/comedi_fops.c | 2 +- drivers/comedi/range.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
drivers/comedi/comedi.h +1 -1
@@ -640,7 +640,7 @@ struct comedi_chaninfo {/** * struct comedi_rangeinfo - used to retrieve the range table for a channel -* @range_type: Encodes subdevice index (bits 27:24), channel index +* @range_type: Encodes subdevice index (bits 31:24), channel index * (bits 23:16) and range table length (bits 15:0). * @range_ptr: Pointer to array of @struct comedi_krange to be filled * in with the range table for the channel or subdevice.
drivers/comedi/comedi_fops.c +1 -1
@@ -1095,7 +1095,7 @@ static int do_chaninfo_ioctl(struct comefor (i =0 ; i < s->n_chan; i++) {int x; - x = (dev->minor <<28 ) | (it->subdev <<24 ) | (i <<16 ) | + x = (it->subdev <<24 ) | (i <<16 ) | (s->range_table_list[i]->length);if (put_user (x, it->rangelist + i))return -EFAULT ;
drivers/comedi/range.c +1 -1
@@ -52,7 +52,7 @@ int do_rangeinfo_ioctl(struct comedi_devconst struct comedi_lrange *lr;struct comedi_subdevice *s; - subd = (it->range_type >>24 ) &0xf ; + subd = (it->range_type >>24 ) &0xff ; chan = (it->range_type >>16 ) &0xff ;if (!dev->attached)
Greg Kroah-Hartman
maintainerPATCH 158/206 of: platform: Use default match table for /firmware
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rob Herring (Arm) <[email protected]>
commit 48e6a9c4a20870e09f85ff1a3628275d6bce31c0 upstream.
Calling of_platform_populate() without a match table will only populate the immediate child nodes under /firmware. This is usually fine, but in the case of something like a "simple-mfd" node such as "raspberrypi,bcm2835-firmware", those child nodes will not be populated. And subsequent calls won't work either because the /firmware node is marked as processed already.
Switch the call to of_platform_default_populate() to solve this problem. It should be a nop for existing cases.
--- drivers/of/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/of/platform.c +1 -1
@@ -533,7 +533,7 @@ static int __init of_platform_default_po node =of_find_node_by_path ("/firmware" );if (node) { -of_platform_populate (node,NULL ,NULL ,NULL ); +of_platform_default_populate (node,NULL ,NULL );of_node_put (node); }
Greg Kroah-Hartman
maintainerPATCH 159/206 iio: adc: exynos_adc: fix OF populate on driver rebind
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit ea6b4feba85e996e840e0b661bc42793df6eb701 ]
Since commit c6e126de43e7 ("of: Keep track of populated platform devices") child devices will not be created by of_platform_populate() if the devices had previously been deregistered individually so that the OF_POPULATED flag is still set in the corresponding OF nodes.
Switch to using of_platform_depopulate() instead of open coding so that the child devices are created if the driver is rebound.
--- drivers/iio/adc/exynos_adc.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-)
drivers/iio/adc/exynos_adc.c +2 -11
@@ -721,14 +721,7 @@ static const struct iio_chan_spec exynos ADC_CHANNEL(9, "adc9"), }; -static int exynos_adc_remove_devices (struct device *dev,void *c) -{ -struct platform_device *pdev =to_platform_device (dev); - -platform_device_unregister (pdev); -return 0 ; -}static int exynos_adc_ts_open (struct input_dev *dev) {
@@ -929,8 +922,7 @@ static int exynos_adc_probe(struct platfreturn 0 ; err_of_populate: -device_for_each_child (&indio_dev->dev,NULL , - exynos_adc_remove_devices); +of_platform_depopulate (&indio_dev->dev);if (has_ts) {input_unregister_device (info->input);free_irq (info->tsirq, info);
@@ -959,8 +951,7 @@ static int exynos_adc_remove(struct platfree_irq (info->tsirq, info);input_unregister_device (info->input); } -device_for_each_child (&indio_dev->dev,NULL , - exynos_adc_remove_devices); +of_platform_depopulate (&indio_dev->dev);iio_device_unregister (indio_dev);free_irq (info->irq, info);if (info->data->exit_hw)
Greg Kroah-Hartman
maintainerPATCH 160/206 scsi: xen: scsiback: Fix potential memory leak in scsiback_remove()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
[ Upstream commit 901a5f309daba412e2a30364d7ec1492fa11c32c ]
Memory allocated for struct vscsiblk_info in scsiback_probe() is not freed in scsiback_remove() leading to potential memory leaks on remove, as well as in the scsiback_probe() error paths. Fix that by freeing it in scsiback_remove().
--- drivers/xen/xen-scsiback.c | 1 + 1 file changed, 1 insertion(+)
drivers/xen/xen-scsiback.c +1 -0
@@ -1197,6 +1197,7 @@ static int scsiback_remove(struct xenbusgnttab_page_cache_shrink (&info->free_pages,0 );dev_set_drvdata (&dev->dev,NULL ); +kfree (info);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 161/206 arm64: dts: rockchip: remove redundant max-link-speed from nanopi-r4s
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geraldo Nascimento <[email protected]>
[ Upstream commit ce652c98a7bfa0b7c675ef5cd85c44c186db96af ]
This is already the default in rk3399-base.dtsi, remove redundant declaration from rk3399-nanopi-r4s.dtsi.
--- arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts | 1 - 1 file changed, 1 deletion(-)
arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts +0 -1
@@ -73,7 +73,6 @@ }; &pcie0 { - max-link-speed = <1>; num-lanes = <1>; vpcie3v3-supply = <&vcc3v3_sys>; };
Greg Kroah-Hartman
maintainerPATCH 162/206 w1: w1_therm: use swap() to make code cleaner
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Guang <[email protected]>
[ Upstream commit e233897b1f7a859092bd20b10bfd412013381a10 ]
Use the macro 'swap()' defined in 'include/linux/minmax.h' to avoid opencoding it.
Stable-dep-of: 761fcf46a1bd ("w1: therm: Fix off-by-one buffer overflow in alarms_store")
--- drivers/w1/slaves/w1_therm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/w1/slaves/w1_therm.c +3 -4
@@ -1782,7 +1782,7 @@ static ssize_t alarms_store(struct devicu8 new_config_register[3 ];/* array of data to be written */ int temp, ret;char *token =NULL ; -s8 tl, th, tt;/* 1 byte per value + temp ring order */ +s8 tl, th;/* 1 byte per value + temp ring order */ char *p_args, *orig; p_args = orig =kmalloc (size,GFP_KERNEL );
@@ -1833,9 +1833,8 @@ static ssize_t alarms_store(struct devic th =int_to_short (temp);/* Reorder if required th and tl */ -if (tl > th) { - tt = tl; tl = th; th = tt; - } +if (tl > th) +swap (tl, th);/* * Read the scratchpad to change only the required bits
Greg Kroah-Hartman
maintainerPATCH 163/206 w1: therm: Fix off-by-one buffer overflow in alarms_store
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
[ Upstream commit 761fcf46a1bd797bd32d23f3ea0141ffd437668a ]
The sysfs buffer passed to alarms_store() is allocated with 'size + 1' bytes and a NUL terminator is appended. However, the 'size' argument does not account for this extra byte. The original code then allocated 'size' bytes and used strcpy() to copy 'buf', which always writes one byte past the allocated buffer since strcpy() copies until the NUL terminator at index 'size'.
Fix this by parsing the 'buf' parameter directly using simple_strtoll() without allocating any intermediate memory or string copying. This removes the overflow while simplifying the code.
--- drivers/w1/slaves/w1_therm.c | 60 +++++++++++++------------------------------ 1 file changed, 19 insertions(+), 41 deletions(-)
drivers/w1/slaves/w1_therm.c +19 -41
@@ -1780,53 +1780,35 @@ static ssize_t alarms_store(struct devicstruct w1_slave *sl =dev_to_w1_slave (device);struct therm_info info;u8 new_config_register[3 ];/* array of data to be written */ -int temp, ret; -char *token =NULL ; +long long temp; +int ret =0 ;s8 tl, th;/* 1 byte per value + temp ring order */ -char *p_args, *orig; +const char *p = buf; +char *endp; - p_args = orig =kmalloc (size,GFP_KERNEL ); -/* Safe string copys as buf is const */ -if (!p_args) { -dev_warn (device, -"%s: error unable to allocate memory %d\n" , - __func__, -ENOMEM ); -return size; - } -strcpy (p_args, buf); - -/* Split string using space char */ - token =strsep (&p_args," " ); - -if (!token) { -dev_info (device, -"%s: error parsing args %d\n" , __func__, -EINVAL ); - goto free_m; - } - -/* Convert 1st entry to int */ - ret =kstrtoint (token,10 , &temp); + temp =simple_strtoll (p, &endp,10 ); +if (p == endp || *endp !=' ' ) + ret = -EINVAL ; +else if (temp <INT_MIN || temp >INT_MAX ) + ret = -ERANGE ;if (ret) {dev_info (device,"%s: error parsing args %d\n" , __func__, ret); - goto free_m; +return size; } tl =int_to_short (temp); -/* Split string using space char */ - token =strsep (&p_args," " ); -if (!token) { -dev_info (device, -"%s: error parsing args %d\n" , __func__, -EINVAL ); - goto free_m; - } -/* Convert 2nd entry to int */ - ret =kstrtoint (token,10 , &temp); + p = endp +1 ; + temp =simple_strtoll (p, &endp,10 ); +if (p == endp) + ret = -EINVAL ; +else if (temp <INT_MIN || temp >INT_MAX ) + ret = -ERANGE ;if (ret) {dev_info (device,"%s: error parsing args %d\n" , __func__, ret); - goto free_m; +return size; }/* Prepare to cast to short by eliminating out of range values */
@@ -1849,7 +1831,7 @@ static ssize_t alarms_store(struct devicdev_info (device,"%s: error reading from the slave device %d\n" , __func__, ret); - goto free_m; +return size; }/* Write data in the device RAM */
@@ -1857,7 +1839,7 @@ static ssize_t alarms_store(struct devicdev_info (device,"%s: Device not supported by the driver %d\n" , __func__, -ENODEV ); - goto free_m; +return size; } ret =SLAVE_SPECIFIC_FUNC (sl)->write_data (sl, new_config_register);
@@ -1866,10 +1848,6 @@ static ssize_t alarms_store(struct devic"%s: error writing to the slave device %d\n" , __func__, ret); -free_m: -/* free allocated memory */ -kfree (orig); -return size; }
Greg Kroah-Hartman
maintainerPATCH 164/206 dmaengine: stm32: dmamux: fix OF node leak on route allocation failure
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit b1b590a590af13ded598e70f0b72bc1e515787a1 ]
Make sure to drop the reference taken to the DMA master OF node also on late route allocation failures.
--- drivers/dma/stm32-dmamux.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/dma/stm32-dmamux.c +3 -1
@@ -140,7 +140,7 @@ static void *stm32_dmamux_route_allocate ret =pm_runtime_resume_and_get (&pdev->dev);if (ret <0 ) {spin_unlock_irqrestore (&dmamux->lock, flags); - goto error; + goto err_put_dma_spec_np; }spin_unlock_irqrestore (&dmamux->lock, flags);
@@ -160,6 +160,8 @@ static void *stm32_dmamux_route_allocatereturn mux; +err_put_dma_spec_np: +of_node_put (dma_spec->np); error:clear_bit (mux->chan_id, dmamux->dma_inuse);
Greg Kroah-Hartman
maintainerPATCH 165/206 dmaengine: stm32: dmamux: fix device leak on route allocation
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit dd6e4943889fb354efa3f700e42739da9bddb6ef ]
Make sure to drop the reference taken when looking up the DMA mux platform device during route allocation.
Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.
--- drivers/dma/stm32-dmamux.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
drivers/dma/stm32-dmamux.c +12 -6
@@ -88,23 +88,25 @@ static void *stm32_dmamux_route_allocatestruct stm32_dmamux_data *dmamux =platform_get_drvdata (pdev);struct stm32_dmamux *mux;u32 i, min, max; -int ret; +int ret = -EINVAL ;unsigned long flags;if (dma_spec->args_count !=3 ) {dev_err (&pdev->dev,"invalid number of dma mux args\n" ); -return ERR_PTR (-EINVAL ); + goto err_put_pdev; }if (dma_spec->args[0 ] > dmamux->dmamux_requests) {dev_err (&pdev->dev,"invalid mux request number: %d\n" , dma_spec->args[0 ]); -return ERR_PTR (-EINVAL ); + goto err_put_pdev; } mux =kzalloc (sizeof (*mux),GFP_KERNEL ); -if (!mux) -return ERR_PTR (-ENOMEM ); +if (!mux) { + ret = -ENOMEM ; + goto err_put_pdev; + }spin_lock_irqsave (&dmamux->lock, flags); mux->chan_id = find_first_zero_bit(dmamux->dma_inuse,
@@ -131,7 +133,6 @@ static void *stm32_dmamux_route_allocate dma_spec->np =of_parse_phandle (ofdma->of_node,"dma-masters" , i -1 );if (!dma_spec->np) {dev_err (&pdev->dev,"can't get dma master\n" ); - ret = -EINVAL ; goto error; }
@@ -158,6 +159,8 @@ static void *stm32_dmamux_route_allocatedev_dbg (&pdev->dev,"Mapping DMAMUX(%u) to DMA%u(%u)\n" , mux->request, mux->master, mux->chan_id); +put_device (&pdev->dev); +return mux; err_put_dma_spec_np:
@@ -167,6 +170,9 @@ error: error_chan_id:kfree (mux); +err_put_pdev: +put_device (&pdev->dev); +return ERR_PTR (ret); }
Greg Kroah-Hartman
maintainerPATCH 166/206 xfs: set max_agbno to allow sparse alloc of last full inode chunk
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brian Foster <[email protected]>
[ Upstream commit c360004c0160dbe345870f59f24595519008926f ]
Sparse inode cluster allocation sets min/max agbno values to avoid allocating an inode cluster that might map to an invalid inode chunk. For example, we can't have an inode record mapped to agbno 0 or that extends past the end of a runt AG of misaligned size.
The initial calculation of max_agbno is unnecessarily conservative, however. This has triggered a corner case allocation failure where a small runt AG (i.e. 2063 blocks) is mostly full save for an extent to the EOFS boundary: [2050,13]. max_agbno is set to 2048 in this case, which happens to be the offset of the last possible valid inode chunk in the AG. In practice, we should be able to allocate the 4-block cluster at agbno 2052 to map to the parent inode record at agbno 2048, but the max_agbno value precludes it.
Note that this can result in filesystem shutdown via dirty trans cancel on stable kernels prior to commit 9eb775968b68 ("xfs: walk all AGs if TRYLOCK passed to xfs_alloc_vextent_iterate_ags") because the tail AG selection by the allocator sets t_highest_agno on the transaction. If the inode allocator spins around and finds an inode chunk with free inodes in an earlier AG, the subsequent dir name creation path may still fail to allocate due to the AG restriction and cancel.
To avoid this problem, update the max_agbno calculation to the agbno prior to the last chunk aligned agbno in the AG. This is not necessarily the last valid allocation target for a sparse chunk, but since inode chunks (i.e. records) are chunk aligned and sparse allocs are cluster sized/aligned, this allows the sb_spino_align alignment restriction to take over and round down the max effective agbno to within the last valid inode chunk in the AG.
Note that even though the allocator improvements in the aforementioned commit seem to avoid this particular dirty trans cancel situation, the max_agbno logic improvement still applies as we should be able to allocate from an AG that has been appropriately selected. The more important target for this patch however are older/stable kernels prior to this allocator rework/improvement.
--- fs/xfs/libxfs/xfs_ialloc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
fs/xfs/libxfs/xfs_ialloc.c +6 -5
@@ -772,14 +772,15 @@ sparse_alloc:* invalid inode records, such as records that start at agbno 0 * or extend beyond the AG. * -* Set min agbno to the first aligned, non-zero agbno and max to -* the last aligned agbno that is at least one full chunk from -* the end of the AG. +* Set min agbno to the first chunk aligned, non-zero agbno and +* max to one less than the last chunk aligned agbno from the +* end of the AG. We subtract 1 from max so that the cluster +* allocation alignment takes over and allows allocation within +* the last full inode chunk in the AG. */ args.min_agbno = args.mp->m_sb.sb_inoalignmt; args.max_agbno =round_down (args.mp->m_sb.sb_agblocks, - args.mp->m_sb.sb_inoalignmt) - - igeo->ialloc_blks; + args.mp->m_sb.sb_inoalignmt) -1 ; error =xfs_alloc_vextent (&args);if (error)
Greg Kroah-Hartman
maintainerPATCH 167/206 nvme-fc: rename free_ctrl callback to match name pattern
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Wagner <[email protected]>
[ Upstream commit 205fb5fa6fde1b5b426015eb1ff69f2ff25ef5bb ]
Rename nvme_fc_nvme_ctrl_freed to nvme_fc_free_ctrl to match the name pattern for the callback.
Stable-dep-of: 0edb475ac0a7 ("nvme: fix PCIe subsystem reset controller state transition")
--- drivers/nvme/host/fc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/nvme/host/fc.c +2 -2
@@ -2410,7 +2410,7 @@ nvme_fc_ctrl_get(struct nvme_fc_ctrl *ct* controller. Called after last nvme_put_ctrl() call */ static void -nvme_fc_nvme_ctrl_freed (struct nvme_ctrl *nctrl) +nvme_fc_free_ctrl (struct nvme_ctrl *nctrl) {struct nvme_fc_ctrl *ctrl =to_fc_ctrl (nctrl);
@@ -3361,7 +3361,7 @@ static const struct nvme_ctrl_ops nvme_f .reg_read32 = nvmf_reg_read32, .reg_read64 = nvmf_reg_read64, .reg_write32 = nvmf_reg_write32, - .free_ctrl = nvme_fc_nvme_ctrl_freed, + .free_ctrl = nvme_fc_free_ctrl, .submit_async_event = nvme_fc_submit_async_event, .delete_ctrl = nvme_fc_delete_ctrl, .get_address = nvmf_get_address,
Greg Kroah-Hartman
maintainerPATCH 168/206 nvme-pci: do not directly handle subsys reset fallout
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Keith Busch <[email protected]>
[ Upstream commit 210b1f6576e8b367907e7ff51ef425062e1468e4 ]
Scheduling reset_work after a nvme subsystem reset is expected to fail on pcie, but this also prevents potential handling the platform's pcie services may provide that might successfully recovering the link without re-enumeration. Such examples include AER, DPC, and power's EEH.
Provide a pci specific operation that safely initiates a subsystem reset, and instead of scheduling reset work, read back the status register to trigger a pcie read error.
Since this only affects pci, the other fabrics drivers subscribe to a generic nvmf subsystem reset that is exactly the same as before. The loop fabric doesn't use it because nvmet doesn't support setting that property anyway.
And since we're using the magic NSSR value in two places now, provide a symbolic define for it.
Stable-dep-of: 0edb475ac0a7 ("nvme: fix PCIe subsystem reset controller state transition")
--- drivers/nvme/host/fabrics.c | 15 +++++++++++++++ drivers/nvme/host/fabrics.h | 1 + drivers/nvme/host/fc.c | 1 + drivers/nvme/host/nvme.h | 14 +++----------- drivers/nvme/host/pci.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/nvme/host/rdma.c | 1 + drivers/nvme/host/tcp.c | 1 + include/linux/nvme.h | 3 +++ 8 files changed, 61 insertions(+), 11 deletions(-)
drivers/nvme/host/fabrics.c +15 -0
@@ -254,6 +254,21 @@ int nvmf_reg_write32(struct nvme_ctrl *c }EXPORT_SYMBOL_GPL (nvmf_reg_write32); +int nvmf_subsystem_reset (struct nvme_ctrl *ctrl) +{ +int ret; + +if (!nvme_wait_reset (ctrl)) +return -EBUSY ; + + ret = ctrl->ops->reg_write32 (ctrl,NVME_REG_NSSR ,NVME_SUBSYS_RESET ); +if (ret) +return ret; + +return nvme_try_sched_reset (ctrl); +} +EXPORT_SYMBOL_GPL (nvmf_subsystem_reset); +/** * nvmf_log_connect_error() - Error-parsing-diagnostic print out function for * connect() errors.
drivers/nvme/host/fabrics.h +1 -0
@@ -182,6 +182,7 @@ nvmf_ctlr_matches_baseopts(struct nvme_cint nvmf_reg_read32 (struct nvme_ctrl *ctrl,u32 off,u32 *val);int nvmf_reg_read64 (struct nvme_ctrl *ctrl,u32 off,u64 *val);int nvmf_reg_write32 (struct nvme_ctrl *ctrl,u32 off,u32 val); +int nvmf_subsystem_reset (struct nvme_ctrl *ctrl);int nvmf_connect_admin_queue (struct nvme_ctrl *ctrl);int nvmf_connect_io_queue (struct nvme_ctrl *ctrl,u16 qid);int nvmf_register_transport (struct nvmf_transport_ops *ops);
drivers/nvme/host/fc.c +1 -0
@@ -3361,6 +3361,7 @@ static const struct nvme_ctrl_ops nvme_f .reg_read32 = nvmf_reg_read32, .reg_read64 = nvmf_reg_read64, .reg_write32 = nvmf_reg_write32, + .subsystem_reset = nvmf_subsystem_reset, .free_ctrl = nvme_fc_free_ctrl, .submit_async_event = nvme_fc_submit_async_event, .delete_ctrl = nvme_fc_delete_ctrl,
drivers/nvme/host/nvme.h +3 -11
@@ -514,6 +514,7 @@ struct nvme_ctrl_ops {int (*reg_read64)(struct nvme_ctrl *ctrl,u32 off,u64 *val);void (*free_ctrl)(struct nvme_ctrl *ctrl);void (*submit_async_event)(struct nvme_ctrl *ctrl); +int (*subsystem_reset)(struct nvme_ctrl *ctrl);void (*delete_ctrl)(struct nvme_ctrl *ctrl);void (*stop_ctrl)(struct nvme_ctrl *ctrl);int (*get_address)(struct nvme_ctrl *ctrl,char *buf,int size);
@@ -583,18 +584,9 @@ int nvme_try_sched_reset(struct nvme_ctrstatic inline int nvme_reset_subsystem (struct nvme_ctrl *ctrl) { -int ret; - -if (!ctrl->subsystem) +if (!ctrl->subsystem || !ctrl->ops->subsystem_reset)return -ENOTTY ; -if (!nvme_wait_reset (ctrl)) -return -EBUSY ; - - ret = ctrl->ops->reg_write32 (ctrl,NVME_REG_NSSR ,0x4E564D65 ); -if (ret) -return ret; - -return nvme_try_sched_reset (ctrl); +return ctrl->ops->subsystem_reset (ctrl); }/*
drivers/nvme/host/pci.c +36 -0
@@ -1121,6 +1121,41 @@ static void nvme_pci_submit_async_event(spin_unlock (&nvmeq->sq_lock); } +static int nvme_pci_subsystem_reset (struct nvme_ctrl *ctrl) +{ +struct nvme_dev *dev =to_nvme_dev (ctrl); +int ret =0 ; + +/* +* Taking the shutdown_lock ensures the BAR mapping is not being +* altered by reset_work. Holding this lock before the RESETTING state +* change, if successful, also ensures nvme_remove won't be able to +* proceed to iounmap until we're done. +*/ +mutex_lock (&dev->shutdown_lock); +if (!dev->bar_mapped_size) { + ret = -ENODEV ; + goto unlock; + } + +if (!nvme_change_ctrl_state (ctrl,NVME_CTRL_RESETTING )) { + ret = -EBUSY ; + goto unlock; + } + +writel (NVME_SUBSYS_RESET , dev->bar +NVME_REG_NSSR ); +nvme_change_ctrl_state (ctrl,NVME_CTRL_LIVE ); + +/* +* Read controller status to flush the previous write and trigger a +* pcie read error. +*/ +readl (dev->bar +NVME_REG_CSTS ); +unlock: +mutex_unlock (&dev->shutdown_lock); +return ret; +} +static int adapter_delete_queue (struct nvme_dev *dev,u8 opcode,u16 id) {struct nvme_command c = { };
@@ -2905,6 +2940,7 @@ static const struct nvme_ctrl_ops nvme_p .reg_read64 = nvme_pci_reg_read64, .free_ctrl = nvme_pci_free_ctrl, .submit_async_event = nvme_pci_submit_async_event, + .subsystem_reset = nvme_pci_subsystem_reset, .get_address = nvme_pci_get_address, };
drivers/nvme/host/rdma.c +1 -0
@@ -2287,6 +2287,7 @@ static const struct nvme_ctrl_ops nvme_r .reg_read32 = nvmf_reg_read32, .reg_read64 = nvmf_reg_read64, .reg_write32 = nvmf_reg_write32, + .subsystem_reset = nvmf_subsystem_reset, .free_ctrl = nvme_rdma_free_ctrl, .submit_async_event = nvme_rdma_submit_async_event, .delete_ctrl = nvme_rdma_delete_ctrl,
drivers/nvme/host/tcp.c +1 -0
@@ -2559,6 +2559,7 @@ static const struct nvme_ctrl_ops nvme_t .reg_read32 = nvmf_reg_read32, .reg_read64 = nvmf_reg_read64, .reg_write32 = nvmf_reg_write32, + .subsystem_reset = nvmf_subsystem_reset, .free_ctrl = nvme_tcp_free_ctrl, .submit_async_event = nvme_tcp_submit_async_event, .delete_ctrl = nvme_tcp_delete_ctrl,
include/linux/nvme.h +3 -0
@@ -27,6 +27,9 @@#define NVME_NSID_ALL 0xffffffff +/* Special NSSR value, 'NVMe' */ +#define NVME_SUBSYS_RESET 0x4E564D65 +enum nvme_subsys_type {NVME_NQN_DISC =1 ,/* Discovery type target subsystem */ NVME_NQN_NVME =2 ,/* NVME type target subsystem */
Greg Kroah-Hartman
maintainerPATCH 169/206 nvme: fix PCIe subsystem reset controller state transition
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nilay Shroff <[email protected]>
[ Upstream commit 0edb475ac0a7d153318a24d4dca175a270a5cc4f ]
The commit d2fe192348f9 (“nvme: only allow entering LIVE from CONNECTING state”) disallows controller state transitions directly from RESETTING to LIVE. However, the NVMe PCIe subsystem reset path relies on this transition to recover the controller on PowerPC (PPC) systems.
On PPC systems, issuing a subsystem reset causes a temporary loss of communication with the NVMe adapter. A subsequent PCIe MMIO read then triggers EEH recovery, which restores the PCIe link and brings the controller back online. For EEH recovery to proceed correctly, the controller must transition back to the LIVE state.
Due to the changes introduced by commit d2fe192348f9 (“nvme: only allow entering LIVE from CONNECTING state”), the controller can no longer transition directly from RESETTING to LIVE. As a result, EEH recovery exits prematurely, leaving the controller stuck in the RESETTING state.
Fix this by explicitly transitioning the controller state from RESETTING to CONNECTING and then to LIVE. This satisfies the updated state transition rules and allows the controller to be successfully recovered on PPC systems following a PCIe subsystem reset.
--- drivers/nvme/host/pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/nvme/host/pci.c +4 -1
@@ -1144,7 +1144,10 @@ static int nvme_pci_subsystem_reset(stru }writel (NVME_SUBSYS_RESET , dev->bar +NVME_REG_NSSR ); -nvme_change_ctrl_state (ctrl,NVME_CTRL_LIVE ); + +if (!nvme_change_ctrl_state (ctrl,NVME_CTRL_CONNECTING ) || + !nvme_change_ctrl_state (ctrl,NVME_CTRL_LIVE )) + goto unlock;/* * Read controller status to flush the previous write and trigger a
Greg Kroah-Hartman
maintainerPATCH 170/206 ALSA: scarlett2: Fix buffer overflow in config retrieval
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samasth Norway Ananda <[email protected]>
[ Upstream commit 6f5c69f72e50d51be3a8c028ae7eda42c82902cb ]
The scarlett2_usb_get_config() function has a logic error in the endianness conversion code that can cause buffer overflows when count > 1.
The code checks if (size == 2) where size is the total buffer size in bytes, then loops count times treating each element as u16 (2 bytes). This causes the loop to access count * 2 bytes when the buffer only has size bytes allocated.
Fix by checking the element size (config_item->size) instead of the total buffer size. This ensures the endianness conversion matches the actual element type.
--- sound/usb/mixer_scarlett_gen2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
sound/usb/mixer_scarlett_gen2.c +6 -1
@@ -1194,11 +1194,16 @@ static int scarlett2_usb_get_config( err =scarlett2_usb_get (mixer, config_item->offset, buf, size);if (err <0 )return err; -if (size ==2 ) { +if (config_item->size ==16 ) {u16 *buf_16 = buf;for (i =0 ; i < count; i++, buf_16++) *buf_16 =le16_to_cpu (*(__le16 *)buf_16); + }else if (config_item->size ==32 ) { +u32 *buf_32 = (u32 *)buf; + +for (i =0 ; i < count; i++, buf_32++) + *buf_32 =le32_to_cpu (*(__le32 *)buf_32); }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 171/206 mei: trace: treat reg parameter as string
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Usyskin <[email protected]>
[ Upstream commit 06d5a7afe1d0b47102936d8fba568572c2b4b941 ]
The commitafd2627f727b ("tracing: Check "%s" dereference via the field and not the TP_printk format") forbids to emit event with a plain char* without a wrapper.
The reg parameter always passed as static string and wrapper is not strictly required, contrary to dev parameter.
Use the string wrapper anyway to check sanity of the reg parameters, store it value independently and prevent internal kernel data leaks.
Since some code refactoring has taken place, explicit backporting may be needed for kernels older than 6.10.
--- drivers/misc/mei/mei-trace.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/misc/mei/mei-trace.h +9 -9
@@ -21,18 +21,18 @@ TRACE_EVENT(mei_reg_read, TP_ARGS(dev, reg, offs, val),TP_STRUCT__entry (__string (dev ,dev_name (dev )) - __field(const char *, reg) +__string (reg, reg)__field (u32, offs)__field (u32, val) ),TP_fast_assign ( __assign_str(dev, dev_name(dev)); - __entry->reg = reg; +__assign_str (reg, reg); __entry->offs = offs; __entry->val = val; ),TP_printk ("[%s] read %s:[%#x] = %#x" , -__get_str (dev), __entry->reg, __entry->offs, __entry->val) +__get_str (dev),__get_str (reg), __entry->offs, __entry->val) ); TRACE_EVENT(mei_reg_write,
@@ -40,18 +40,18 @@ TRACE_EVENT(mei_reg_write, TP_ARGS(dev, reg, offs, val),TP_STRUCT__entry (__string (dev ,dev_name (dev )) - __field(const char *, reg) +__string (reg, reg)__field (u32, offs)__field (u32, val) ),TP_fast_assign ( __assign_str(dev, dev_name(dev)); - __entry->reg = reg; +__assign_str (reg, reg); __entry->offs = offs; __entry->val = val; ),TP_printk ("[%s] write %s[%#x] = %#x" , -__get_str (dev), __entry->reg, __entry->offs, __entry->val) +__get_str (dev),__get_str (reg), __entry->offs, __entry->val) ); TRACE_EVENT(mei_pci_cfg_read,
@@ -59,18 +59,18 @@ TRACE_EVENT(mei_pci_cfg_read,TP_ARGS (dev, reg, offs, val),TP_STRUCT__entry ( __string(dev, dev_name(dev)) - __field(const char *, reg) + __string(reg, reg) __field(u32, offs)__field (u32, val) ),TP_fast_assign ( __assign_str(dev, dev_name(dev)); - __entry->reg = reg; +__assign_str (reg, reg); __entry->offs = offs; __entry->val = val; ),TP_printk ("[%s] pci cfg read %s:[%#x] = %#x" , -__get_str (dev), __entry->reg, __entry->offs, __entry->val) +__get_str (dev),__get_str (reg), __entry->offs, __entry->val) );#endif /* _MEI_TRACE_H_ */
Greg Kroah-Hartman
maintainerPATCH 172/206 ksmbd: smbd: fix dma_unmap_sg() nents
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Fourier <[email protected]>
[ Upstream commit 98e3e2b561bc88f4dd218d1c05890672874692f6 ]
The dma_unmap_sg() functions should be called with the same nents as the dma_map_sg(), not the value the map function returned.
--- fs/ksmbd/transport_rdma.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
fs/ksmbd/transport_rdma.c +7 -8
@@ -1086,14 +1086,12 @@ static int get_sg_list(void *buf, int sistatic int get_mapped_sg_list (struct ib_device *device,void *buf,int size,struct scatterlist *sg_list,int nentries, -enum dma_data_direction dir) +enum dma_data_direction dir,int *npages) { -int npages; - - npages =get_sg_list (buf, size, sg_list, nentries); -if (npages <0 ) + *npages =get_sg_list (buf, size, sg_list, nentries); +if (*npages <0 )return -EINVAL ; -return ib_dma_map_sg (device, sg_list, npages, dir); +return ib_dma_map_sg (device, sg_list, *npages, dir); } static int post_sendmsg(struct smb_direct_transport *t,
@@ -1162,12 +1160,13 @@ static int smb_direct_post_send_data(strfor (i =0 ; i < niov; i++) {struct ib_sge *sge;int sg_cnt; +int npages;sg_init_table (sg,SMB_DIRECT_MAX_SEND_SGES -1 ); sg_cnt =get_mapped_sg_list (t->cm_id->device, iov[i].iov_base, iov[i].iov_len, sg,SMB_DIRECT_MAX_SEND_SGES -1 , -DMA_TO_DEVICE ); +DMA_TO_DEVICE , &npages);if (sg_cnt <=0 ) {pr_err ("failed to map buffer\n" ); ret = -ENOMEM ;
@@ -1175,7 +1174,7 @@ static int smb_direct_post_send_data(str }else if (sg_cnt + msg->num_sge >SMB_DIRECT_MAX_SEND_SGES ) {pr_err ("buffer not fitted into sges\n" ); ret = -E2BIG ; -ib_dma_unmap_sg (t->cm_id->device, sg, sg_cnt, +ib_dma_unmap_sg (t->cm_id->device, sg, npages,DMA_TO_DEVICE ); goto err; }
Greg Kroah-Hartman
maintainerPATCH 173/206 mm/pagewalk: add walk_page_range_vma()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
[ Upstream commit e07cda5f232fac4de0925d8a4c92e51e41fa2f6e ]
Let's add walk_page_range_vma(), which is similar to walk_page_vma(), however, is only interested in a subset of the VMA range.
To be used in KSM code to stop using follow_page() next.
Stable-dep-of: f5548c318d6 ("ksm: use range-walk function to jump over holes in scan_get_next_rmap_item")
--- include/linux/pagewalk.h | 3 +++ mm/pagewalk.c | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+)
include/linux/pagewalk.h +3 -0
@@ -99,6 +99,9 @@ int walk_page_range_novma(struct mm_stru unsigned long end, const struct mm_walk_ops *ops, pgd_t *pgd, void *private); +int walk_page_range_vma (struct vm_area_struct *vma,unsigned long start, +unsigned long end,const struct mm_walk_ops *ops, +void *private);int walk_page_vma (struct vm_area_struct *vma,const struct mm_walk_ops *ops,void *private); int walk_page_mapping(struct address_space *mapping, pgoff_t first_index,
mm/pagewalk.c +20 -0
@@ -509,6 +509,26 @@ int walk_page_range_novma(struct mm_strureturn walk_pgd_range (start, end, &walk); } +int walk_page_range_vma (struct vm_area_struct *vma,unsigned long start, +unsigned long end,const struct mm_walk_ops *ops, +void *private) +{ +struct mm_walk walk = { + .ops = ops, + .mm = vma->vm_mm, + .vma = vma, + .private = private, + }; + +if (start >= end || !walk.mm) +return -EINVAL ; +if (start < vma->vm_start || end > vma->vm_end) +return -EINVAL ; + +mmap_assert_locked (walk.mm); +return __walk_page_range (start, end, &walk); +} +int walk_page_vma (struct vm_area_struct *vma,const struct mm_walk_ops *ops,void *private) {
Greg Kroah-Hartman
maintainerPATCH 174/206 ksm: use range-walk function to jump over holes in scan_get_next_rmap_item
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pedro Demarchi Gomes <[email protected]>
[ Upstream commit f5548c318d6520d4fa3c5ed6003eeb710763cbc5 ]
Currently, scan_get_next_rmap_item() walks every page address in a VMA to locate mergeable pages. This becomes highly inefficient when scanning large virtual memory areas that contain mostly unmapped regions, causing ksmd to use large amount of cpu without deduplicating much pages.
This patch replaces the per-address lookup with a range walk using walk_page_range(). The range walker allows KSM to skip over entire unmapped holes in a VMA, avoiding unnecessary lookups. This problem was previously discussed in [1].
Consider the following test program which creates a 32 TiB mapping in the virtual address space but only populates a single page:
/* 32 TiB */
const size_t size = 32ul * 1024 * 1024 * 1024 * 1024;
int main() {
char *area = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_NORESERVE | MAP_PRIVATE | MAP_ANON, -1, 0);
if (area == MAP_FAILED) {
perror("mmap() failed\n");
return -1;
}
/* Populate a single page such that we get an anon_vma. */
*area = 0;
/* Enable KSM. */
madvise(area, size, MADV_MERGEABLE);
pause();
return 0;
}$ ./ksm-sparse & $ echo 1 > /sys/kernel/mm/ksm/run
Without this patch ksmd uses 100% of the cpu for a long time (more then 1 hour in my test machine) scanning all the 32 TiB virtual address space that contain only one mapped page. This makes ksmd essentially deadlocked not able to deduplicate anything of value. With this patch ksmd walks only the one mapped page and skips the rest of the 32 TiB virtual address space, making the scan fast using little cpu.
[ change folio to page, replace pmdp_get_lockless with pmd_read_atomic and pmdp_get with
READ_ONCE(*pmdp) ]
--- mm/ksm.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 105 insertions(+), 10 deletions(-)
mm/ksm.c +105 -10
@@ -38,6 +38,7 @@#include <linux/freezer.h> #include <linux/oom.h> #include <linux/numa.h> +#include <linux/pagewalk.h> #include <asm/tlbflush.h> #include "internal.h"
@@ -2214,6 +2215,89 @@ static struct rmap_item *get_next_rmap_ireturn rmap_item; } +struct ksm_next_page_arg { +struct page *page; +unsigned long addr; +}; + +static int ksm_next_page_pmd_entry (pmd_t *pmdp,unsigned long addr,unsigned long end, +struct mm_walk *walk) +{ +struct ksm_next_page_arg *private = walk->private; +struct vm_area_struct *vma = walk->vma; +pte_t *start_ptep =NULL , *ptep, pte; +struct mm_struct *mm = walk->mm; +struct page *page; +spinlock_t *ptl; +pmd_t pmd; + +if (ksm_test_exit (mm)) +return 0 ; + +cond_resched (); + + pmd =pmd_read_atomic (pmdp); +if (!pmd_present (pmd)) +return 0 ; + +if (IS_ENABLED (CONFIG_TRANSPARENT_HUGEPAGE ) &&pmd_leaf (pmd)) { + ptl =pmd_lock (mm, pmdp); + pmd =READ_ONCE (*pmdp); + +if (!pmd_present (pmd)) { + goto not_found_unlock; + }else if (pmd_leaf (pmd)) { + page =vm_normal_page_pmd (vma, addr, pmd); +if (!page) + goto not_found_unlock; + +if (is_zone_device_page (page) || !PageAnon (page)) + goto not_found_unlock; + + page += ((addr & (PMD_SIZE -1 )) >>PAGE_SHIFT ); + goto found_unlock; + } +spin_unlock (ptl); + } + + start_ptep =pte_offset_map_lock (mm, pmdp, addr, &ptl); +if (!start_ptep) +return 0 ; + +for (ptep = start_ptep; addr < end; ptep++, addr +=PAGE_SIZE ) { + pte =ptep_get (ptep); + +if (!pte_present (pte)) +continue ; + + page =vm_normal_page (vma, addr, pte); +if (!page) +continue ; + +if (is_zone_device_page (page) || !PageAnon (page)) +continue ; + goto found_unlock; + } + +not_found_unlock: +spin_unlock (ptl); +if (start_ptep) +pte_unmap (start_ptep); +return 0 ; +found_unlock: +get_page (page); +spin_unlock (ptl); +if (start_ptep) +pte_unmap (start_ptep); + private->page = page; + private->addr = addr; +return 1 ; +} + +static struct mm_walk_ops ksm_next_page_ops = { + .pmd_entry = ksm_next_page_pmd_entry, +}; +static struct rmap_item *scan_get_next_rmap_item (struct page **page) {struct mm_struct *mm;
@@ -2293,29 +2377,40 @@ next_mm: ksm_scan.address = vma->vm_end;while (ksm_scan.address < vma->vm_end) { +struct ksm_next_page_arg ksm_next_page_arg; +struct page *tmp_page =NULL ; +int found; +if (ksm_test_exit (mm))break ; - *page =follow_page (vma, ksm_scan.address,FOLL_GET ); -if (IS_ERR_OR_NULL (*page)) { - ksm_scan.address +=PAGE_SIZE ; -cond_resched (); -continue ; + + found =walk_page_range_vma (vma, ksm_scan.address, + vma->vm_end, + &ksm_next_page_ops, + &ksm_next_page_arg); + +if (found >0 ) { + tmp_page = ksm_next_page_arg.page; + ksm_scan.address = ksm_next_page_arg.addr; + }else { +VM_WARN_ON_ONCE (found <0 ); + ksm_scan.address = vma->vm_end -PAGE_SIZE ; } -if (PageAnon (*page)) { -flush_anon_page (vma, *page, ksm_scan.address); -flush_dcache_page (*page); +if (tmp_page) { +flush_anon_page (vma, tmp_page, ksm_scan.address); +flush_dcache_page (tmp_page); rmap_item =get_next_rmap_item (slot, ksm_scan.rmap_list, ksm_scan.address);if (rmap_item) { ksm_scan.rmap_list = &rmap_item->rmap_list; ksm_scan.address +=PAGE_SIZE ; + *page = tmp_page; }else -put_page (*page); +put_page (tmp_page);mmap_read_unlock (mm);return rmap_item; } -put_page (*page); ksm_scan.address +=PAGE_SIZE ;cond_resched (); }
Greg Kroah-Hartman
maintainerPATCH 175/206 drm/ttm: fix undefined behavior in bit shift for TTM_TT_FLAG_PRIV_POPULATED
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gaosheng Cui <[email protected]>
[ Upstream 387659939c00156f8d6bab0fbc55b4eaf2b6bc5b commit ]
Shifting signed 32-bit value by 31 bits is undefined, so changing significant bit to unsigned. The UBSAN warning calltrace like below:
UBSAN: shift-out-of-bounds in ./include/drm/ttm/ttm_tt.h:122:26 left shift of 1 by 31 places cannot be represented in type 'int' Call Trace: <TASK> dump_stack_lvl+0x7d/0xa5 dump_stack+0x15/0x1b ubsan_epilogue+0xe/0x4e __ubsan_handle_shift_out_of_bounds+0x1e7/0x20c ttm_bo_move_memcpy+0x3b4/0x460 [ttm] bo_driver_move+0x32/0x40 [drm_vram_helper] ttm_bo_handle_move_mem+0x118/0x200 [ttm] ttm_bo_validate+0xfa/0x220 [ttm] drm_gem_vram_pin_locked+0x70/0x1b0 [drm_vram_helper] drm_gem_vram_pin+0x48/0xb0 [drm_vram_helper] drm_gem_vram_plane_helper_prepare_fb+0x53/0xe0 [drm_vram_helper] drm_gem_vram_simple_display_pipe_prepare_fb+0x26/0x30 [drm_vram_helper] drm_simple_kms_plane_prepare_fb+0x4d/0xe0 [drm_kms_helper] drm_atomic_helper_prepare_planes+0xda/0x210 [drm_kms_helper] drm_atomic_helper_commit+0xc3/0x1e0 [drm_kms_helper] drm_atomic_commit+0x9c/0x160 [drm] drm_client_modeset_commit_atomic+0x33a/0x380 [drm] drm_client_modeset_commit_locked+0x77/0x220 [drm] drm_client_modeset_commit+0x31/0x60 [drm] __drm_fb_helper_restore_fbdev_mode_unlocked+0xa7/0x170 [drm_kms_helper] drm_fb_helper_set_par+0x51/0x90 [drm_kms_helper] fbcon_init+0x316/0x790 visual_init+0x113/0x1d0 do_bind_con_driver+0x2a3/0x5c0 do_take_over_console+0xa9/0x270 do_fbcon_takeover+0xa1/0x170 do_fb_registered+0x2a8/0x340 fbcon_fb_registered+0x47/0xe0 register_framebuffer+0x294/0x4a0 __drm_fb_helper_initial_config_and_unlock+0x43c/0x880 [drm_kms_helper] drm_fb_helper_initial_config+0x52/0x80 [drm_kms_helper] drm_fbdev_client_hotplug+0x156/0x1b0 [drm_kms_helper] drm_fbdev_generic_setup+0xfc/0x290 [drm_kms_helper] bochs_pci_probe+0x6ca/0x772 [bochs] local_pci_probe+0x4d/0xb0 pci_device_probe+0x119/0x320 really_probe+0x181/0x550 __driver_probe_device+0xc6/0x220 driver_probe_device+0x32/0x100 __driver_attach+0x195/0x200 bus_for_each_dev+0xbb/0x120 driver_attach+0x27/0x30 bus_add_driver+0x22e/0x2f0 driver_register+0xa9/0x190 __pci_register_driver+0x90/0xa0 bochs_pci_driver_init+0x52/0x1000 [bochs] do_one_initcall+0x76/0x430 do_init_module+0x61/0x28a load_module+0x1f82/0x2e50 __do_sys_finit_module+0xf8/0x190 __x64_sys_finit_module+0x23/0x30 do_syscall_64+0x58/0x80 entry_SYSCALL_64_after_hwframe+0x63/0xcd </TASK>
[ The context change is due to the commit 43d46f0b78bb ("drm/ttm: s/FLAG_SG/FLAG_EXTERNAL/") in v5.16 which is irrelevant to the logic of this patch. In addition, v6.1 has included the fix. ]
--- include/drm/ttm/ttm_tt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/drm/ttm/ttm_tt.h +1 -1
@@ -43,7 +43,7 @@ struct ttm_operation_ctx;#define TTM_PAGE_FLAG_SG (1 << 8)#define TTM_PAGE_FLAG_NO_RETRY (1 << 9) -#define TTM_PAGE_FLAG_PRIV_POPULATED (1 << 31) +#define TTM_PAGE_FLAG_PRIV_POPULATED (1U << 31)/** * struct ttm_tt
Greg Kroah-Hartman
maintainerPATCH 176/206 ksmbd: fix use-after-free in ksmbd_tree_connect_put under concurrency
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit b39a1833cc4a2755b02603eec3a71a85e9dff926 ]
Under high concurrency, A tree-connection object (tcon) is freed on a disconnect path while another path still holds a reference and later executes *_put()/write on it.
--- fs/ksmbd/mgmt/tree_connect.c | 18 ++++-------------- fs/ksmbd/mgmt/tree_connect.h | 1 - fs/ksmbd/smb2pdu.c | 3 --- 3 files changed, 4 insertions(+), 18 deletions(-)
fs/ksmbd/mgmt/tree_connect.c +4 -14
@@ -76,7 +76,6 @@ ksmbd_tree_conn_connect(struct ksmbd_con tree_conn->t_state =TREE_NEW ; status.tree_conn = tree_conn;atomic_set (&tree_conn->refcount,1 ); -init_waitqueue_head (&tree_conn->refcount_q); ret =xa_err (xa_store (&sess->tree_conns, tree_conn->id, tree_conn,GFP_KERNEL ));
@@ -98,14 +97,8 @@ out_error:void ksmbd_tree_connect_put (struct ksmbd_tree_connect *tcon) { -/* -* Checking waitqueue to releasing tree connect on -* tree disconnect. waitqueue_active is safe because it -* uses atomic operation for condition. -*/ -if (!atomic_dec_return (&tcon->refcount) && -waitqueue_active (&tcon->refcount_q)) -wake_up (&tcon->refcount_q); +if (atomic_dec_and_test (&tcon->refcount)) +kfree (tcon); } int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
@@ -117,14 +110,11 @@ int ksmbd_tree_conn_disconnect(struct ksxa_erase (&sess->tree_conns, tree_conn->id);write_unlock (&sess->tree_conns_lock); -if (!atomic_dec_and_test (&tree_conn->refcount)) -wait_event (tree_conn->refcount_q, -atomic_read (&tree_conn->refcount) ==0 ); - ret =ksmbd_ipc_tree_disconnect_request (sess->id, tree_conn->id);ksmbd_release_tree_conn_id (sess, tree_conn->id);ksmbd_share_config_put (tree_conn->share_conf); -kfree (tree_conn); +if (atomic_dec_and_test (&tree_conn->refcount)) +kfree (tree_conn);return ret; }
fs/ksmbd/mgmt/tree_connect.h +0 -1
@@ -32,7 +32,6 @@ struct ksmbd_tree_connect {int maximal_access;bool posix_extensions;atomic_t refcount; -wait_queue_head_t refcount_q;unsigned int t_state; };
fs/ksmbd/smb2pdu.c +0 -3
@@ -2169,7 +2169,6 @@ int smb2_tree_disconnect(struct ksmbd_wo goto err_out; } -WARN_ON_ONCE (atomic_dec_and_test (&tcon->refcount)); tcon->t_state =TREE_DISCONNECTED ;write_unlock (&sess->tree_conns_lock);
@@ -2179,8 +2178,6 @@ int smb2_tree_disconnect(struct ksmbd_wo goto err_out; } - work->tcon =NULL ; - rsp->StructureSize =cpu_to_le16 (4 ); err =ksmbd_iov_pin_rsp (work, rsp,sizeof (struct smb2_tree_disconnect_rsp ));
Greg Kroah-Hartman
maintainerPATCH 177/206 fs/ntfs3: Initialize allocated memory before use
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartlomiej Kubik <[email protected]>
[ Upstream commit a8a3ca23bbd9d849308a7921a049330dc6c91398 ]
KMSAN reports: Multiple uninitialized values detected:
- KMSAN: uninit-value in ntfs_read_hdr (3)
- KMSAN: uninit-value in bcmp (3)
Memory is allocated by __getname(), which is a wrapper for kmem_cache_alloc(). This memory is used before being properly cleared. Change kmem_cache_alloc() to kmem_cache_zalloc() to properly allocate and clear memory before use.
--- fs/ntfs3/inode.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
fs/ntfs3/inode.c +3 -4
@@ -1298,7 +1298,7 @@ struct inode *ntfs_create_inode(struct u fa |=FILE_ATTRIBUTE_READONLY ;/* Allocate PATH_MAX bytes. */ - new_de =__getname (); + new_de =kmem_cache_zalloc (names_cachep,GFP_KERNEL );if (!new_de) { err = -ENOMEM ; goto out1;
@@ -1694,10 +1694,9 @@ int ntfs_link_inode(struct inode *inode,struct ATTR_FILE_NAME *de_name;/* Allocate PATH_MAX bytes. */ - de =__getname (); + de =kmem_cache_zalloc (names_cachep,GFP_KERNEL );if (!de)return -ENOMEM ; -memset (de,0 ,PATH_MAX );/* Mark rw ntfs as dirty. It will be cleared at umount. */ ntfs_set_state (sbi,NTFS_DIRTY_DIRTY );
@@ -1742,7 +1741,7 @@ int ntfs_unlink_inode(struct inode *dir,return -EINVAL ;/* Allocate PATH_MAX bytes. */ - de =__getname (); + de =kmem_cache_zalloc (names_cachep,GFP_KERNEL );if (!de)return -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 178/206 blk-cgroup: Reinit blkg_iostat_set after clearing in blkcg_reset_stats()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Waiman Long <[email protected]>
[ Upstream commit 3d2af77e31ade05ff7ccc3658c3635ec1bea0979 ]
When blkg_alloc() is called to allocate a blkcg_gq structure with the associated blkg_iostat_set's, there are 2 fields within blkg_iostat_set that requires proper initialization - blkg & sync. The former field was introduced by commit 3b8cc6298724 ("blk-cgroup:
Optimize blkcg_rstat_flush()") while the later one was introduced by commit f73316482977 ("blk-cgroup: reimplement basic IO stats using cgroup rstat").
Unfortunately those fields in the blkg_iostat_set's are not properly re-initialized when they are cleared in v1's blkcg_reset_stats(). This can lead to a kernel panic due to NULL pointer access of the blkg pointer. The missing initialization of sync is less problematic and can be a problem in a debug kernel due to missing lockdep initialization.
Fix these problems by re-initializing them after memory clearing.
[ Remove this line: bis -> blkg = blkg for blkg was introduced by commit
3b8cc6298724 ("blk-cgroup: Optimize blkcg_rstat_flush()") since v6.2. ]
--- block/blk-cgroup.c | 4 ++++ 1 file changed, 4 insertions(+)
block/blk-cgroup.c +4 -0
@@ -491,8 +491,12 @@ static int blkcg_reset_stats(struct cgrostruct blkg_iostat_set *bis =per_cpu_ptr (blkg->iostat_cpu, cpu);memset (bis,0 ,sizeof (*bis)); + +/* Re-initialize the cleared blkg_iostat_set */ +u64_stats_init (&bis->sync); }memset (&blkg->iostat,0 ,sizeof (blkg->iostat)); +u64_stats_init (&blkg->iostat.sync);for (i =0 ; i <BLKCG_MAX_POLS ; i++) {struct blkcg_policy *pol = blkcg_policy[i];
Greg Kroah-Hartman
maintainerPATCH 179/206 espintcp: fix skb leaks
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
[ Upstream commit 63c1f19a3be3169e51a5812d22a6d0c879414076 ]
A few error paths are missing a kfree_skb.
--- net/ipv4/esp4.c | 4 +++- net/ipv6/esp6.c | 4 +++- net/xfrm/espintcp.c | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-)
net/ipv4/esp4.c +3 -1
@@ -196,8 +196,10 @@ static int esp_output_tcp_finish(struct sk =esp_find_tcp_sk (x); err =PTR_ERR_OR_ZERO (sk); -if (err) +if (err) { +kfree_skb (skb); goto out; + }bh_lock_sock (sk);if (sock_owned_by_user (sk))
net/ipv6/esp6.c +3 -1
@@ -214,8 +214,10 @@ static int esp_output_tcp_finish(struct sk =esp6_find_tcp_sk (x); err =PTR_ERR_OR_ZERO (sk); -if (err) +if (err) { +kfree_skb (skb); goto out; + }bh_lock_sock (sk);if (sock_owned_by_user (sk))
net/xfrm/espintcp.c +3 -1
@@ -170,8 +170,10 @@ int espintcp_queue_out(struct sock *sk, {struct espintcp_ctx *ctx =espintcp_getctx (sk); -if (skb_queue_len (&ctx->out_queue) >=READ_ONCE (netdev_max_backlog)) +if (skb_queue_len (&ctx->out_queue) >=READ_ONCE (netdev_max_backlog)) { +kfree_skb (skb);return -ENOBUFS ; + }__skb_queue_tail (&ctx->out_queue, skb);
Greg Kroah-Hartman
maintainerPATCH 180/206 ext4: fix memory leaks in ext4_fname_{setup_filename,prepare_lookup}
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luís Henriques <[email protected]>
[ Upstream commit 7ca4b085f430f3774c3838b3da569ceccd6a0177 ]
If the filename casefolding fails, we'll be leaking memory from the fscrypt_name struct, namely from the 'crypto_buf.name' member.
Make sure we free it in the error path on both ext4_fname_setup_filename() and ext4_fname_prepare_lookup() functions.
[ fs/ext4/crypto.c was removed by commit
a7550b30ab70 ("ext4 crypto: migrate into vfs's crypto engine") since v4.8, so apply this patch to fs/ext4/ext4.h in v5.15. Move ext4_fname_free_filename() to the front of ext4_fname_setup_filename() to fix a build issue. ]
--- fs/ext4/ext4.h | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-)
fs/ext4/ext4.h +21 -17
@@ -2749,6 +2749,23 @@ static inline void ext4_fname_from_fscry dst->crypto_buf = src->crypto_buf; } +static inline void ext4_fname_free_filename (struct ext4_filename *fname) +{ +struct fscrypt_name name; + + name.crypto_buf = fname->crypto_buf; +fscrypt_free_filename (&name); + + fname->crypto_buf.name =NULL ; + fname->usr_fname =NULL ; + fname->disk_name.name =NULL ; + +#ifdef CONFIG_UNICODE +kfree (fname->cf_name.name); + fname->cf_name.name =NULL ; +#endif +} + static inline int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname, int lookup,
@@ -2765,6 +2782,8 @@ static inline int ext4_fname_setup_filen#ifdef CONFIG_UNICODE err =ext4_fname_setup_ci_filename (dir, iname, fname); +if (err) +ext4_fname_free_filename (fname);#endif return err; }
@@ -2784,26 +2803,11 @@ static inline int ext4_fname_prepare_loo#ifdef CONFIG_UNICODE err =ext4_fname_setup_ci_filename (dir, &dentry->d_name, fname); +if (err) +ext4_fname_free_filename (fname);#endif return err; } - -static inline void ext4_fname_free_filename (struct ext4_filename *fname) -{ -struct fscrypt_name name; - - name.crypto_buf = fname->crypto_buf; -fscrypt_free_filename (&name); - - fname->crypto_buf.name =NULL ; - fname->usr_fname =NULL ; - fname->disk_name.name =NULL ; - -#ifdef CONFIG_UNICODE -kfree (fname->cf_name.name); - fname->cf_name.name =NULL ; -#endif -}#else /* !CONFIG_FS_ENCRYPTION */ static inline int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
Greg Kroah-Hartman
maintainerPATCH 181/206 NFSD: fix race between nfsd registration and exports_proc
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maninder Singh <[email protected]>
[ Upstream commit f7fb730cac9aafda8b9813b55d04e28a9664d17c ]
As of now nfsd calls create_proc_exports_entry() at start of init_nfsd and cleanup by remove_proc_entry() at last of exit_nfsd.
Which causes kernel OOPs if there is race between below 2 operations:
(i) exportfs -r
(ii) mount -t nfsd none /proc/fs/nfsd
for 5.4 kernel ARM64:
CPU 1:
el1_irq+0xbc/0x180 arch_counter_get_cntvct+0x14/0x18 running_clock+0xc/0x18 preempt_count_add+0x88/0x110 prep_new_page+0xb0/0x220 get_page_from_freelist+0x2d8/0x1778 __alloc_pages_nodemask+0x15c/0xef0 __vmalloc_node_range+0x28c/0x478 __vmalloc_node_flags_caller+0x8c/0xb0 kvmalloc_node+0x88/0xe0 nfsd_init_net+0x6c/0x108 [nfsd] ops_init+0x44/0x170 register_pernet_operations+0x114/0x270 register_pernet_subsys+0x34/0x50 init_nfsd+0xa8/0x718 [nfsd] do_one_initcall+0x54/0x2e0
CPU 2 :
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010
PC is at : exports_net_open+0x50/0x68 [nfsd]
Call trace: exports_net_open+0x50/0x68 [nfsd] exports_proc_open+0x2c/0x38 [nfsd] proc_reg_open+0xb8/0x198 do_dentry_open+0x1c4/0x418 vfs_open+0x38/0x48 path_openat+0x28c/0xf18 do_filp_open+0x70/0xe8 do_sys_open+0x154/0x248
Sometimes it crashes at exports_net_open() and sometimes cache_seq_next_rcu().
and same is happening on latest 6.14 kernel as well:
[ 0.000000] Linux version 6.14.0-rc5-next-20250304-dirty ... [ 285.455918] Unable to handle kernel paging request at virtual address 00001f4800001f48 ... [ 285.464902] pc : cache_seq_next_rcu+0x78/0xa4 ... [ 285.469695] Call trace: [ 285.470083] cache_seq_next_rcu+0x78/0xa4 (P) [ 285.470488] seq_read+0xe0/0x11c [ 285.470675] proc_reg_read+0x9c/0xf0 [ 285.470874] vfs_read+0xc4/0x2fc [ 285.471057] ksys_read+0x6c/0xf4 [ 285.471231] __arm64_sys_read+0x1c/0x28 [ 285.471428] invoke_syscall+0x44/0x100 [ 285.471633] el0_svc_common.constprop.0+0x40/0xe0 [ 285.471870] do_el0_svc_compat+0x1c/0x34 [ 285.472073] el0_svc_compat+0x2c/0x80 [ 285.472265] el0t_32_sync_handler+0x90/0x140 [ 285.472473] el0t_32_sync+0x19c/0x1a0 [ 285.472887] Code: f9400885 93407c23 937d7c27 11000421 (f86378a3) [ 285.473422] ---[ end trace 0000000000000000 ]---
It reproduced simply with below script:
while [ 1 ]
do
/exportfs -r
done &
while [ 1 ]
do
insmod /nfsd.ko
mount -t nfsd none /proc/fs/nfsd
umount /proc/fs/nfsd
rmmod nfsd
done &
So exporting interfaces to user space shall be done at last and cleanup at first place.
With change there is no Kernel OOPs.
[ The context change is due to the commit bd9d6a3efa97 ("NFSD: add rpc_status netlink support") in v6.7 and the proper adoption is done. ]
--- fs/nfsd/nfsctl.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
fs/nfsd/nfsctl.c +8 -9
@@ -1511,12 +1511,9 @@ static int __init init_nfsd(void)if (retval) goto out_free_pnfs;nfsd_lockd_init ();/* lockd->nfsd callbacks */ - retval =create_proc_exports_entry (); -if (retval) - goto out_free_lockd; retval =register_pernet_subsys (&nfsd_net_ops);if (retval <0 ) - goto out_free_exports; + goto out_free_lockd; retval =register_cld_notifier ();if (retval) goto out_free_subsys;
@@ -1525,17 +1522,19 @@ static int __init init_nfsd(void) goto out_free_cld; retval =register_filesystem (&nfsd_fs_type);if (retval) + goto out_free_nfsd4; + retval =create_proc_exports_entry (); +if (retval) goto out_free_all;return 0 ; out_free_all: +unregister_filesystem (&nfsd_fs_type); +out_free_nfsd4:nfsd4_destroy_laundry_wq (); out_free_cld:unregister_cld_notifier (); out_free_subsys:unregister_pernet_subsys (&nfsd_net_ops); -out_free_exports: -remove_proc_entry ("fs/nfs/exports" ,NULL ); -remove_proc_entry ("fs/nfs" ,NULL ); out_free_lockd:nfsd_lockd_shutdown ();nfsd_drc_slab_free ();
@@ -1548,13 +1547,13 @@ out_free_slabs: static void __exit exit_nfsd(void) { +remove_proc_entry ("fs/nfs/exports" ,NULL ); +remove_proc_entry ("fs/nfs" ,NULL );unregister_filesystem (&nfsd_fs_type);nfsd4_destroy_laundry_wq ();unregister_cld_notifier ();unregister_pernet_subsys (&nfsd_net_ops);nfsd_drc_slab_free (); -remove_proc_entry ("fs/nfs/exports" ,NULL ); -remove_proc_entry ("fs/nfs" ,NULL );nfsd_lockd_shutdown ();nfsd4_free_slabs ();nfsd4_exit_pnfs ();
Greg Kroah-Hartman
maintainerPATCH 182/206 usbnet: Fix using smp_processor_id() in preemptible code warnings
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zqiang <[email protected]>
[ Upstream commit 327cd4b68b4398b6c24f10eb2b2533ffbfc10185 ]
Syzbot reported the following warning:
BUG: using smp_processor_id() in preemptible [00000000] code: dhcpcd/2879 caller is usbnet_skb_return+0x74/0x490 drivers/net/usb/usbnet.c:331 CPU: 1 UID: 0 PID: 2879 Comm: dhcpcd Not tainted 6.15.0-rc4-syzkaller-00098-g615dca38c2ea #0 PREEMPT(voluntary) Call Trace: <TASK> __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x16c/0x1f0 lib/dump_stack.c:120 check_preemption_disabled+0xd0/0xe0 lib/smp_processor_id.c:49 usbnet_skb_return+0x74/0x490 drivers/net/usb/usbnet.c:331 usbnet_resume_rx+0x4b/0x170 drivers/net/usb/usbnet.c:708 usbnet_change_mtu+0x1be/0x220 drivers/net/usb/usbnet.c:417 __dev_set_mtu net/core/dev.c:9443 [inline] netif_set_mtu_ext+0x369/0x5c0 net/core/dev.c:9496 netif_set_mtu+0xb0/0x160 net/core/dev.c:9520 dev_set_mtu+0xae/0x170 net/core/dev_api.c:247 dev_ifsioc+0xa31/0x18d0 net/core/dev_ioctl.c:572 dev_ioctl+0x223/0x10e0 net/core/dev_ioctl.c:821 sock_do_ioctl+0x19d/0x280 net/socket.c:1204 sock_ioctl+0x42f/0x6a0 net/socket.c:1311 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:906 [inline] __se_sys_ioctl fs/ioctl.c:892 [inline] __x64_sys_ioctl+0x190/0x200 fs/ioctl.c:892 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xcd/0x260 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f
For historical and portability reasons, the netif_rx() is usually run in the softirq or interrupt context, this commit therefore add local_bh_disable/enable() protection in the usbnet_resume_rx().
[ The context change is due to the commit 2c04d279e857 ("net: usb: Convert tasklet API to new bottom half workqueue mechanism") in v6.17 which is irrelevant to the logic of this patch.]
--- drivers/net/usb/usbnet.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/usb/usbnet.c +2 -0
@@ -707,6 +707,7 @@ void usbnet_resume_rx(struct usbnet *devstruct sk_buff *skb;int num =0 ; +local_bh_disable ();clear_bit (EVENT_RX_PAUSED , &dev->flags);while ((skb =skb_dequeue (&dev->rxq_pause)) !=NULL ) {
@@ -715,6 +716,7 @@ void usbnet_resume_rx(struct usbnet *dev }tasklet_schedule (&dev->bh); +local_bh_enable ();netif_dbg (dev, rx_status, dev->net,"paused rx queue disabled, %d skbs requeued\n" , num);
Greg Kroah-Hartman
maintainerPATCH 183/206 net: stmmac: make sure that ptp_rate is not 0 before configuring EST
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexis Lothoré <[email protected]>
[ Upstream commit cbefe2ffa7784525ec5d008ba87c7add19ec631a ]
If the ptp_rate recorded earlier in the driver happens to be 0, this bogus value will propagate up to EST configuration, where it will trigger a division by 0.
Prevent this division by 0 by adding the corresponding check and error code.
[ The context change is due to the commit c3f3b97238f6 ("net: stmmac: Refactor EST implementation") and the proper adoption is done. ]
--- drivers/net/ethernet/stmicro/stmmac/dwmac5.c | 5 +++++ drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 5 +++++ 2 files changed, 10 insertions(+)
drivers/net/ethernet/stmicro/stmmac/dwmac5.c +5 -0
@@ -597,6 +597,11 @@ int dwmac5_est_configure(void __iomem *iint i, ret =0x0 ;u32 ctrl; +if (!ptp_rate) { +pr_warn ("Dwmac5: Invalid PTP rate" ); +return -EINVAL ; + } + ret |=dwmac5_est_write (ioaddr,BTR_LOW , cfg->btr[0 ], false); ret |=dwmac5_est_write (ioaddr,BTR_HIGH , cfg->btr[1 ], false); ret |=dwmac5_est_write (ioaddr,TER , cfg->ter, false);
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +5 -0
@@ -1494,6 +1494,11 @@ static int dwxgmac3_est_configure(void _int i, ret =0x0 ;u32 ctrl; +if (!ptp_rate) { +pr_warn ("Dwxgmac2: Invalid PTP rate" ); +return -EINVAL ; + } + ret |=dwxgmac3_est_write (ioaddr,XGMAC_BTR_LOW , cfg->btr[0 ], false); ret |=dwxgmac3_est_write (ioaddr,XGMAC_BTR_HIGH , cfg->btr[1 ], false); ret |=dwxgmac3_est_write (ioaddr,XGMAC_TER , cfg->ter, false);
Greg Kroah-Hartman
maintainerPATCH 184/206 Bluetooth: Fix hci_suspend_sync crash
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ying Hsu <[email protected]>
[ Upstream commit 573ebae162111063eedc6c838a659ba628f66a0f ]
If hci_unregister_dev() frees the hci_dev object but hci_suspend_notifier may still be accessing it, it can cause the program to crash. Here's the call trace:
<4>[102152.653246] Call Trace: <4>[102152.653254] hci_suspend_sync+0x109/0x301 [bluetooth] <4>[102152.653259] hci_suspend_dev+0x78/0xcd [bluetooth] <4>[102152.653263] hci_suspend_notifier+0x42/0x7a [bluetooth] <4>[102152.653268] notifier_call_chain+0x43/0x6b <4>[102152.653271] __blocking_notifier_call_chain+0x48/0x69 <4>[102152.653273] __pm_notifier_call_chain+0x22/0x39 <4>[102152.653276] pm_suspend+0x287/0x57c <4>[102152.653278] state_store+0xae/0xe5 <4>[102152.653281] kernfs_fop_write+0x109/0x173 <4>[102152.653284] __vfs_write+0x16f/0x1a2 <4>[102152.653287] ? selinux_file_permission+0xca/0x16f <4>[102152.653289] ? security_file_permission+0x36/0x109 <4>[102152.653291] vfs_write+0x114/0x21d <4>[102152.653293] __x64_sys_write+0x7b/0xdb <4>[102152.653296] do_syscall_64+0x59/0x194 <4>[102152.653299] entry_SYSCALL_64_after_hwframe+0x5c/0xc1
This patch holds the reference count of the hci_dev object while processing it in hci_suspend_notifier to avoid potential crash caused by the race condition.
--- net/bluetooth/hci_core.c | 4 ++++ 1 file changed, 4 insertions(+)
net/bluetooth/hci_core.c +4 -0
@@ -3706,6 +3706,9 @@ static int hci_suspend_notifier(struct nint ret =0 ;u8 state =BT_RUNNING ; +/* To avoid a potential race with hci_unregister_dev. */ +hci_dev_hold (hdev); +/* If powering down, wait for completion. */ if (mgmt_powering_down (hdev)) {set_bit (SUSPEND_POWERING_DOWN , hdev->suspend_tasks);
@@ -3757,6 +3760,7 @@ done:bt_dev_err (hdev,"Suspend notifier action (%lu) failed: %d" , action, ret); +hci_dev_put (hdev);return NOTIFY_DONE ; }
Greg Kroah-Hartman
maintainerPATCH 185/206 wifi: cfg80211: add a work abstraction with special semantics
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit a3ee4dc84c4e9d14cb34dad095fd678127aca5b6 ]
Add a work abstraction at the cfg80211 level that will always hold the wiphy_lock() for any work executed and therefore also can be canceled safely (without waiting) while holding that. This improves on what we do now as with the new wiphy works we don't have to worry about locking while cancelling them safely.
Also, don't let such works run while the device is suspended, since they'll likely need to interact with the device. Flush them before suspend though.
--- include/net/cfg80211.h | 95 ++++++++++++++++++++++++++++++++++++-- net/wireless/core.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++ net/wireless/core.h | 7 ++ net/wireless/sysfs.c | 8 ++- 4 files changed, 226 insertions(+), 5 deletions(-)
include/net/cfg80211.h +91 -4
@@ -5301,12 +5301,17 @@ struct cfg80211_cqm_config;* wiphy_lock - lock the wiphy * @wiphy: the wiphy to lock * -* This is mostly exposed so it can be done around registering and -* unregistering netdevs that aren't created through cfg80211 calls, -* since that requires locking in cfg80211 when the notifiers is -* called, but that cannot differentiate which way it's called. +* This is needed around registering and unregistering netdevs that +* aren't created through cfg80211 calls, since that requires locking +* in cfg80211 when the notifiers is called, but that cannot +* differentiate which way it's called. +* +* It can also be used by drivers for their own purposes. * * When cfg80211 ops are called, the wiphy is already locked. +* +* Note that this makes sure that no workers that have been queued +* with wiphy_queue_work() are running. */ static inline void wiphy_lock(struct wiphy *wiphy) __acquires(&wiphy->mtx)
@@ -5326,6 +5331,88 @@ static inline void wiphy_unlock(struct wmutex_unlock (&wiphy->mtx); } +struct wiphy_work ; +typedef void (*wiphy_work_func_t )(struct wiphy *,struct wiphy_work *); + +struct wiphy_work { +struct list_head entry; +wiphy_work_func_t func; +}; + +static inline void wiphy_work_init (struct wiphy_work *work, +wiphy_work_func_t func) +{ +INIT_LIST_HEAD (&work->entry); + work->func = func; +} + +/** +* wiphy_work_queue - queue work for the wiphy +* @wiphy: the wiphy to queue for +* @work: the work item +* +* This is useful for work that must be done asynchronously, and work +* queued here has the special property that the wiphy mutex will be +* held as if wiphy_lock() was called, and that it cannot be running +* after wiphy_lock() was called. Therefore, wiphy_cancel_work() can +* use just cancel_work() instead of cancel_work_sync(), it requires +* being in a section protected by wiphy_lock(). +*/ +void wiphy_work_queue (struct wiphy *wiphy,struct wiphy_work *work); + +/** +* wiphy_work_cancel - cancel previously queued work +* @wiphy: the wiphy, for debug purposes +* @work: the work to cancel +* +* Cancel the work *without* waiting for it, this assumes being +* called under the wiphy mutex acquired by wiphy_lock(). +*/ +void wiphy_work_cancel (struct wiphy *wiphy,struct wiphy_work *work); + +struct wiphy_delayed_work { +struct wiphy_work work; +struct wiphy *wiphy; +struct timer_list timer; +}; + +void wiphy_delayed_work_timer (struct timer_list *t); + +static inline void wiphy_delayed_work_init (struct wiphy_delayed_work *dwork, +wiphy_work_func_t func) +{ +timer_setup (&dwork->timer, wiphy_delayed_work_timer,0 ); +wiphy_work_init (&dwork->work, func); +} + +/** +* wiphy_delayed_work_queue - queue delayed work for the wiphy +* @wiphy: the wiphy to queue for +* @dwork: the delayable worker +* @delay: number of jiffies to wait before queueing +* +* This is useful for work that must be done asynchronously, and work +* queued here has the special property that the wiphy mutex will be +* held as if wiphy_lock() was called, and that it cannot be running +* after wiphy_lock() was called. Therefore, wiphy_cancel_work() can +* use just cancel_work() instead of cancel_work_sync(), it requires +* being in a section protected by wiphy_lock(). +*/ +void wiphy_delayed_work_queue (struct wiphy *wiphy, +struct wiphy_delayed_work *dwork, +unsigned long delay); + +/** +* wiphy_delayed_work_cancel - cancel previously queued delayed work +* @wiphy: the wiphy, for debug purposes +* @dwork: the delayed work to cancel +* +* Cancel the work *without* waiting for it, this assumes being +* called under the wiphy mutex acquired by wiphy_lock(). +*/ +void wiphy_delayed_work_cancel (struct wiphy *wiphy, +struct wiphy_delayed_work *dwork); +/** * struct wireless_dev - wireless device state *
net/wireless/core.c +121 -0
154 lines not on this page · raw message
net/wireless/core.h +7 -0
@@ -103,6 +103,12 @@ struct cfg80211_registered_device {/* lock for all wdev lists */ spinlock_t mgmt_registrations_lock; +struct work_struct wiphy_work; +struct list_head wiphy_work_list; +/* protects the list above */ +spinlock_t wiphy_work_lock; +bool suspended; +/* must be last because of the way we do wiphy_priv(), * and it should at least be aligned to NETDEV_ALIGN */ struct wiphy wiphy__aligned(NETDEV_ALIGN) ;
@@ -457,6 +463,7 @@ int cfg80211_change_iface(struct cfg8021 struct net_device *dev, enum nl80211_iftype ntype, struct vif_params *params);void cfg80211_process_rdev_events (struct cfg80211_registered_device *rdev); +void cfg80211_process_wiphy_works (struct cfg80211_registered_device *rdev);void cfg80211_process_wdev_events (struct wireless_dev *wdev); bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
net/wireless/sysfs.c +7 -1
@@ -5,7 +5,7 @@* * Copyright 2005-2006 Jiri Benc <[email protected]> * Copyright 2006 Johannes Berg <[email protected]> -* Copyright (C) 2020-2021 Intel Corporation +* Copyright (C) 2020-2021, 2023 Intel Corporation */ #include <linux/device.h>
@@ -105,14 +105,18 @@ static int wiphy_suspend(struct device *cfg80211_leave_all (rdev);cfg80211_process_rdev_events (rdev); } +cfg80211_process_wiphy_works (rdev);if (rdev->ops->suspend) ret =rdev_suspend (rdev, rdev->wiphy.wowlan_config);if (ret ==1 ) {/* Driver refuse to configure wowlan */ cfg80211_leave_all (rdev);cfg80211_process_rdev_events (rdev); +cfg80211_process_wiphy_works (rdev); ret =rdev_suspend (rdev,NULL ); } +if (ret ==0 ) + rdev->suspended = true; }wiphy_unlock (&rdev->wiphy);rtnl_unlock ();
@@ -132,6 +136,8 @@ static int wiphy_resume(struct device *dwiphy_lock (&rdev->wiphy);if (rdev->wiphy.registered && rdev->ops->resume) ret =rdev_resume (rdev); + rdev->suspended = false; +schedule_work (&rdev->wiphy_work);wiphy_unlock (&rdev->wiphy);if (ret)
Greg Kroah-Hartman
maintainerPATCH 186/206 wifi: mac80211: use wiphy work for sdata->work
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 16114496d684a3df4ce09f7c6b7557a8b2922795 ]
We'll need this later to convert other works that might be cancelled from here, so convert this one first.
--- net/mac80211/ibss.c | 8 ++++---- net/mac80211/ieee80211_i.h | 2 +- net/mac80211/iface.c | 10 +++++----- net/mac80211/mesh.c | 10 +++++----- net/mac80211/mesh_hwmp.c | 6 +++--- net/mac80211/mlme.c | 6 +++--- net/mac80211/ocb.c | 6 +++--- net/mac80211/rx.c | 2 +- net/mac80211/scan.c | 2 +- net/mac80211/status.c | 5 +++-- net/mac80211/util.c | 2 +- 11 files changed, 30 insertions(+), 29 deletions(-)
net/mac80211/ibss.c +4 -4
@@ -746,7 +746,7 @@ static void ieee80211_csa_connection_droskb_queue_purge (&sdata->skb_queue);/* trigger a scan to find another IBSS network to join */ -ieee80211_queue_work (&sdata->local->hw, &sdata->work); +wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work);sdata_unlock (sdata); }
@@ -1245,7 +1245,7 @@ void ieee80211_ibss_rx_no_sta(struct ieespin_lock (&ifibss->incomplete_lock);list_add (&sta->list, &ifibss->incomplete_stations);spin_unlock (&ifibss->incomplete_lock); -ieee80211_queue_work (&local->hw, &sdata->work); +wiphy_work_queue (local->hw.wiphy, &sdata->work); }static void ieee80211_ibss_sta_expire (struct ieee80211_sub_if_data *sdata)
@@ -1726,7 +1726,7 @@ static void ieee80211_ibss_timer(structstruct ieee80211_sub_if_data *sdata =from_timer (sdata, t, u.ibss.timer); -ieee80211_queue_work (&sdata->local->hw, &sdata->work); +wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work); }void ieee80211_ibss_setup_sdata (struct ieee80211_sub_if_data *sdata)
@@ -1861,7 +1861,7 @@ int ieee80211_ibss_join(struct ieee80211 sdata->needed_rx_chains = local->rx_chains; sdata->control_port_over_nl80211 = params->control_port_over_nl80211; -ieee80211_queue_work (&local->hw, &sdata->work); +wiphy_work_queue (local->hw.wiphy, &sdata->work);return 0 ; }
net/mac80211/ieee80211_i.h +1 -1
@@ -966,7 +966,7 @@ struct ieee80211_sub_if_data {/* used to reconfigure hardware SM PS */ struct work_struct recalc_smps; -struct work_struct work; +struct wiphy_work work;struct sk_buff_head skb_queue;struct sk_buff_head status_queue;
net/mac80211/iface.c +5 -5
@@ -43,7 +43,7 @@* by either the RTNL, the iflist_mtx or RCU. */ -static void ieee80211_iface_work (struct work_struct *work); +static void ieee80211_iface_work (struct wiphy *wiphy,struct wiphy_work *work);bool __ieee80211_recalc_txpower (struct ieee80211_sub_if_data *sdata) {
@@ -539,7 +539,7 @@ static void ieee80211_do_stop(struct ieeRCU_INIT_POINTER (local->p2p_sdata,NULL ); fallthrough;default : -cancel_work_sync (&sdata->work); +wiphy_work_cancel (sdata->local->hw.wiphy, &sdata->work);/* * When we get here, the interface is marked down. * Free the remaining keys, if there are any
@@ -1005,7 +1005,7 @@ int ieee80211_add_virtual_monitor(structskb_queue_head_init (&sdata->skb_queue);skb_queue_head_init (&sdata->status_queue); -INIT_WORK (&sdata->work, ieee80211_iface_work); +wiphy_work_init (&sdata->work, ieee80211_iface_work);return 0 ; }
@@ -1487,7 +1487,7 @@ static void ieee80211_iface_process_stat } } -static void ieee80211_iface_work (struct work_struct *work) +static void ieee80211_iface_work (struct wiphy *wiphy,struct wiphy_work *work) {struct ieee80211_sub_if_data *sdata = container_of(work, struct ieee80211_sub_if_data, work);
@@ -1590,7 +1590,7 @@ static void ieee80211_setup_sdata(structskb_queue_head_init (&sdata->skb_queue);skb_queue_head_init (&sdata->status_queue); -INIT_WORK (&sdata->work, ieee80211_iface_work); +wiphy_work_init (&sdata->work, ieee80211_iface_work);INIT_WORK (&sdata->recalc_smps, ieee80211_recalc_smps_work);INIT_WORK (&sdata->csa_finalize_work, ieee80211_csa_finalize_work);INIT_WORK (&sdata->color_change_finalize_work, ieee80211_color_change_finalize_work);
net/mac80211/mesh.c +5 -5
@@ -44,7 +44,7 @@ static void ieee80211_mesh_housekeeping_set_bit (MESH_WORK_HOUSEKEEPING , &ifmsh->wrkq_flags); -ieee80211_queue_work (&local->hw, &sdata->work); +wiphy_work_queue (local->hw.wiphy, &sdata->work); }/**
@@ -642,7 +642,7 @@ static void ieee80211_mesh_path_timer(ststruct ieee80211_sub_if_data *sdata =from_timer (sdata, t, u.mesh.mesh_path_timer); -ieee80211_queue_work (&sdata->local->hw, &sdata->work); +wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work); }static void ieee80211_mesh_path_root_timer (struct timer_list *t)
@@ -653,7 +653,7 @@ static void ieee80211_mesh_path_root_timset_bit (MESH_WORK_ROOT , &ifmsh->wrkq_flags); -ieee80211_queue_work (&sdata->local->hw, &sdata->work); +wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work); }void ieee80211_mesh_root_setup (struct ieee80211_if_mesh *ifmsh)
@@ -1018,7 +1018,7 @@ void ieee80211_mbss_info_change_notify(sfor_each_set_bit (bit, &bits,sizeof (changed) *BITS_PER_BYTE )set_bit (bit, &ifmsh->mbss_changed);set_bit (MESH_WORK_MBSS_CHANGED , &ifmsh->wrkq_flags); -ieee80211_queue_work (&sdata->local->hw, &sdata->work); +wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work); }int ieee80211_start_mesh (struct ieee80211_sub_if_data *sdata)
@@ -1043,7 +1043,7 @@ int ieee80211_start_mesh(struct ieee8021 ifmsh->sync_offset_clockdrift_max =0 ;set_bit (MESH_WORK_HOUSEKEEPING , &ifmsh->wrkq_flags);ieee80211_mesh_root_setup (ifmsh); -ieee80211_queue_work (&local->hw, &sdata->work); +wiphy_work_queue (local->hw.wiphy, &sdata->work); sdata->vif.bss_conf.ht_operation_mode = ifmsh->mshcfg.ht_opmode; sdata->vif.bss_conf.enable_beacon = true;
net/mac80211/mesh_hwmp.c +3 -3
@@ -1,7 +1,7 @@// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2008, 2009 open80211s Ltd. -* Copyright (C) 2019, 2021 Intel Corporation +* Copyright (C) 2019, 2021-2023 Intel Corporation * Author: Luis Carlos Cobo <[email protected]> */
@@ -1020,14 +1020,14 @@ static void mesh_queue_preq(struct mesh_spin_unlock_bh (&ifmsh->mesh_preq_queue_lock);if (time_after (jiffies, ifmsh->last_preq +min_preq_int_jiff (sdata))) -ieee80211_queue_work (&sdata->local->hw, &sdata->work); +wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work);else if (time_before (jiffies, ifmsh->last_preq)) {/* avoid long wait if did not send preqs for a long time * and jiffies wrapped around */ ifmsh->last_preq = jiffies -min_preq_int_jiff (sdata) -1 ; -ieee80211_queue_work (&sdata->local->hw, &sdata->work); +wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work); }else mod_timer (&ifmsh->mesh_path_timer, ifmsh->last_preq +min_preq_int_jiff (sdata));
net/mac80211/mlme.c +3 -3
@@ -2509,7 +2509,7 @@ void ieee80211_sta_tx_notify(struct ieee sdata->u.mgd.probe_send_count =0 ; else sdata->u.mgd.nullfunc_failed = true; -ieee80211_queue_work (&sdata->local->hw, &sdata->work); +wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work); } static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata,
@@ -4415,7 +4415,7 @@ static void ieee80211_sta_timer(struct tstruct ieee80211_sub_if_data *sdata =from_timer (sdata, t, u.mgd.timer); -ieee80211_queue_work (&sdata->local->hw, &sdata->work); +wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work); } void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
@@ -4559,7 +4559,7 @@ void ieee80211_mgd_conn_tx_status(struct sdata->u.mgd.status_acked = acked; sdata->u.mgd.status_received = true; -ieee80211_queue_work (&local->hw, &sdata->work); +wiphy_work_queue (local->hw.wiphy, &sdata->work); }void ieee80211_sta_work (struct ieee80211_sub_if_data *sdata)
net/mac80211/ocb.c +3 -3
@@ -80,7 +80,7 @@ void ieee80211_ocb_rx_no_sta(struct ieeespin_lock (&ifocb->incomplete_lock);list_add (&sta->list, &ifocb->incomplete_stations);spin_unlock (&ifocb->incomplete_lock); -ieee80211_queue_work (&local->hw, &sdata->work); +wiphy_work_queue (local->hw.wiphy, &sdata->work); }static struct sta_info *ieee80211_ocb_finish_sta (struct sta_info *sta)
@@ -156,7 +156,7 @@ static void ieee80211_ocb_housekeeping_tset_bit (OCB_WORK_HOUSEKEEPING , &ifocb->wrkq_flags); -ieee80211_queue_work (&local->hw, &sdata->work); +wiphy_work_queue (local->hw.wiphy, &sdata->work); }void ieee80211_ocb_setup_sdata (struct ieee80211_sub_if_data *sdata)
@@ -196,7 +196,7 @@ int ieee80211_ocb_join(struct ieee80211_ ifocb->joined = true;set_bit (OCB_WORK_HOUSEKEEPING , &ifocb->wrkq_flags); -ieee80211_queue_work (&local->hw, &sdata->work); +wiphy_work_queue (local->hw.wiphy, &sdata->work);netif_carrier_on (sdata->dev);return 0 ;
net/mac80211/rx.c +1 -1
@@ -219,7 +219,7 @@ static void __ieee80211_queue_skb_to_ifa struct sk_buff *skb) {skb_queue_tail (&sdata->skb_queue, skb); -ieee80211_queue_work (&sdata->local->hw, &sdata->work); +wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work);if (sta) sta->rx_stats.packets++; }
net/mac80211/scan.c +1 -1
@@ -498,7 +498,7 @@ static void __ieee80211_scan_completed(s*/ list_for_each_entry_rcu (sdata, &local->interfaces, list) {if (ieee80211_sdata_running (sdata)) -ieee80211_queue_work (&sdata->local->hw, &sdata->work); +wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work); }if (was_scanning)
net/mac80211/status.c +3 -2
@@ -5,6 +5,7 @@* Copyright 2006-2007 Jiri Benc <[email protected]> * Copyright 2008-2010 Johannes Berg <[email protected]> * Copyright 2013-2014 Intel Mobile Communications GmbH +* Copyright 2021-2023 Intel Corporation */ #include <linux/export.h>
@@ -716,8 +717,8 @@ static void ieee80211_report_used_skb(stif (qskb) {skb_queue_tail (&sdata->status_queue, qskb); -ieee80211_queue_work (&local->hw, - &sdata->work); +wiphy_work_queue (local->hw.wiphy, + &sdata->work); } } }else {
net/mac80211/util.c +1 -1
@@ -2679,7 +2679,7 @@ int ieee80211_reconfig(struct ieee80211_/* Requeue all works */ list_for_each_entry (sdata, &local->interfaces, list) -ieee80211_queue_work (&local->hw, &sdata->work); +wiphy_work_queue (local->hw.wiphy, &sdata->work); } ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
Greg Kroah-Hartman
maintainerPATCH 187/206 wifi: mac80211: move TDLS work to wiphy work
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 777b26002b73127e81643d9286fadf3d41e0e477 ]
Again, to have the wiphy locked for it.
[ Summary of conflict resolutions:
- In mlme.c, move only tdls_peer_del_work
to wiphy work, and none the other works ]
--- net/mac80211/ieee80211_i.h | 4 ++-- net/mac80211/mlme.c | 7 ++++--- net/mac80211/tdls.c | 11 ++++++----- 3 files changed, 12 insertions(+), 10 deletions(-)
net/mac80211/ieee80211_i.h +2 -2
@@ -542,7 +542,7 @@ struct ieee80211_if_managed {/* TDLS support */ u8 tdls_peer[ETH_ALEN ]__aligned(2) ; -struct delayed_work tdls_peer_del_work; +struct wiphy_delayed_work tdls_peer_del_work;struct sk_buff *orig_teardown_skb;/* The original teardown skb */ struct sk_buff *teardown_skb;/* A copy to send through the AP */ spinlock_t teardown_lock;/* To lock changing teardown_skb */
@@ -2494,7 +2494,7 @@ int ieee80211_tdls_mgmt(struct wiphy *wi size_t extra_ies_len);int ieee80211_tdls_oper (struct wiphy *wiphy,struct net_device *dev,const u8 *peer,enum nl80211_tdls_operation oper); -void ieee80211_tdls_peer_del_work (struct work_struct *wk); +void ieee80211_tdls_peer_del_work (struct wiphy *wiphy,struct wiphy_work *wk);int ieee80211_tdls_channel_switch (struct wiphy *wiphy,struct net_device *dev,const u8 *addr,u8 oper_class,struct cfg80211_chan_def *chandef);
net/mac80211/mlme.c +4 -3
@@ -4890,8 +4890,8 @@ void ieee80211_sta_setup_sdata(struct ieINIT_WORK (&ifmgd->csa_connection_drop_work, ieee80211_csa_connection_drop_work);INIT_WORK (&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work); -INIT_DELAYED_WORK (&ifmgd->tdls_peer_del_work, - ieee80211_tdls_peer_del_work); +wiphy_delayed_work_init (&ifmgd->tdls_peer_del_work, + ieee80211_tdls_peer_del_work);timer_setup (&ifmgd->timer, ieee80211_sta_timer,0 );timer_setup (&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,0 );timer_setup (&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer,0 );
@@ -6010,7 +6010,8 @@ void ieee80211_mgd_stop(struct ieee80211cancel_work_sync (&ifmgd->request_smps_work);cancel_work_sync (&ifmgd->csa_connection_drop_work);cancel_work_sync (&ifmgd->chswitch_work); -cancel_delayed_work_sync (&ifmgd->tdls_peer_del_work); +wiphy_delayed_work_cancel (sdata->local->hw.wiphy, + &ifmgd->tdls_peer_del_work);sdata_lock (sdata);if (ifmgd->assoc_data) {
net/mac80211/tdls.c +6 -5
@@ -21,7 +21,7 @@/* give usermode some time for retries in setting up the TDLS session */ #define TDLS_PEER_SETUP_TIMEOUT (15 * HZ) -void ieee80211_tdls_peer_del_work (struct work_struct *wk) +void ieee80211_tdls_peer_del_work (struct wiphy *wiphy,struct wiphy_work *wk) {struct ieee80211_sub_if_data *sdata;struct ieee80211_local *local;
@@ -1126,9 +1126,9 @@ ieee80211_tdls_mgmt_setup(struct wiphy *return ret; } -ieee80211_queue_delayed_work (&sdata->local->hw, - &sdata->u.mgd.tdls_peer_del_work, -TDLS_PEER_SETUP_TIMEOUT ); +wiphy_delayed_work_queue (sdata->local->hw.wiphy, + &sdata->u.mgd.tdls_peer_del_work, +TDLS_PEER_SETUP_TIMEOUT );return 0 ; out_unlock:
@@ -1425,7 +1425,8 @@ int ieee80211_tdls_oper(struct wiphy *wi }if (ret ==0 &ðer_addr_equal (sdata->u.mgd.tdls_peer, peer)) { -cancel_delayed_work (&sdata->u.mgd.tdls_peer_del_work); +wiphy_delayed_work_cancel (sdata->local->hw.wiphy, + &sdata->u.mgd.tdls_peer_del_work);eth_zero_addr (sdata->u.mgd.tdls_peer); }
Greg Kroah-Hartman
maintainerPATCH 188/206 HID: uclogic: Correct devm device reference for hidinput input_dev name
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rahul Rameshbabu <[email protected]>
[ Upstream commit dd613a4e45f8d35f49a63a2064e5308fa5619e29 ]
Reference the HID device rather than the input device for the devm allocation of the input_dev name. Referencing the input_dev would lead to a use-after-free when the input_dev was unregistered and subsequently fires a uevent that depends on the name. At the point of firing the uevent, the name would be freed by devres management.
Use devm_kasprintf to simplify the logic for allocating memory and formatting the input_dev name string.
--- drivers/hid/hid-uclogic-core.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-)
drivers/hid/hid-uclogic-core.c +3 -10
@@ -104,10 +104,8 @@ static int uclogic_input_configured(stru {struct uclogic_drvdata *drvdata =hid_get_drvdata (hdev);struct uclogic_params *params = &drvdata->params; -char *name;const char *suffix =NULL ;struct hid_field *field; -size_t len;/* no report associated (HID_QUIRK_MULTI_INPUT not set) */ if (!hi->report)
@@ -145,14 +143,9 @@ static int uclogic_input_configured(strubreak ; } -if (suffix) { - len =strlen (hdev->name) +2 +strlen (suffix); - name =devm_kzalloc (&hi->input->dev, len,GFP_KERNEL ); -if (name) { -snprintf (name, len,"%s %s" , hdev->name, suffix); - hi->input->name = name; - } - } +if (suffix) + hi->input->name =devm_kasprintf (&hdev->dev,GFP_KERNEL , +"%s %s" , hdev->name, suffix);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 189/206 HID: uclogic: Add NULL check in uclogic_input_configured()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Henry Martin <[email protected]>
[ Upstream commit bd07f751208ba190f9b0db5e5b7f35d5bb4a8a1e ]
devm_kasprintf() returns NULL when memory allocation fails. Currently, uclogic_input_configured() does not check for this case, which results in a NULL pointer dereference.
Add NULL check after devm_kasprintf() to prevent this issue.
--- drivers/hid/hid-uclogic-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/hid/hid-uclogic-core.c +4 -1
@@ -143,9 +143,12 @@ static int uclogic_input_configured(strubreak ; } -if (suffix) +if (suffix) { hi->input->name =devm_kasprintf (&hdev->dev,GFP_KERNEL ,"%s %s" , hdev->name, suffix); +if (!hi->input->name) +return -ENOMEM ; + }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 190/206 genirq/irq_sim: Initialize work context pointers properly
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gyeyoung Baek <[email protected]>
[ Upstream commit 8a2277a3c9e4cc5398f80821afe7ecbe9bdf2819 ]
Initialize ops member's pointers properly by using kzalloc() instead of kmalloc() when allocating the simulation work context. Otherwise the pointers contain random content leading to invalid dereferencing.
[ The context change is due to the commit 011f583781fa ("genirq/irq_sim: add an extended irq_sim initializer") which is irrelevant to the logic of this patch. ]
--- kernel/irq/irq_sim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/irq/irq_sim.c +1 -1
@@ -166,7 +166,7 @@ struct irq_domain *irq_domain_create_sim {struct irq_sim_work_ctx *work_ctx; - work_ctx =kmalloc (sizeof (*work_ctx),GFP_KERNEL ); + work_ctx =kzalloc (sizeof (*work_ctx),GFP_KERNEL );if (!work_ctx) goto err_out;
Greg Kroah-Hartman
maintainerPATCH 191/206 can: esd_usb: esd_usb_read_bulk_callback(): fix URB memory leak
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marc Kleine-Budde <[email protected]>
commit 5a4391bdc6c8357242f62f22069c865b792406b3 upstream.
Fix similar memory leak as in commit 7352e1d5932a ("can: gs_usb:gs_usb_receive_bulk_callback(): fix URB memory leak").
In esd_usb_open(), the URBs for USB-in transfers are allocated, added to the dev->rx_submitted anchor and submitted. In the complete callback esd_usb_read_bulk_callback(), the URBs are processed and resubmitted. In esd_usb_close() the URBs are freed by calling usb_kill_anchored_urbs(&dev->rx_submitted).
However, this does not take into account that the USB framework unanchors the URB before the complete function is called. This means that once an in-URB has been completed, it is no longer anchored and is ultimately not released in esd_usb_close().
Fix the memory leak by anchoring the URB in the esd_usb_read_bulk_callback() to the dev->rx_submitted anchor.
--- drivers/net/can/usb/esd_usb2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/net/can/usb/esd_usb2.c +8 -1
@@ -440,13 +440,20 @@ resubmit_urb: urb->transfer_buffer,RX_BUFFER_SIZE , esd_usb2_read_bulk_callback, dev); +usb_anchor_urb (urb, &dev->rx_submitted); + retval =usb_submit_urb (urb,GFP_ATOMIC ); +if (!retval) +return ; + +usb_unanchor_urb (urb); +if (retval == -ENODEV ) {for (i =0 ; i < dev->net_count; i++) {if (dev->nets[i])netif_device_detach (dev->nets[i]->netdev); } - }else if (retval) { + }else {dev_err (dev->udev->dev.parent,"failed resubmitting read bulk urb: %d\n" , retval); }
Greg Kroah-Hartman
maintainerPATCH 192/206 drm/amdkfd: fix a memory leak in device_queue_manager_init()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit 80614c509810fc051312d1a7ccac8d0012d6b8d0 upstream.
If dqm->ops.initialize() fails, add deallocate_hiq_sdma_mqd() to release the memory allocated by allocate_hiq_sdma_mqd(). Move deallocate_hiq_sdma_mqd() up to ensure proper function visibility at the point of use.
--- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +10 -8
@@ -1847,6 +1847,14 @@ static int allocate_hiq_sdma_mqd(structreturn retval; } +static void deallocate_hiq_sdma_mqd (struct kfd_dev *dev, +struct kfd_mem_obj *mqd) +{ +WARN (!mqd,"No hiq sdma mqd trunk to free" ); + +amdgpu_amdkfd_free_gtt_mem (dev->kgd, &mqd->gtt_mem); +} +struct device_queue_manager *device_queue_manager_init (struct kfd_dev *dev) {struct device_queue_manager *dqm;
@@ -1980,19 +1988,13 @@ struct device_queue_manager *device_queuif (!dqm->ops.initialize (dqm))return dqm; +deallocate_hiq_sdma_mqd (dev, &dqm->hiq_sdma_mqd); + out_free:kfree (dqm);return NULL ; } -static void deallocate_hiq_sdma_mqd (struct kfd_dev *dev, -struct kfd_mem_obj *mqd) -{ -WARN (!mqd,"No hiq sdma mqd trunk to free" ); - -amdgpu_amdkfd_free_gtt_mem (dev->kgd, mqd->gtt_mem); -} -void device_queue_manager_uninit (struct device_queue_manager *dqm) { dqm->ops.uninitialize (dqm);
Greg Kroah-Hartman
maintainerPATCH 193/206 btrfs: prevent use-after-free on page private data in btrfs_subpage_clear_uptodate()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: JP Kobryn <[email protected]>
This is a stable-only patch. The issue was inadvertently fixed in 6.17 [0] as part of a refactoring, but this patch serves as a minimal targeted fix for prior kernels.
Users of find_lock_page() need to guard against the situation where releasepage() has been invoked during reclaim but the page was ultimately not removed from the page cache. This patch covers one location that was overlooked.
After acquiring the page, use set_page_extent_mapped() to ensure the page private state is valid. This is especially important in the subpage case, where the private field is an allocated struct containing bitmap and lock data.
Without this protection, the race below is possible:
[mm] page cache reclaim path [fs] relocation in subpage modeshrink_page_list()
trylock_page() /* lock acquired */
try_to_release_page()
mapping->a_ops->releasepage()
btrfs_releasepage()
__btrfs_releasepage()
clear_page_extent_mapped()
btrfs_detach_subpage()
subpage = detach_page_private(page) btrfs_free_subpage(subpage)
kfree(subpage) /* point A */
prealloc_file_extent_cluster()
find_lock_page()
page_cache_get_speculative() lock_page() /* wait for lock */
if (...)
...
else if (!mapping || !__remove_mapping(..))
/*
* __remove_mapping() returns zero when
* page_ref_freeze(page, refcount) fails /* point B */ */
goto keep_locked /* page remains in cache */keep_locked:
unlock_page(page) /* lock released */
/* lock acquired */
btrfs_subpage_clear_uptodate()
/* use-after-free */
subpage = page->private[0] 4e346baee95f ("btrfs: reloc: unconditionally invalidate the page cache for each cluster")
--- fs/btrfs/relocation.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
fs/btrfs/relocation.c +13 -0
@@ -2900,6 +2900,19 @@ static noinline_for_stack int prealloc_f* will re-read the whole page anyway. */ if (page) { +/* +* releasepage() could have cleared the page private data while +* we were not holding the lock. Reset the mapping if needed so +* subpage operations can access a valid private page state. +*/ + ret =set_page_extent_mapped (page); +if (ret) { +unlock_page (page); +put_page (page); + +return ret; + } +btrfs_subpage_clear_uptodate (fs_info, page, i_size,round_up (i_size,PAGE_SIZE ) - i_size);unlock_page (page);
Greg Kroah-Hartman
maintainerPATCH 194/206 net/sched: act_ife: convert comma to semicolon
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Ni <[email protected]>
commit 205305c028ad986d0649b8b100bab6032dcd1bb5 upstream.
Replace comma between expressions with semicolons.
Using a ',' in place of a ';' can have unintended side effects. Although that is not the case here, it is seems best to use ';' unless ',' is intended.
Found by inspection.
No functional change intended.
Compile tested only.
--- net/sched/act_ife.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/sched/act_ife.c +3 -3
@@ -648,9 +648,9 @@ static int tcf_ife_dump(struct sk_buff *memset (&opt,0 ,sizeof (opt)); - opt.index = ife->tcf_index, - opt.refcnt =refcount_read (&ife->tcf_refcnt) - ref, - opt.bindcnt =atomic_read (&ife->tcf_bindcnt) - bind, + opt.index = ife->tcf_index; + opt.refcnt =refcount_read (&ife->tcf_refcnt) - ref; + opt.bindcnt =atomic_read (&ife->tcf_bindcnt) - bind;spin_lock_bh (&ife->tcf_lock); opt.action = ife->tcf_action;
Greg Kroah-Hartman
maintainerPATCH 195/206 mm/kfence: randomize the freelist on initialization
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pimyn Girgis <[email protected]>
commit 870ff19251bf3910dda7a7245da826924045fedd upstream.
Randomize the KFENCE freelist during pool initialization to make allocation patterns less predictable. This is achieved by shuffling the order in which metadata objects are added to the freelist using get_random_u32_below().
Additionally, ensure the error path correctly calculates the address range to be reset if initialization fails, as the address increment logic has been moved to a separate loop.
--- mm/kfence/core.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)
mm/kfence/core.c +20 -4
@@ -520,7 +520,7 @@ static bool __init kfence_init_pool(void {unsigned long addr = (unsigned long )__kfence_pool;struct page *pages; -int i; +int i, rand;char *p;if (!__kfence_pool)
@@ -576,13 +576,28 @@ static bool __init kfence_init_pool(voidINIT_LIST_HEAD (&meta->list);raw_spin_lock_init (&meta->lock); meta->state =KFENCE_OBJECT_UNUSED ; - meta->addr = addr;/* Initialize for validation in metadata_to_pageaddr(). */ -list_add_tail (&meta->list, &kfence_freelist); +/* Use addr to randomize the freelist. */ + meta->addr = i;/* Protect the right redzone. */ -if (unlikely (!kfence_protect (addr +PAGE_SIZE ))) +if (unlikely (!kfence_protect (addr +2 * i *PAGE_SIZE +PAGE_SIZE ))) goto err; + } + +for (i =CONFIG_KFENCE_NUM_OBJECTS ; i >0 ; i--) { + rand =get_random_u32 () % i; +swap (kfence_metadata[i -1 ].addr, kfence_metadata[rand].addr); + } + +for (i =0 ; i <CONFIG_KFENCE_NUM_OBJECTS ; i++) { +struct kfence_metadata *meta_1 = &kfence_metadata[i]; +struct kfence_metadata *meta_2 = &kfence_metadata[meta_1->addr]; + +list_add_tail (&meta_2->list, &kfence_freelist); + } +for (i =0 ; i <CONFIG_KFENCE_NUM_OBJECTS ; i++) { + kfence_metadata[i].addr = addr; addr +=2 *PAGE_SIZE ; }
@@ -597,6 +612,7 @@ static bool __init kfence_init_pool(voidreturn true; err: + addr +=2 * i *PAGE_SIZE ;/* * Only release unprotected pages, and do not try to go back and change * page attributes due to risk of failing to do so as well. If changing
Re: [PATCH 5.15 195/206] mm/kfence: randomize the freelist on initialization
Quoted 80 lines · Greg Kroah-Hartman
5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pimyn Girgis <[email protected]>
commit
870ff19251bf3910dda7a7245da826924045feddupstream.Randomize the KFENCE freelist during pool initialization to make allocation patterns less predictable. This is achieved by shuffling the order in which metadata objects are added to the freelist using
get_random_u32_below().Additionally, ensure the error path correctly calculates the address range to be reset if initialization fails, as the address increment logic has been moved to a separate loop.
Fixes 0ce20dd84089 ("mm: add Kernel Electric-Fence infrastructure")Signed-off-by Pimyn Girgis <[email protected]>Reviewed-by Alexander Potapenko <[email protected]>Cc Dmitry Vyukov <[email protected]>Cc Marco Elver <[email protected]>Cc Ernesto Martnez Garca <[email protected]>Cc Greg KH <[email protected]>Cc Kees Cook <[email protected]>Cc <[email protected]>Signed-off-by Andrew Morton <[email protected]>Signed-off-by Pimyn Girgis <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- mm/kfence/core.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)mm/kfence/core.c +19
-4@@ -520,7 +520,7 @@ static bool __init kfence_init_pool(void {unsigned long addr = (unsigned long )__kfence_pool;struct page *pages; -int i; +int i, rand;char *p;if (!__kfence_pool)@@ -576,13 +576,28 @@ static bool __init kfence_init_pool(voidINIT_LIST_HEAD (&meta->list);raw_spin_lock_init (&meta->lock); meta->state =KFENCE_OBJECT_UNUSED ; - meta->addr = addr;/* Initialize for validation in metadata_to_pageaddr(). */ -list_add_tail (&meta->list, &kfence_freelist); +/* Use addr to randomize the freelist. */ + meta->addr = i;/* Protect the right redzone. */ -if (unlikely (!kfence_protect (addr +PAGE_SIZE ))) +if (unlikely (!kfence_protect (addr +2 * i *PAGE_SIZE +PAGE_SIZE ))) goto err; + } + +for (i =CONFIG_KFENCE_NUM_OBJECTS ; i >0 ; i--) { + rand =get_random_u32 () % i; +swap (kfence_metadata[i -1 ].addr, kfence_metadata[rand].addr); + } + +for (i =0 ; i <CONFIG_KFENCE_NUM_OBJECTS ; i++) { +struct kfence_metadata *meta_1 = &kfence_metadata[i]; +struct kfence_metadata *meta_2 = &kfence_metadata[meta_1->addr]; + +list_add_tail (&meta_2->list, &kfence_freelist); + } +for (i =0 ; i <CONFIG_KFENCE_NUM_OBJECTS ; i++) { + kfence_metadata[i].addr = addr; addr +=2 *PAGE_SIZE ; }
mm/kfence/core.c static bool __init kfence_init_pool(void · line 618
Quoted 7 lines
mm/kfence/core.c +1
-0@@ -597,6 +612,7 @@ static bool __init kfence_init_pool(voidreturn true; err: + addr +=2 * i *PAGE_SIZE ;/* * Only release unprotected pages, and do not try to go back and change * page attributes due to risk of failing to do so as well. If changing
This introduces a new instance of -Wsometimes-uninitialized, as pointed out by this KernelCI report:
https://lore.kernel.org/177022794292.7001.3716577555750776270@22d5995788c3/
mm/kfence/core.c:529:6: error: variable 'i' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized]
529 | if (!arch_kfence_init_pool())
| ^~~~~~~~~~~~~~~~~~~~~~~~
mm/kfence/core.c:615:14: note: uninitialized use occurs here
615 | addr += 2 * i * PAGE_SIZE;
| ^
mm/kfence/core.c:529:2: note: remove the 'if' if its condition is always false
529 | if (!arch_kfence_init_pool())
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
530 | goto err;
| ~~~~~~~~
mm/kfence/core.c:523:7: note: initialize the variable 'i' to silence this warning
523 | int i, rand;
| ^
| = 0Cheers,
Nathan
Re: [PATCH 5.15 195/206] mm/kfence: randomize the freelist on initialization
Quoted 4 lines · Nathan Chancellor
This introduces a new instance of -Wsometimes-uninitialized, as pointed out by this KernelCI report:
https://lore.kernel.org/177022794292.7001.3716577555750776270@22d5995788c3/
Thanks! I'll be sending a V2 shortly.
Greg Kroah-Hartman
maintainerRe: [PATCH 5.15 195/206] mm/kfence: randomize the freelist on initialization
Quoted 8 lines · Pimyn Girgis
Quoted 4 lines · Nathan Chancellor
This introduces a new instance of -Wsometimes-uninitialized, as pointed out by this KernelCI report:
https://lore.kernel.org/177022794292.7001.3716577555750776270@22d5995788c3/
Thanks! I'll be sending a V2 shortly.
Ok, will drop this one for now and wait for the new one for the next -rc cycle.
thanks,
greg k-h
Greg Kroah-Hartman
maintainerPATCH 196/206 pinctrl: lpass-lpi: implement .get_direction() for the GPIO driver
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
[ Upstream commit 4f0d22ec60cee420125f4055af76caa0f373a3fe ]
GPIO controller driver should typically implement the .get_direction() callback as GPIOLIB internals may try to use it to determine the state of a pin. Add it for the LPASS LPI driver.
--- drivers/pinctrl/qcom/pinctrl-lpass-lpi.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
drivers/pinctrl/qcom/pinctrl-lpass-lpi.c +17 -0
@@ -484,6 +484,22 @@ static const struct pinconf_ops lpi_gpio .pin_config_group_set = lpi_config_set, }; +static int lpi_gpio_get_direction (struct gpio_chip *chip,unsigned int pin) +{ +unsigned long config =pinconf_to_config_packed (PIN_CONFIG_OUTPUT ,0 ); +struct lpi_pinctrl *state =gpiochip_get_data (chip); +unsigned long arg; +int ret; + + ret =lpi_config_get (state->ctrl, pin, &config); +if (ret) +return ret; + + arg =pinconf_to_config_argument (config); + +return arg ?GPIO_LINE_DIRECTION_OUT :GPIO_LINE_DIRECTION_IN ; +} +static int lpi_gpio_direction_input (struct gpio_chip *chip,unsigned int pin) {struct lpi_pinctrl *state =gpiochip_get_data (chip);
@@ -582,6 +598,7 @@ static void lpi_gpio_dbg_show(struct seq#endif static const struct gpio_chip lpi_gpio_template = { + .get_direction = lpi_gpio_get_direction, .direction_input = lpi_gpio_direction_input, .direction_output = lpi_gpio_direction_output, .get = lpi_gpio_get,
Greg Kroah-Hartman
maintainerPATCH 197/206 drm/imx/tve: fix probe device leak
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit e535c23513c63f02f67e3e09e0787907029efeaf ]
Make sure to drop the reference taken to the DDC device during probe on probe failure (e.g. probe deferral) and on driver unbind.
--- drivers/gpu/drm/imx/imx-tve.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/gpu/drm/imx/imx-tve.c +13 -0
@@ -521,6 +521,13 @@ static const struct component_ops imx_tv .bind = imx_tve_bind, }; +static void imx_tve_put_device (void *_dev) +{ +struct device *dev = _dev; + +put_device (dev); +} +static int imx_tve_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;
@@ -543,6 +550,12 @@ static int imx_tve_probe(struct platformif (ddc_node) { tve->ddc =of_find_i2c_adapter_by_node (ddc_node);of_node_put (ddc_node); +if (tve->ddc) { + ret =devm_add_action_or_reset (dev, imx_tve_put_device, + &tve->ddc->dev); +if (ret) +return ret; + } } tve->mode =of_get_tve_mode (np);
Greg Kroah-Hartman
maintainerPATCH 198/206 writeback: fix 100% CPU usage when dirtytime_expire_interval is 0
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Laveesh Bansal <[email protected]>
[ Upstream commit 543467d6fe97e27e22a26e367fda972dbefebbff ]
When vm.dirtytime_expire_seconds is set to 0, wakeup_dirtytime_writeback() schedules delayed work with a delay of 0, causing immediate execution. The function then reschedules itself with 0 delay again, creating an infinite busy loop that causes 100% kworker CPU usage.
Fix by:
- Only scheduling delayed work in wakeup_dirtytime_writeback() when dirtytime_expire_interval is non-zero
- Cancelling the delayed work in dirtytime_interval_handler() when the interval is set to 0
- Adding a guard in start_dirtytime_writeback() for defensive coding
Tested by booting kernel in QEMU with virtme-ng:
- Before fix: kworker CPU spikes to ~73%
- After fix: CPU remains at normal levels
- Setting interval back to non-zero correctly resumes writeback
--- fs/fs-writeback.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
fs/fs-writeback.c +10 -4
@@ -2391,12 +2391,14 @@ static void wakeup_dirtytime_writeback(swb_wakeup (wb); }rcu_read_unlock (); -schedule_delayed_work (&dirtytime_work, dirtytime_expire_interval *HZ ); +if (dirtytime_expire_interval) +schedule_delayed_work (&dirtytime_work, dirtytime_expire_interval *HZ ); }static int __init start_dirtytime_writeback (void ) { -schedule_delayed_work (&dirtytime_work, dirtytime_expire_interval *HZ ); +if (dirtytime_expire_interval) +schedule_delayed_work (&dirtytime_work, dirtytime_expire_interval *HZ );return 0 ; }__initcall (start_dirtytime_writeback);
@@ -2407,8 +2409,12 @@ int dirtytime_interval_handler(struct ctint ret; ret =proc_dointvec_minmax (table, write, buffer, lenp, ppos); -if (ret ==0 && write) -mod_delayed_work (system_wq, &dirtytime_work,0 ); +if (ret ==0 && write) { +if (dirtytime_expire_interval) +mod_delayed_work (system_wq, &dirtytime_work,0 ); +else +cancel_delayed_work_sync (&dirtytime_work); + }return ret; }
Greg Kroah-Hartman
maintainerPATCH 199/206 mptcp: avoid dup SUB_CLOSED events after disconnect
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Matthieu Baerts (NGI0)" <[email protected]>
[ Upstream commit 280d654324e33f8e6e3641f76764694c7b64c5db ]
In case of subflow disconnect(), which can also happen with the first subflow in case of errors like timeout or reset, mptcp_subflow_ctx_reset will reset most fields from the mptcp_subflow_context structure, including close_event_done. Then, when another subflow is closed, yet another SUB_CLOSED event for the disconnected initial subflow is sent. Because of the previous reset, there are no source address and destination port.
A solution is then to also check the subflow's local id: it shouldn't be negative anyway.
Another solution would be not to reset subflow->close_event_done at disconnect time, but when reused. But then, probably the whole reset could be done when being reused. Let's not change this logic, similar to TCP with tcp_disconnect().
--- net/mptcp/protocol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/mptcp/protocol.c +2 -2
@@ -2398,8 +2398,8 @@ static void __mptcp_close_ssk(struct socvoid mptcp_close_ssk (struct sock *sk,struct sock *ssk,struct mptcp_subflow_context *subflow) { -/* The first subflow can already be closed and still in the list */ -if (subflow->close_event_done) +/* The first subflow can already be closed or disconnected */ +if (subflow->close_event_done ||READ_ONCE (subflow->local_id) <0 )return ; subflow->close_event_done = true;
Greg Kroah-Hartman
maintainerPATCH 200/206 pinctrl: meson: mark the GPIO controller as sleeping
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
[ Upstream commit 28f24068387169722b508bba6b5257cb68b86e74 ]
The GPIO controller is configured as non-sleeping but it uses generic pinctrl helpers which use a mutex for synchronization.
This can cause the following lockdep splat with shared GPIOs enabled on boards which have multiple devices using the same GPIO:
BUG: sleeping function called from invalid context at
kernel/locking/mutex.c:591in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 142, name:
kworker/u25:3preempt_count: 1, expected: 0
RCU nest depth: 0, expected: 0
INFO: lockdep is turned off.
irq event stamp: 46379 hardirqs last enabled at (46379): [<ffff8000813acb24>] _raw_spin_unlock_irqrestore+0x74/0x78 hardirqs last disabled at (46378): [<ffff8000813abf38>] _raw_spin_lock_irqsave+0x84/0x88 softirqs last enabled at (46330): [<ffff8000800c71b4>] handle_softirqs+0x4c4/0x4dc softirqs last disabled at (46295): [<ffff800080010674>] __do_softirq+0x14/0x20 CPU: 1 UID: 0 PID: 142 Comm: kworker/u25:3 Tainted: G C 6.19.0-rc4-next-20260105+ #11963 PREEMPT Tainted: [C]=CRAP Hardware name: Khadas VIM3 (DT) Workqueue: events_unbound deferred_probe_work_func Call trace: show_stack+0x18/0x24 (C) dump_stack_lvl+0x90/0xd0 dump_stack+0x18/0x24 __might_resched+0x144/0x248 __might_sleep+0x48/0x98 __mutex_lock+0x5c/0x894 mutex_lock_nested+0x24/0x30 pinctrl_get_device_gpio_range+0x44/0x128 pinctrl_gpio_set_config+0x40/0xdc gpiochip_generic_config+0x28/0x3c gpio_do_set_config+0xa8/0x194 gpiod_set_config+0x34/0xfc gpio_shared_proxy_set_config+0x6c/0xfc [gpio_shared_proxy] gpio_do_set_config+0xa8/0x194 gpiod_set_transitory+0x4c/0xf0 gpiod_configure_flags+0xa4/0x480 gpiod_find_and_request+0x1a0/0x574 gpiod_get_index+0x58/0x84 devm_gpiod_get_index+0x20/0xb4 devm_gpiod_get+0x18/0x24 mmc_pwrseq_emmc_probe+0x40/0xb8 platform_probe+0x5c/0xac really_probe+0xbc/0x298 __driver_probe_device+0x78/0x12c driver_probe_device+0xdc/0x164 __device_attach_driver+0xb8/0x138 bus_for_each_drv+0x80/0xdc __device_attach+0xa8/0x1b0
--- drivers/pinctrl/meson/pinctrl-meson.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/meson/pinctrl-meson.c +1 -1
@@ -617,7 +617,7 @@ static int meson_gpiolib_register(struct pc->chip.set = meson_gpio_set; pc->chip.base =-1 ; pc->chip.ngpio = pc->data->num_pins; - pc->chip.can_sleep = false; + pc->chip.can_sleep = true; pc->chip.of_node = pc->of_node; pc->chip.of_gpio_n_cells =2 ;
Greg Kroah-Hartman
maintainerPATCH 201/206 team: Move team device type change at the end of team_port_add
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Nikola Z. Ivanov" <[email protected]>
[ Upstream commit 0ae9cfc454ea5ead5f3ddbdfe2e70270d8e2c8ef ]
Attempting to add a port device that is already up will expectedly fail, but not before modifying the team device header_ops.
In the case of the syzbot reproducer the gre0 device is already in state UP when it attempts to add it as a
port device of team0, this fails but before that header_ops->create of team0 is changed from eth_header to ipgre_header in the call to team_dev_type_check_change.
Later when we end up in ipgre_header() struct ip_tunnel* points to nonsense as the private data of the device still holds a struct team.
Example sequence of iproute2 commands to reproduce the hang/BUG():
ip link add dev team0 type team
ip link add dev gre0 type gre
ip link set dev gre0 up
ip link set dev gre0 master team0
ip link set dev team0 up
ping -I team0 1.1.1.1
Move team_dev_type_check_change down where all other checks have passed as it changes the dev type with no way to restore it in case one of the checks that follow it fail.
Also make sure to preserve the origial mtu assignment:
- If port_dev is not the same type as dev, dev takes mtu from port_dev
- If port_dev is the same type as dev, port_dev takes mtu from dev
This is done by adding a conditional before the call to dev_set_mtu to prevent it from assigning port_dev->mtu = dev->mtu and instead letting team_dev_type_check_change assign dev->mtu = port_dev->mtu. The conditional is needed because the patch moves the call to team_dev_type_check_change past dev_set_mtu.
Testing:
- team device driver in-tree selftests
- Add/remove various devices as slaves of team device
- syzbot
--- drivers/net/team/team.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
drivers/net/team/team.c +15 -8
@@ -1181,10 +1181,6 @@ static int team_port_add(struct team *tereturn -EPERM ; } - err =team_dev_type_check_change (dev, port_dev); -if (err) -return err; -if (port_dev->flags &IFF_UP ) {NL_SET_ERR_MSG (extack,"Device is up. Set it down before adding it as a team port" ); netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n",
@@ -1202,10 +1198,16 @@ static int team_port_add(struct team *teINIT_LIST_HEAD (&port->qom_list); port->orig.mtu = port_dev->mtu; - err =dev_set_mtu (port_dev, dev->mtu); -if (err) { -netdev_dbg (dev,"Error %d calling dev_set_mtu\n" , err); - goto err_set_mtu; +/* +* MTU assignment will be handled in team_dev_type_check_change +* if dev and port_dev are of different types +*/ +if (dev->type == port_dev->type) { + err =dev_set_mtu (port_dev, dev->mtu); +if (err) { +netdev_dbg (dev,"Error %d calling dev_set_mtu\n" , err); + goto err_set_mtu; + } }memcpy (port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len);
@@ -1280,6 +1282,10 @@ static int team_port_add(struct team *te } } + err =team_dev_type_check_change (dev, port_dev); +if (err) + goto err_set_dev_type; +if (dev->flags &IFF_UP ) {netif_addr_lock_bh (dev);dev_uc_sync_multiple (port_dev, dev);
@@ -1298,6 +1304,7 @@ static int team_port_add(struct team *tereturn 0 ; +err_set_dev_type: err_set_slave_promisc:__team_option_inst_del_port (team, port);
Greg Kroah-Hartman
maintainerPATCH 202/206 wifi: cfg80211: use system_unbound_wq for wiphy work
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
commit 91d20ab9d9ca035527af503d00e1e30d6c375f2a upstream.
Since wiphy work items can run pretty much arbitrary code in the stack/driver, it can take longer to run all of this, so we shouldn't be using system_wq via schedule_work(). Also, we lock the wiphy (which is the reason this exists), so use system_unbound_wq.
--- net/wireless/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/wireless/core.c +1 -1
@@ -1593,7 +1593,7 @@ void wiphy_work_queue(struct wiphy *wiphlist_add_tail (&work->entry, &rdev->wiphy_work_list);spin_unlock_irqrestore (&rdev->wiphy_work_lock, flags); -schedule_work (&rdev->wiphy_work); +queue_work (system_unbound_wq, &rdev->wiphy_work); }EXPORT_SYMBOL_GPL (wiphy_work_queue);
Greg Kroah-Hartman
maintainerPATCH 203/206 wifi: cfg80211: fix wiphy delayed work queueing
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
commit b743287d7a0007493f5cada34ed2085d475050b4 upstream.
When a wiphy work is queued with timer, and then again without a delay, it's started immediately but *also* started again after the timer expires. This can lead, for example, to warnings in mac80211's offchannel code as reported by Jouni. Running the same work twice isn't expected, of course. Fix this by deleting the timer at this point, when queuing immediately due to delay=0.
--- net/wireless/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/wireless/core.c +2 -1
@@ -5,7 +5,7 @@* Copyright 2006-2010 Johannes Berg <[email protected]> * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2015-2017 Intel Deutschland GmbH -* Copyright (C) 2018-2022 Intel Corporation +* Copyright (C) 2018-2024 Intel Corporation */ #define pr_fmt (fmt) KBUILD_MODNAME ": " fmt
@@ -1624,6 +1624,7 @@ void wiphy_delayed_work_queue(struct wip unsigned long delay) {if (!delay) { +del_timer (&dwork->timer);wiphy_work_queue (wiphy, &dwork->work);return ; }
Greg Kroah-Hartman
maintainerPATCH 204/206 wifi: cfg80211: cancel wiphy_work before freeing wiphy
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miri Korenblit <[email protected]>
commit 72d520476a2fab6f3489e8388ab524985d6c4b90 upstream.
A wiphy_work can be queued from the moment the wiphy is allocated and initialized (i.e. wiphy_new_nm). When a wiphy_work is queued, the rdev::wiphy_work is getting queued.
If wiphy_free is called before the rdev::wiphy_work had a chance to run, the wiphy memory will be freed, and then when it eventally gets to run it'll use invalid memory.
Fix this by canceling the work before freeing the wiphy.
--- net/wireless/core.c | 7 +++++++ 1 file changed, 7 insertions(+)
net/wireless/core.c +7 -0
@@ -1127,6 +1127,13 @@ void cfg80211_dev_free(struct cfg80211_r {struct cfg80211_internal_bss *scan, *tmp;struct cfg80211_beacon_registration *reg, *treg; +unsigned long flags; + +spin_lock_irqsave (&rdev->wiphy_work_lock, flags); +WARN_ON (!list_empty (&rdev->wiphy_work_list)); +spin_unlock_irqrestore (&rdev->wiphy_work_lock, flags); +cancel_work_sync (&rdev->wiphy_work); +rfkill_destroy (rdev->wiphy.rfkill);list_for_each_entry_safe (reg, treg, &rdev->beacon_registrations, list) {list_del (®->list);
Greg Kroah-Hartman
maintainerPATCH 205/206 wifi: cfg80211: fully move wiphy work to unbound workqueue
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
commit e296c95eac655008d5a709b8cf54d0018da1c916 upstream.
Previously I had moved the wiphy work to the unbound system workqueue, but missed that when it restarts and during resume it was still using the normal system workqueue. Fix that.
--- net/wireless/core.c | 2 +- net/wireless/sysfs.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
net/wireless/core.c +1 -1
@@ -427,7 +427,7 @@ static void cfg80211_wiphy_work(struct wif (wk) {list_del_init (&wk->entry);if (!list_empty (&rdev->wiphy_work_list)) -schedule_work (work); +queue_work (system_unbound_wq, work);spin_unlock_irq (&rdev->wiphy_work_lock); wk->func (&rdev->wiphy, wk);
net/wireless/sysfs.c +2 -2
@@ -5,7 +5,7 @@* * Copyright 2005-2006 Jiri Benc <[email protected]> * Copyright 2006 Johannes Berg <[email protected]> -* Copyright (C) 2020-2021, 2023 Intel Corporation +* Copyright (C) 2020-2021, 2023-2024 Intel Corporation */ #include <linux/device.h>
@@ -137,7 +137,7 @@ static int wiphy_resume(struct device *dif (rdev->wiphy.registered && rdev->ops->resume) ret =rdev_resume (rdev); rdev->suspended = false; -schedule_work (&rdev->wiphy_work); +queue_work (system_unbound_wq, &rdev->wiphy_work);wiphy_unlock (&rdev->wiphy);if (ret)
Greg Kroah-Hartman
maintainerPATCH 206/206 wifi: cfg80211: init wiphy_work before allocating rfkill fails
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis <[email protected]>
commit fc88dee89d7b63eeb17699393eb659aadf9d9b7c upstream.
syzbort reported a uninitialize wiphy_work_lock in cfg80211_dev_free. [1]
After rfkill allocation fails, the wiphy release process will be performed, which will cause cfg80211_dev_free to access the uninitialized wiphy_work related data.
Move the initialization of wiphy_work to before rfkill initialization to avoid this issue.
[1]
INFO: trying to register non-static key.
The code is fine but needs lockdep annotation, or maybe you didn't initialize this object before use? turning off the locking correctness validator.
CPU: 0 UID: 0 PID: 5935 Comm: syz-executor550 Not tainted 6.14.0-rc6-syzkaller-00103-g4003c9e78778 #0 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Call Trace: <TASK> __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120 assign_lock_key kernel/locking/lockdep.c:983 [inline] register_lock_class+0xc39/0x1240 kernel/locking/lockdep.c:1297 __lock_acquire+0x135/0x3c40 kernel/locking/lockdep.c:5103 lock_acquire.part.0+0x11b/0x380 kernel/locking/lockdep.c:5851 __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] _raw_spin_lock_irqsave+0x3a/0x60 kernel/locking/spinlock.c:162 cfg80211_dev_free+0x30/0x3d0 net/wireless/core.c:1196 device_release+0xa1/0x240 drivers/base/core.c:2568 kobject_cleanup lib/kobject.c:689 [inline] kobject_release lib/kobject.c:720 [inline] kref_put include/linux/kref.h:65 [inline] kobject_put+0x1e4/0x5a0 lib/kobject.c:737 put_device+0x1f/0x30 drivers/base/core.c:3774 wiphy_free net/wireless/core.c:1224 [inline] wiphy_new_nm+0x1c1f/0x2160 net/wireless/core.c:562 ieee80211_alloc_hw_nm+0x1b7a/0x2260 net/mac80211/main.c:835 mac80211_hwsim_new_radio+0x1d6/0x54e0 drivers/net/wireless/virtual/mac80211_hwsim.c:5185 hwsim_new_radio_nl+0xb42/0x12b0 drivers/net/wireless/virtual/mac80211_hwsim.c:6242 genl_family_rcv_msg_doit+0x202/0x2f0 net/netlink/genetlink.c:1115 genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline] genl_rcv_msg+0x565/0x800 net/netlink/genetlink.c:1210 netlink_rcv_skb+0x16b/0x440 net/netlink/af_netlink.c:2533 genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219 netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline] netlink_unicast+0x53c/0x7f0 net/netlink/af_netlink.c:1338 netlink_sendmsg+0x8b8/0xd70 net/netlink/af_netlink.c:1882 sock_sendmsg_nosec net/socket.c:718 [inline] __sock_sendmsg net/socket.c:733 [inline] ____sys_sendmsg+0xaaf/0xc90 net/socket.c:2573 ___sys_sendmsg+0x135/0x1e0 net/socket.c:2627 __sys_sendmsg+0x16e/0x220 net/socket.c:2659 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83
Close: https://syzkaller.appspot.com/bug?extid=aaf0488c83d1d5f4f029
--- net/wireless/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/wireless/core.c +3 -3
@@ -546,6 +546,9 @@ use_default_name:INIT_WORK (&rdev->mgmt_registrations_update_wk, cfg80211_mgmt_registrations_update_wk);spin_lock_init (&rdev->mgmt_registrations_lock); +INIT_WORK (&rdev->wiphy_work, cfg80211_wiphy_work); +INIT_LIST_HEAD (&rdev->wiphy_work_list); +spin_lock_init (&rdev->wiphy_work_lock);#ifdef CONFIG_CFG80211_DEFAULT_PS rdev->wiphy.flags |=WIPHY_FLAG_PS_ON_BY_DEFAULT ;
@@ -563,9 +566,6 @@ use_default_name:return NULL ; } -INIT_WORK (&rdev->wiphy_work, cfg80211_wiphy_work); -INIT_LIST_HEAD (&rdev->wiphy_work_list); -spin_lock_init (&rdev->wiphy_work_lock);INIT_WORK (&rdev->rfkill_block, cfg80211_rfkill_block_work);INIT_WORK (&rdev->conn_work, cfg80211_conn_work);INIT_WORK (&rdev->event_work, cfg80211_event_work);
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.199 release. There are 206 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 Fri, 06 Feb 2026 14:38:23 +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/v5.x/stable-review/patch-5.15.199-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Signature · 1 line
Florian
# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 5.15.199-rc1-00207-g28560a25ac8d #1 SMP Wed Feb 4 19:30:54 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.199 release. There are 206 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 Fri, 06 Feb 2026 14:38:23 +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/v5.x/stable-review/patch-5.15.199-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.199 release. There are 206 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.