6.18.34-rc1 review
Subsystems (3)
Greg Kroah-Hartman
maintainerPATCH 265/377 block: dont overwrite bip_vcnt in bio_integrity_copy_user()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <[email protected]>
[ Upstream commit 637ad3a56a3b889527d1dacea6fea2a8bd648140 ]
bio_integrity_add_page() already sets bip_vcnt to 1 for the bounce segment. Overwriting it with nr_vecs breaks bip_vcnt <= bip_max_vcnt on WRITE (bip_max_vcnt is 1), so the gap-merge checks in block/blk.h read past the bip_vec[] flex array. On READ the read is in bounds but lands on a saved user bvec instead of the bounce.
The line was added for split propagation, but bio_integrity_clone() doesn't copy bip_vcnt and BIP_CLONE_FLAGS excludes BIP_COPY_USER.
--- block/bio-integrity.c | 1 - 1 file changed, 1 deletion(-)
block/bio-integrity.c +0 -1
@@ -205,7 +205,6 @@ static int bio_integrity_copy_user(struct bio *bio, struct bio_vec *bvec, } bip->bip_flags |=BIP_COPY_USER ; - bip->bip_vcnt = nr_vecs;return 0 ; free_bip:bio_integrity_free (bio);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 266/377 block: recompute nr_integrity_segments in blk_insert_cloned_request
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Casey Chen <[email protected]>
[ Upstream commit 2c6e6a18a37b905cb584eb0dda3ae482162a81ca ]
blk_insert_cloned_request() already recomputes nr_phys_segments against the bottom queue, because "the queue settings related to segment counting may differ from the original queue." The exact same reasoning applies to integrity segments: a stacked driver's underlying queue can have tighter virt_boundary_mask, seg_boundary_mask, or max_segment_size than the top queue, in which case blk_rq_count_integrity_sg() against the bottom queue produces a different count than the cached rq->nr_integrity_segments inherited from the source request by blk_rq_prep_clone().
When the cached count is lower than the bottom queue's actual count, blk_rq_map_integrity_sg() trips
BUG_ON(segments > rq->nr_integrity_segments);
on dispatch. The same families of stacked setups that motivated the existing nr_phys_segments recompute -- dm-multipath fanning out to nvme-rdma in particular -- can produce this.
Mirror the nr_phys_segments handling: when the request carries integrity, recompute nr_integrity_segments against the bottom queue and reject the request if it exceeds the bottom queue's max_integrity_segments. blk_rq_count_integrity_sg() and queue_max_integrity_segments() are both already available via <linux/blk-integrity.h>, which blk-mq.c includes.
This closes a latent gap in the stacking contract and brings the integrity-segment accounting in line with the existing phys-segment accounting.
--- block/blk-mq.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
block/blk-mq.c +19 -0
@@ -3285,6 +3285,25 @@ blk_status_t blk_insert_cloned_request(struct request *rq)return BLK_STS_IOERR ; } +/* +* Integrity segment counting depends on the same queue limits +* (virt_boundary_mask, seg_boundary_mask, max_segment_size) that +* vary across stacked queues, so recompute against the bottom +* queue just like nr_phys_segments above. +*/ +if (blk_integrity_rq (rq) && rq->bio) { +unsigned short max_int_segs =queue_max_integrity_segments (q); + + rq->nr_integrity_segments = +blk_rq_count_integrity_sg (rq->q, rq->bio); +if (rq->nr_integrity_segments > max_int_segs) { +printk (KERN_ERR "%s: over max integrity segments limit. (%u > %u)\n" , + __func__, rq->nr_integrity_segments, + max_int_segs); +return BLK_STS_IOERR ; + } + } +if (q->disk &&should_fail_request (q->disk->part0,blk_rq_bytes (rq)))return BLK_STS_IOERR ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 267/377 HID: quirks: really enable the intended work around for appledisplay
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lukas Bulwahn <[email protected]>
[ Upstream commit 5f90dcfa8dc32a488581b78e575cdd7808ba5c78 ]
Commit c7fabe4ad921 ("HID: quirks: work around VID/PID conflict for appledisplay") intends to add a quirk for kernels built with Apple Cinema Display support, but it refers to the non-existing config option CONFIG_APPLEDISPLAY, whereas the config option for Apple Cinema Display support is named CONFIG_USB_APPLEDISPLAY.
Refer to the intended config option CONFIG_USB_APPLEDISPLAY in the ifdef directive.
--- drivers/hid/hid-quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hid/hid-quirks.c +1 -1
@@ -234,7 +234,7 @@ static const struct hid_device_id hid_quirks[] = {* used as a driver. See hid_scan_report(). */ static const struct hid_device_id hid_have_special_driver[] = { -#if IS_ENABLED(CONFIG_APPLEDISPLAY) +#if IS_ENABLED(CONFIG_USB_APPLEDISPLAY) {HID_USB_DEVICE (USB_VENDOR_ID_APPLE ,0x9218 ) }, {HID_USB_DEVICE (USB_VENDOR_ID_APPLE ,0x9219 ) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 0x921c) },
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 268/377 block: bio-integrity: Fix null-ptr-deref in bio_integrity_map_user()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sungwoo Kim <[email protected]>
[ Upstream commit 8582792cf23b3d94674d4d838f7cde9a28d0fcaf ]
pin_user_pages_fast() can partially succeed and return the number of pages that were actually pinned. However, the bio_integrity_map_user() does not handle this partial pinning. This leads to a general protection fault since bvec_from_pages() dereferences an unpinned page address, which is 0.
To fix this, add a check to verify that all requested memory is pinned. If partial pinning occurs, unpin the memory and return -EFAULT.
Kernel Oops:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] CPU: 0 UID: 0 PID: 1061 Comm: nvme-passthroug Not tainted 7.0.0-11783-g90957f9314e8-dirty #16 PREEMPT(lazy) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014 RIP: 0010:bio_integrity_map_user.cold+0x1b0/0x9d6
--- block/bio-integrity.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
block/bio-integrity.c +18 -0
@@ -299,6 +299,24 @@ int bio_integrity_map_user(struct bio *bio, struct iov_iter *iter)if (unlikely (ret <0 )) goto free_bvec; +/* +* Handle partial pinning. This can happen when pin_user_pages_fast() +* returns fewer pages than requested. +*/ +if (user_backed_iter (iter) &&unlikely (ret != bytes)) { +if (ret >0 ) { +int npinned =DIV_ROUND_UP (offset + ret,PAGE_SIZE ); +int i; + +for (i =0 ; i < npinned; i++) +unpin_user_page (pages[i]); + } +if (pages != stack_pages) +kvfree (pages); + ret = -EFAULT ; + goto free_bvec; + } + nr_bvecs =bvec_from_pages (bvec, pages, nr_vecs, bytes, offset, &is_p2p);if (pages != stack_pages)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 269/377 accel/qaic: Add overflow check to remap_pfn_range during mmap
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zack McKevitt <[email protected]>
[ Upstream commit aa16b2bc0f02709919e2435f531406531e5bcc69 ]
The call to remap_pfn_range in qaic_gem_object_mmap is susceptible to (re)mapping beyond the VMA if the BO is too large. This can cause use after free issues when munmap() unmaps only the VMA region and not the additional mappings. To prevent this, check the remaining size of the VMA before remapping and truncate the remapped length if sg->length is too large.
--- drivers/accel/qaic/qaic_data.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
drivers/accel/qaic/qaic_data.c +21 -2
@@ -605,8 +605,11 @@ static const struct vm_operations_struct drm_vm_ops = {static int qaic_gem_object_mmap (struct drm_gem_object *obj,struct vm_area_struct *vma) {struct qaic_bo *bo =to_qaic_bo (obj); +unsigned long remap_start;unsigned long offset =0 ; +unsigned long remap_end;struct scatterlist *sg; +unsigned long length;int ret =0 ;if (drm_gem_is_imported (obj))
@@ -614,11 +617,27 @@ static int qaic_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_strucfor (sg = bo->sgt->sgl; sg; sg =sg_next (sg)) {if (sg_page (sg)) { +/* if sg is too large for the VMA, so truncate it to fit */ +if (check_add_overflow (vma->vm_start, offset, &remap_start)) +return -EINVAL ; +if (check_add_overflow (remap_start, sg->length, &remap_end)) +return -EINVAL ; + +if (remap_end > vma->vm_end) { +if (check_sub_overflow (vma->vm_end, remap_start, &length)) +return -EINVAL ; + }else { + length = sg->length; + } + +if (length ==0 ) + goto out; + ret =remap_pfn_range (vma, vma->vm_start + offset,page_to_pfn (sg_page (sg)), - sg->length, vma->vm_page_prot); + length, vma->vm_page_prot);if (ret) goto out; - offset += sg->length; + offset += length; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 270/377 net/smc: avoid NULL deref of conn->lnk in smc_msg_event tracepoint
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit 7bf563badd37cb796df5477d2b78bb64148a1268 ]
The smc_msg_event tracepoint class, shared by smc_tx_sendmsg and smc_rx_recvmsg, unconditionally dereferences smc->conn.lnk:
__string(name, smc->conn.lnk->ibname)
conn->lnk is only set for SMC-R; for SMC-D it is NULL. Other code on these paths already handles this (e.g. !conn->lnk in SMC_STAT_RMB_TX_SIZE_SMALL()). With the tracepoint enabled, the first sendmsg()/recvmsg() on an SMC-D socket crashes:
Oops: general protection fault, probably for non-canonical address KASAN: null-ptr-deref in range [...] RIP: 0010:strlen+0x1e/0xa0 Call Trace: trace_event_raw_event_smc_msg_event (net/smc/smc_tracepoint.h:44) smc_rx_recvmsg (net/smc/smc_rx.c:515) smc_recvmsg (net/smc/af_smc.c:2859) __sys_recvfrom (net/socket.c:2315) __x64_sys_recvfrom (net/socket.c:2326) do_syscall_64
The faulting address 0x3e0 is offsetof(struct smc_link, ibname), confirming the NULL ->lnk deref. Enabling the tracepoint requires root, but the trigger itself is unprivileged: socket(AF_SMC, ...) has no capability check, and SMC-D negotiation needs no admin step on s390 or on x86 with the loopback ISM device loaded.
Log an empty device name for SMC-D instead of dereferencing NULL.
--- net/smc/smc_tracepoint.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/smc/smc_tracepoint.h +1 -1
@@ -51,7 +51,7 @@ DECLARE_EVENT_CLASS(smc_msg_event, __field(const void *, smc) __field(u64, net_cookie) __field(size_t, len) - __string(name, smc->conn.lnk->ibname) + __string(name, smc->conn.lnk ? smc->conn.lnk->ibname : "") ), TP_fast_assign(
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 271/377 ethtool: fix ethnl_bitmap32_not_zero() bit interval semantics
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <[email protected]>
[ Upstream commit 3d042592ebd4c7e44974d556de0b727cb7db4dab ]
ethnl_bitmap32_not_zero() should return true if some bit in [start, end) is set:
- Fix inverted memchr_inv() sense: return true when the scan finds a non-zero byte, not when the middle words are all zero.
- Return false for an empty interval (end <= start).
- When end is 32-bit aligned, indices in [start, end) do not include any bits from map[end_word]; return false after earlier checks found no non-zero data.
--- net/ethtool/bitset.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/ethtool/bitset.c +4 -4
@@ -91,7 +91,7 @@ static bool ethnl_bitmap32_not_zero(const u32 *map, unsigned int start,u32 mask;if (end <= start) -return true; +return false;if (start %32 ) { mask =ethnl_upper_bits (start);
@@ -104,11 +104,11 @@ static bool ethnl_bitmap32_not_zero(const u32 *map, unsigned int start, start_word++; } -if (!memchr_inv (map + start_word,'\0' , - (end_word - start_word) *sizeof (u32))) +if (memchr_inv (map + start_word,'\0' , + (end_word - start_word) *sizeof (u32)))return true;if (end %32 ==0 ) -return true; +return false;return map[end_word] ðnl_lower_bits (end); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 272/377 drm/msm/dsi: dont dump registers past the mapped region
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit 5b49a46baa853b26dbefa65c6c75dd9ff69f63d4 ]
On DSI 6G platforms the IO address space is internally adjusted by io_offset. Later this adjusted address might be used for memory dumping. However the size that is used for memory dumping isn't adjusted to account for the io_offset, leading to the potential access to the unmapped region. Lower ctrl_size by the io_offset value to prevent access past the mapped area.
msm_disp_snapshot_add_block+0x1d4/0x3c8 [msm] (P) msm_dsi_host_snapshot+0x4c/0x78 [msm] msm_dsi_snapshot+0x28/0x50 [msm] msm_disp_snapshot_capture_state+0x74/0x140 [msm] msm_disp_snapshot_state_sync+0x60/0x90 [msm] _msm_disp_snapshot_work+0x30/0x90 [msm] kthread_worker_fn+0xdc/0x460 kthread+0x120/0x140
Patchwork: https://patchwork.freedesktop.org/patch/721747/
--- drivers/gpu/drm/msm/dsi/dsi_host.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/msm/dsi/dsi_host.c +1 -0
@@ -2003,6 +2003,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)/* fixup base address by io offset */ msm_host->ctrl_base += cfg->io_offset; + msm_host->ctrl_size -= cfg->io_offset; ret = devm_regulator_bulk_get_const(&pdev->dev, cfg->num_regulators, cfg->regulator_data,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 273/377 drm/msm/dpu: dont mix devm and drmm functions
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit c0c70a11365cba7fba25a77463582bcec0f7846e ]
Mixing devm and drmm functions will result in a use-after-free on msm driver teardown if userspace keeps a reference on the drm device:
The WB connector data will be destroyed because of the use of devm_kzalloc()), while the usersoace still can try interacting with the WB connector (which uses drmm_ functions).
Change dpu_writeback_init() to use drmm_.
Patchwork: https://patchwork.freedesktop.org/patch/722656/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c +2 -1
@@ -5,6 +5,7 @@#include <drm/drm_edid.h> #include <drm/drm_framebuffer.h> +#include <drm/drm_managed.h> #include "dpu_writeback.h"
@@ -125,7 +126,7 @@ int dpu_writeback_init(struct drm_device *dev, struct drm_encoder *enc,struct dpu_wb_connector *dpu_wb_conn;int rc =0 ; - dpu_wb_conn =devm_kzalloc (dev->dev,sizeof (*dpu_wb_conn),GFP_KERNEL ); + dpu_wb_conn =drmm_kzalloc (dev,sizeof (*dpu_wb_conn),GFP_KERNEL );if (!dpu_wb_conn)return -ENOMEM ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 274/377 selftests: ublk: cap nthreads to kernels actual nr_hw_queues
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
[ Upstream commit 87d0740b7c4cc847be1b6f307ab6d8547cb1a726 ]
dev->nthreads is derived from the user-requested queue count before the ADD command, but the kernel may reduce nr_hw_queues (capped to nr_cpu_ids). When the VM has fewer CPUs than requested queues, the daemon creates more handler threads than there are kernel queues.
In non-batch mode, the extra threads access uninitialized queues (q_depth=0), submit zero io_uring SQEs, and block forever in io_cqring_wait. In batch mode, the extra threads cause similar hangs during device removal.
In both cases, the stuck threads prevent the daemon from closing the char device, holding the last ublk_device reference and causing ublk_ctrl_del_dev() to hang in wait_event_interruptible().
Fix by capping dev->nthreads to the kernel-returned nr_hw_queues after the ADD command completes. per_io_tasks mode is excluded because threads interleave across all queues, so nthreads > nr_hw_queues is valid.
--- tools/testing/selftests/ublk/kublk.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
tools/testing/selftests/ublk/kublk.c +11 -0
@@ -1220,6 +1220,17 @@ static int __cmd_dev_add(const struct dev_ctx *ctx) goto fail; } +/* +* The kernel may reduce nr_hw_queues (e.g. capped to nr_cpu_ids). +* Cap nthreads to the actual queue count to avoid creating extra +* handler threads that will hang during device removal. +* +* per_io_tasks mode is excluded: threads interleave across all +* queues so nthreads > nr_hw_queues is valid and intentional. +*/ +if (!ctx->per_io_tasks && dev->nthreads > info->nr_hw_queues) + dev->nthreads = info->nr_hw_queues; + ret =ublk_start_daemon (ctx, dev);ublk_dbg (UBLK_DBG_DEV ,"%s: daemon exit %d\n" , __func__, ret);if (ret <0 )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 275/377 x86/mce: Restore MCA polling interval halving
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Borislav Petkov (AMD) <[email protected]>
[ Upstream commit ea324444ece9f301b5c4ff71b258cc68990c4d61 ]
RongQing reported that the MCA polling interval doesn't halve when an error gets logged. It was traced down to the commit in Fixes:, because:
mce_timer_fn()
|-> mce_poll_banks() |-> machine_check_poll() |-> mce_log()
which will queue the work and return.
Now, back in mce_timer_fn():
/*
* Alert userspace if needed. If we logged an MCE, reduce the polling
* interval, otherwise increase the polling interval.
*/
if (mce_notify_irq())<--- here we haven't ran the notifier chain yet so mce_need_notify is not set yet so this won't hit and we won't halve the interval iv.
Now the notifier chain runs. mce_early_notifier() sets the bit, does mce_notify_irq(), that clears the bit and then the notifier chain a little later logs the error.
So this is a silly timing issue.
But, that's all unnecessary.
All it needs to happen here is, the "should we notify of a logged MCE" mce_notify_irq() asks, should be simply a question to the mce gen pool:
"Are you empty?"
And that then turns into a simple yes or no answer and it all JustWorks(tm).
So do that and also distribute the functionality where it belongs:
- Print that MCE events have been logged in mce_log()
- Trigger the mcelog tool specific work in the first notifier
As a result, mce_notify_irq() can go now.
--- arch/x86/kernel/cpu/mce/core.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-)
arch/x86/kernel/cpu/mce/core.c +5 -28
@@ -89,7 +89,6 @@ struct mca_config mca_cfg __read_mostly = { }; static DEFINE_PER_CPU(struct mce_hw_err, hw_errs_seen); -static unsigned long mce_need_notify;/* * MCA banks polled by the period polling timer for corrected events.
@@ -151,8 +150,10 @@ EXPORT_PER_CPU_SYMBOL_GPL(injectm);void mce_log (struct mce_hw_err *err) { -if (mce_gen_pool_add (err)) +if (mce_gen_pool_add (err)) { +pr_info (HW_ERR "Machine check events logged\n" );irq_work_queue (&mce_irq_work); + } }EXPORT_SYMBOL_GPL (mce_log);
@@ -584,28 +585,6 @@ bool mce_is_correctable(struct mce *m) }EXPORT_SYMBOL_GPL (mce_is_correctable); -/* -* Notify the user(s) about new machine check events. -* Can be called from interrupt context, but not from machine check/NMI -* context. -*/ -static bool mce_notify_irq (void ) -{ -/* Not more than two messages every minute */ - static DEFINE_RATELIMIT_STATE(ratelimit, 60*HZ, 2); - -if (test_and_clear_bit (0 , &mce_need_notify)) { -mce_work_trigger (); - -if (__ratelimit (&ratelimit)) -pr_info (HW_ERR "Machine check events logged\n" ); - -return true; - } - -return false; -} -static int mce_early_notifier (struct notifier_block *nb,unsigned long val,void *data) {
@@ -617,9 +596,7 @@ static int mce_early_notifier(struct notifier_block *nb, unsigned long val,/* Emit the trace record: */ trace_mce_record (err); -set_bit (0 , &mce_need_notify); - -mce_notify_irq (); +mce_work_trigger ();return NOTIFY_DONE ; }
@@ -1771,7 +1748,7 @@ static void mce_timer_fn(struct timer_list *t)* Alert userspace if needed. If we logged an MCE, reduce the polling * interval, otherwise increase the polling interval. */ -if (mce_notify_irq ()) +if (!mce_gen_pool_empty ()) iv =max (iv /2 , (unsigned long )HZ /100 );else iv =min (iv *2 ,round_jiffies_relative (check_interval *HZ ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 276/377 Documentation: intel_pstate: Fix description of asymmetric packing with SMT
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ricardo Neri <[email protected]>
[ Upstream commit ee047fc7a2da90554410128195058c409a391d43 ]
Patchset [1], including commits
046a5a95c3b0 ("x86/sched/itmt: Give all SMT siblings of a core the same priority") 995998ebdebd ("x86/sched: Remove SD_ASYM_PACKING from the SMT domain flags")
overhauled asym_packing handling in the scheduler on x86 hybrid processors with SMT. It removed SD_ASYM_PACKING from the x86 SMT scheduling domain and made all SMT siblings of a core share the same priority. As a result, asym_packing operates only across physical cores, spreading tasks among them and only using idle SMT siblings once all physical cores are busy.
Fix the documentation to reflect this behavior.
--- Documentation/admin-guide/pm/intel_pstate.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
Documentation/admin-guide/pm/intel_pstate.rst +6 -5
@@ -348,11 +348,12 @@ HyperThreading (HT) in the context of Intel processors, is enabled on at least one core, ``intel_pstate`` assigns performance-based priorities to CPUs. Namely, the priority of a given CPU reflects its highest HWP performance level which causes the CPU scheduler to generally prefer more performant CPUs, so the less -performant CPUs are used when the other ones are fully loaded. However, SMT -siblings (that is, logical CPUs sharing one physical core) are treated in a -special way such that if one of them is in use, the effective priority of the -other ones is lowered below the priorities of the CPUs located in the other -physical cores. +performant CPUs are used when the other ones are fully loaded. SMT siblings +(that is, logical CPUs sharing one physical core) are given the same priority. +The scheduler can pull tasks from lower-priority cores and place them on any +sibling. Since the scheduler spreads tasks among physical cores, tasks will be +placed on the SMT siblings of physical cores only after all physical cores are +busy. This approach maximizes performance in the majority of cases, but unfortunately it also leads to excessive energy usage in some important scenarios, like video
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 277/377 drm/msm/adreno: fix userspace-triggered crash on a2xx-a4xx
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit 2b4abf879360ea00a9e2b46d2d15dcdbc0687eed ]
Before a5xx Adreno driver will not try fetching UBWC params (because those generations didn't support UBWC anyway), however it's still possible to query UBWC-related params from the userspace, triggering possible NULL pointer dereference. Check for UBWC config in adreno_get_param() and return sane defaults if there is none.
Patchwork: https://patchwork.freedesktop.org/patch/717778/
Message-ID: <[email protected]>
--- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/drm/msm/adreno/adreno_gpu.c +6 -0
@@ -419,15 +419,21 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx, *value = vm->mm_range;return 0 ;case MSM_PARAM_HIGHEST_BANK_BIT : +if (!adreno_gpu->ubwc_config) +return UERR (ENOENT , drm,"no UBWC on this platform" ); *value = adreno_gpu->ubwc_config->highest_bank_bit;return 0 ;case MSM_PARAM_RAYTRACING : *value = adreno_gpu->has_ray_tracing;return 0 ;case MSM_PARAM_UBWC_SWIZZLE : +if (!adreno_gpu->ubwc_config) +return UERR (ENOENT , drm,"no UBWC on this platform" ); *value = adreno_gpu->ubwc_config->ubwc_swizzle;return 0 ;case MSM_PARAM_MACROTILE_MODE : +if (!adreno_gpu->ubwc_config) +return UERR (ENOENT , drm,"no UBWC on this platform" ); *value = adreno_gpu->ubwc_config->macrotile_mode;return 0 ;case MSM_PARAM_UCHE_TRAP_BASE :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 278/377 drm/msm: Fix iommu_map_sgtable() return value check and avoid WARN
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikko Perttunen <[email protected]>
[ Upstream commit 55e0f0d1c1a4ee1e46da7da4d443eb3044fb3851 ]
Commit "iommu: return full error code from iommu_map_sg[_atomic]()" changed iommu_map_sgtable() to return an ssize_t and negative values in error cases, rather than a size_t and a zero.
Store the return value in the appropriate type and in case of error, return it rather than WARNing.
Patchwork: https://patchwork.freedesktop.org/patch/719685/
Message-ID: <[email protected]>
--- drivers/gpu/drm/msm/msm_iommu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/msm_iommu.c +3 -2
@@ -677,7 +677,7 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, int prot) {struct msm_iommu *iommu =to_msm_iommu (mmu); -size_t ret; +ssize_t ret;WARN_ON (off !=0 );
@@ -686,7 +686,8 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, iova |=GENMASK_ULL (63 ,49 ); ret =iommu_map_sgtable (iommu->domain, iova, sgt, prot); -WARN_ON (!ret); +if (ret <0 ) +return ret;return (ret == len) ?0 : -EINVAL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 279/377 powerpc/time: Remove redundant preempt_disable|enable() calls from arch_irq_work_raise()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sayali Patil <[email protected]>
[ Upstream commit 31467b23823ffec1f6fff407f8e3ca9af8b7491a ]
A kernel panic is observed when handling machine check exceptions from real mode.
BUG: Unable to handle kernel data access on read at 0xc00000006be21300 Oops: Kernel access of bad area, sig: 11 [#1] MSR: 8000000000001003 <SF,ME,RI,LE> CR: 88222248 XER: 00000005 CFAR: c00000000003ffc4 DAR: c00000006be21300 DSISR: 40000000 IRQMASK: 0 NIP [c000000000029e40] arch_irq_work_raise+0x10/0x70 LR [c00000000003ffc8] machine_check_queue_event+0xa8/0x150 Call Trace: [c0000000179d3c70] [c00000000003ff64] machine_check_queue_event+0x44/0x150 [c0000000179d3d30] [c0000000000084e0] machine_check_early_common+0x1f0/0x2c0
The crash occurs because arch_irq_work_raise() calls preempt_disable() from machine check exception (MCE) handlers running in real mode. In this context, accessing the preempt_count can fault, leading to the panic.
The preempt_disable()/preempt_enable() pair in arch_irq_work_raise() was originally added by commit 0fe1ac48bef0 ("powerpc/perf_event: Fix oops due to perf_event_do_pending call") to avoid races while raising irq work from exception context.
Later, commit 471ba0e686cb ("irq_work: Do not raise an IPI when queueing work on the local CPU") added preemption protection in irq_work_queue() path, while commit 20b876918c06 ("irq_work: Use per cpu atomics instead of regular atomics") added equivalent protection in irq_work_queue_on() before reaching arch_irq_work_raise():
irq_work_queue() / irq_work_queue_on()
-> preempt_disable()
-> __irq_work_queue_local()
-> irq_work_raise()
-> arch_irq_work_raise()As a result, callers other than mce_irq_work_raise() already execute with preemption disabled, making the additional preempt_disable()/preempt_enable() pair in arch_irq_work_raise() redundant.
The arch_irq_work_raise() function executes in NMI context when called from MCE handler. Hence we will not be preempted or scheduled out since we are in NMI context with MSR[EE]=0. Therefore, it is safe to remove the preempt_disable()/preempt_enable() calls from here.
Remove it to avoid accessing preempt_count from real mode context.
--- arch/powerpc/kernel/time.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/powerpc/kernel/time.c +4 -2
@@ -458,6 +458,10 @@ DEFINE_PER_CPU(u8, irq_work_pending);#endif /* 32 vs 64 bit */ +/* +* Must be called with preemption disabled since it updates +* per-CPU irq_work state and programs the local CPU decrementer. +*/ void arch_irq_work_raise (void ) {/*
@@ -471,10 +475,8 @@ void arch_irq_work_raise(void)* which could get tangled up if we're messing with the same state * here. */ -preempt_disable ();set_irq_work_pending_flag ();set_dec (1 ); -preempt_enable (); }static void set_dec_or_work (u64 val)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 280/377 net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit 277740023def559a4a2ddc3e8e784ee37a0f16a9 ]
On the SMC-D client, slot 0 of ini->ism_dev[]/ini->ism_chid[] is reserved for an SMC-Dv1 device. smc_find_ism_v2_device_clnt() populates V2 entries starting at index 1, so when no V1 device is selected slot 0 is left in its kzalloc()'ed state with ism_dev[0] == NULL and ism_chid[0] == 0.
smc_v2_determine_accepted_chid() then matches the peer's CHID against the array starting from index 0 using the CHID alone. A malicious peer replying to a SMC-Dv2-only proposal with d1.chid == 0 matches the empty slot, ini->ism_selected becomes 0, and the subsequent ism_dev[0]->lgr_lock dereference in smc_conn_create() faults at offsetof(struct smcd_dev, lgr_lock) == 0x68:
BUG: KASAN: null-ptr-deref in _raw_spin_lock_bh+0x79/0xe0 Write of size 4 at addr 0000000000000068 by task exploit/144 Call Trace: _raw_spin_lock_bh smc_conn_create (net/smc/smc_core.c:1997) __smc_connect (net/smc/af_smc.c:1447) smc_connect (net/smc/af_smc.c:1720) __sys_connect __x64_sys_connect do_syscall_64
Require ism_dev[i] to be non-NULL before accepting a CHID match.
--- net/smc/af_smc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/smc/af_smc.c +2 -1
@@ -1400,7 +1400,8 @@ smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm *aclc,int i;for (i =0 ; i < ini->ism_offered_cnt +1 ; i++) { -if (ini->ism_chid[i] ==ntohs (aclc->d1.chid)) { +if (ini->ism_dev[i] && + ini->ism_chid[i] ==ntohs (aclc->d1.chid)) { ini->ism_selected = i;return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 281/377 net: tls: fix off-by-one in sg_chain entry count for wrapped sk_msg ring
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit 285943c6e7ca309bbea84b253745154241d9788a ]
When an sk_msg scatterlist ring wraps (sg.end < sg.start), tls_push_record() chains the tail portion of the ring to the head using sg_chain(). An extra entry in the sg array is reserved for this:
struct sk_msg_sg {
[...]
/* The extra two elements:
* 1) used for chaining the front and sections when the list becomes
* partitioned (e.g. end < start). The crypto APIs require the
* chaining;
* 2) to chain tailer SG entries after the message.
*/
struct scatterlist data[MAX_MSG_FRAGS + 2];
The current code uses MAX_SKB_FRAGS + 1 as the ring size:
sg_chain(&msg_pl->sg.data[msg_pl->sg.start],
MAX_SKB_FRAGS - msg_pl->sg.start + 1,
msg_pl->sg.data);This places the chain pointer at
sg_chain(data[start], (MAX_SKB_FRAGS - msg_start + 1) .. = &data[start] + (MAX_SKB_FRAGS - msg_start + 1) - 1 = data[start + (MAX_SKB_FRAGS - start + 1) - 1] = data[MAX_SKB_FRAGS]
instead of the true last entry. This is likely due to a "race" of the commit under Fixes landing close to
commit 031097d9e079 ("bpf: sk_msg, zap ingress queue on psock down")
Convert to ARRAY_SIZE and drop the data[start] / - start (as suggested by Sabrina).
--- net/tls/tls_sw.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
net/tls/tls_sw.c +2 -4
@@ -800,11 +800,9 @@ static int tls_push_record(struct sock *sk, int flags,sg_mark_end (sk_msg_elem (msg_pl, i)); } -if (msg_pl->sg.end < msg_pl->sg.start) { -sg_chain (&msg_pl->sg.data[msg_pl->sg.start], -MAX_SKB_FRAGS - msg_pl->sg.start +1 , +if (msg_pl->sg.end < msg_pl->sg.start) +sg_chain (msg_pl->sg.data,ARRAY_SIZE (msg_pl->sg.data), msg_pl->sg.data); - } i = msg_pl->sg.start;sg_chain (rec->sg_aead_in,2 , &msg_pl->sg.data[i]);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 282/377 net: tls: prevent chain-after-chain in plain text SG
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit ff26a0e8377dec07e4a7230db7675bed1b9a6d03 ]
Sashiko points out that if end = 0 (start != 0) the current code will create a chain link to content type right after the wrap link:
This would create a chain where the wrap link points directly to another chain link. The scatterlist API sg_next iterator does not recursively resolve consecutive chain links.
meaning this is illegal input to crypto.
The wrapping link is unnecessary if end = 0. end is the entry after the last one used so end = 0 means there's nothing pushed after the wrap:
end start i
v v v
[ ]...[ ][ d ][ d ][ d ][ d ][rsv for wrap]
Skip the wrapping in this case.
TLS 1.3 can use the "wrapping slot" for it's chaining if end = 0. This avoids the chain-after-chain.
Move the wrap chaining before marking END and chaining off content type, that feels like more logical ordering to me, but should not matter from functional perspective.
--- net/tls/tls_sw.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
net/tls/tls_sw.c +18 -6
@@ -789,21 +789,33 @@ static int tls_push_record(struct sock *sk, int flags, i = msg_pl->sg.end;sk_msg_iter_var_prev (i); +/* msg_pl->sg.data is a ring; data[MAX+1] is reserved for the wrap +* link (frags won't use it). 'i' is now the last filled entry: +* +* i end start +* v v v [ rsv ] +* [ d ][ d ][ ][ ]...[ ][ d ][ d ][ d ][chain] +* ^ END v +* `-----------------------------------------' +* +* Note that SGL does not allow chain-after-chain, so for TLS 1.3, +* we must make sure we don't create the wrap entry and then chain +* link to content_type immediately at index 0. +*/ +if (i < msg_pl->sg.start) +sg_chain (msg_pl->sg.data,ARRAY_SIZE (msg_pl->sg.data), + msg_pl->sg.data); + rec->content_type = record_type;if (prot->version ==TLS_1_3_VERSION ) {/* Add content type to end of message. No padding added */ sg_set_buf (&rec->sg_content_type, &rec->content_type,1 );sg_mark_end (&rec->sg_content_type); -sg_chain (msg_pl->sg.data, msg_pl->sg.end +1 , - &rec->sg_content_type); +sg_chain (msg_pl->sg.data, i +2 , &rec->sg_content_type); }else {sg_mark_end (sk_msg_elem (msg_pl, i)); } -if (msg_pl->sg.end < msg_pl->sg.start) -sg_chain (msg_pl->sg.data,ARRAY_SIZE (msg_pl->sg.data), - msg_pl->sg.data); - i = msg_pl->sg.start;sg_chain (rec->sg_aead_in,2 , &msg_pl->sg.data[i]);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 283/377 net: phy: DP83TC811: add reading of abilities
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Schuchmann <[email protected]>
[ Upstream commit c78bdba7b9666020c0832150a4fc4c0aebc7c6ac ]
At this time the driver is not listing any speeds
it supports. This should be ETHTOOL_LINK_MODE_100baseT1_Full_BIT for DP83TC811. Add the missing call for phylib to read the abilities.
--- drivers/net/phy/dp83tc811.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/phy/dp83tc811.c +1 -0
@@ -393,6 +393,7 @@ static struct phy_driver dp83811_driver[] = { .config_init = dp83811_config_init, .config_aneg = dp83811_config_aneg, .soft_reset = dp83811_phy_reset, + .get_features = genphy_c45_pma_read_ext_abilities, .get_wol = dp83811_get_wol, .set_wol = dp83811_set_wol, .config_intr = dp83811_config_intr,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 284/377 ovpn: tcp - use cached peer pointer in ovpn_tcp_close()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <[email protected]>
[ Upstream commit 775d8d7ad02aa345e1588424a6a8b9ae49fb9012 ]
ovpn_tcp_close() loads the ovpn_socket via rcu_dereference_sk_user_data() under rcu_read_lock(), takes a reference on sock->peer, caches the peer pointer in a local, and drops the read lock. It then passes sock->peer (rather than the cached local) to ovpn_peer_del(), re-dereferencing the ovpn_socket after the RCU read section has ended.
Unlike ovpn_tcp_sendmsg(), which uses the same "load under RCU, use after unlock" pattern but is protected by lock_sock() held across the function, ovpn_tcp_close() runs without the socket lock: inet_release() invokes sk_prot->close() without taking lock_sock first.
ovpn_socket_release() can therefore complete its kref_put -> detach -> synchronize_rcu -> kfree(sock) sequence concurrently, in the window after ovpn_tcp_close() drops rcu_read_lock() but before it dereferences sock->peer. The synchronize_rcu() in ovpn_socket_release() protects readers that use the dereferenced pointer inside the RCU read section, not those that escape the pointer to a local and use it afterwards.
A reproducer follows the pattern of commit 94560267d6c4 ("ovpn: tcp - don't deref NULL sk_socket member after tcp_close()"): trigger a peer removal (keepalive expiration or netlink OVPN_CMD_DEL_PEER) at the same moment userspace closes the TCP fd. That commit fixed the detach-side of the same race window; this one fixes the close-side at a different victim.
Tighten the entry block to read sock->peer exactly once into the cached peer local, and route all subsequent uses (the hold check, the ovpn_peer_del() call, and the prot->close() invocation) through that local. sock->peer is only ever written once in ovpn_socket_new() under lock_sock(), before rcu_assign_sk_user_data() publishes the ovpn_socket, and is never reassigned afterwards - but the previous multi-read pattern made that invariant implicit rather than explicit. The same multi-read shape exists in ovpn_tcp_recvmsg(), ovpn_tcp_sendmsg(), ovpn_tcp_data_ready() and ovpn_tcp_write_space(); those will be cleaned up via a dedicated helper in a follow-up net-next series.
--- drivers/net/ovpn/tcp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/net/ovpn/tcp.c +7 -2
@@ -581,14 +581,19 @@ static void ovpn_tcp_close(struct sock *sk, long timeout)rcu_read_lock (); sock =rcu_dereference_sk_user_data (sk); -if (!sock || !sock->peer || !ovpn_peer_hold (sock->peer)) { +if (!sock) {rcu_read_unlock ();return ; } + peer = sock->peer; +if (!peer || !ovpn_peer_hold (peer)) { +rcu_read_unlock (); +return ; + }rcu_read_unlock (); -ovpn_peer_del (sock->peer,OVPN_DEL_PEER_REASON_TRANSPORT_DISCONNECT ); +ovpn_peer_del (peer,OVPN_DEL_PEER_REASON_TRANSPORT_DISCONNECT ); peer->tcp.sk_cb.prot->close (sk, timeout);ovpn_peer_put (peer); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 285/377 ovpn: respect peer refcount in CMD_NEW_PEER error path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <[email protected]>
[ Upstream commit 1fef6614673ff0846d30acdeeaf3cf98bb5f6116 ]
ovpn_nl_peer_new_doit()'s error path calls ovpn_peer_release() directly rather than ovpn_peer_put(), bypassing the kref. The accompanying comment ("peer was not yet hashed, thus it is not used in any context") holds for UDP but not for TCP.
For UDP, the ovpn_socket union uses the .ovpn arm and never points back at a peer; UDP encap_recv looks up peers via the not-yet-populated hashtables, so the new peer is unreachable until ovpn_peer_add() publishes it.
For TCP, ovpn_socket_new() sets ovpn_sock->peer and ovpn_tcp_socket_attach() publishes ovpn_sock via rcu_assign_sk_user_data().
Quoted 1 line
From that moment until
ovpn_socket_release()detaches in the error path,
the TCP fd is fully wired: userspace recvmsg / sendmsg / close / poll on the fd, as well as the strparser-driven ovpn_tcp_rcv() path, can reach the peer through sk_user_data -> ovpn_sock->peer and bump its refcount via ovpn_peer_hold().
ovpn_tcp_socket_wait_finish() (called inside ovpn_socket_release()) drains strparser and the tx work, but does not synchronize with userspace syscall callers that already hold a peer reference. If ovpn_nl_peer_modify() or ovpn_peer_add() returns an error while such a caller is in flight - notably an ovpn_tcp_recvmsg() blocked in __skb_recv_datagram() on peer->tcp.user_queue - the direct ovpn_peer_release() destroys the peer while the caller still holds the reference, and the eventual ovpn_peer_put() from that caller operates on freed memory.
Replace the direct destructor call with ovpn_peer_put() so the kref correctly defers destruction until the last reference is dropped. In the common case where no concurrent user is present, behaviour is
unchanged: the kref hits zero immediately and ovpn_peer_release_kref() runs the same destructor.
With this conversion ovpn_peer_release() has no callers outside peer.c
- ovpn_peer_release_kref() in the same translation unit is the only remaining user - so make it static and drop its declaration from peer.h.
--- drivers/net/ovpn/netlink.c | 8 +++++--- drivers/net/ovpn/peer.c | 2 +- drivers/net/ovpn/peer.h | 1 - 3 files changed, 6 insertions(+), 5 deletions(-)
drivers/net/ovpn/netlink.c +5 -3
@@ -455,10 +455,12 @@ int ovpn_nl_peer_new_doit(struct sk_buff *skb, struct genl_info *info) sock_release:ovpn_socket_release (peer); peer_release: -/* release right away because peer was not yet hashed, thus it is not -* used in any context +/* For UDP, the peer is unreachable until added to the hashtables, so +* dropping the initial reference is enough. For TCP, the peer may be +* concurrently reachable via sk_user_data->peer until +* ovpn_socket_release() detaches; rely on the refcount. */ -ovpn_peer_release (peer); +ovpn_peer_put (peer);return ret; }
drivers/net/ovpn/peer.c +1 -1
@@ -348,7 +348,7 @@ static void ovpn_peer_release_rcu(struct rcu_head *head)* ovpn_peer_release - release peer private members * @peer: the peer to release */ -void ovpn_peer_release (struct ovpn_peer *peer) +static void ovpn_peer_release (struct ovpn_peer *peer) {ovpn_crypto_state_release (&peer->crypto);spin_lock_bh (&peer->lock);
drivers/net/ovpn/peer.h +0 -1
@@ -125,7 +125,6 @@ static inline bool ovpn_peer_hold(struct ovpn_peer *peer)return kref_get_unless_zero (&peer->refcount); } -void ovpn_peer_release (struct ovpn_peer *peer);void ovpn_peer_release_kref (struct kref *kref);/**
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 286/377 ovpn: fix race between deleting interface and adding new peer
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Antonio Quartulli <[email protected]>
[ Upstream commit 982422b11e6f95f766a8cd2c2b1cbdb77e234a61 ]
While deleting an existing ovpn interface, there is a very narrow window where adding a new peer via netlink may cause the netdevice to hang and prevent its unregistration.
It may happen during ovpn_dellink(), when all existing peers are freed and the device is queued for deregistration, but a CMD_PEER_NEW message comes in adding a new peer that takes again a reference to the netdev.
At this point there is no way to release the device because we are under the assumption that all peers were already released.
Fix the race condition by releasing all peers in ndo_uninit(), when the netdevice has already been removed from the netdev list.
Also ovpn_peer_add() has now an extra check that forces the function to bail out if the device reg_state is not REGISTERED. This way any incoming CMD_PEER_NEW racing with the interface deletion routine will simply stop before adding the peer.
Note that the above check happens while holding the netdev_lock to prevent racing netdev state changes.
ovpn_dellink() is now empty and can be removed.
--- drivers/net/ovpn/main.c | 12 ++---------- drivers/net/ovpn/peer.c | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 13 deletions(-)
drivers/net/ovpn/main.c +2 -10
@@ -92,6 +92,8 @@ static void ovpn_net_uninit(struct net_device *dev) {struct ovpn_priv *ovpn =netdev_priv (dev); +disable_delayed_work_sync (&ovpn->keepalive_work); +ovpn_peers_free (ovpn,NULL ,OVPN_DEL_PEER_REASON_TEARDOWN );gro_cells_destroy (&ovpn->gro_cells); }
@@ -208,15 +210,6 @@ static int ovpn_newlink(struct net_device *dev,return register_netdevice (dev); } -static void ovpn_dellink (struct net_device *dev,struct list_head *head) -{ -struct ovpn_priv *ovpn =netdev_priv (dev); - -cancel_delayed_work_sync (&ovpn->keepalive_work); -ovpn_peers_free (ovpn,NULL ,OVPN_DEL_PEER_REASON_TEARDOWN ); -unregister_netdevice_queue (dev, head); -} -static int ovpn_fill_info (struct sk_buff *skb,const struct net_device *dev) {struct ovpn_priv *ovpn =netdev_priv (dev);
@@ -235,7 +228,6 @@ static struct rtnl_link_ops ovpn_link_ops = { .policy = ovpn_policy, .maxtype = IFLA_OVPN_MAX, .newlink = ovpn_newlink, - .dellink = ovpn_dellink, .fill_info = ovpn_fill_info, };
drivers/net/ovpn/peer.c +18 -3
@@ -1029,14 +1029,29 @@ static int ovpn_peer_add_p2p(struct ovpn_priv *ovpn, struct ovpn_peer *peer)*/ int ovpn_peer_add (struct ovpn_priv *ovpn,struct ovpn_peer *peer) { +int ret = -ENODEV ; + +/* Prevent adding new peers while destroying the ovpn interface. +* Failing to do so would end up holding the device reference +* endlessly hostage of the new peer object with no chance of +* release.. +*/ +netdev_lock (ovpn->dev); +if (ovpn->dev->reg_state !=NETREG_REGISTERED ) + goto out; +switch (ovpn->mode) {case OVPN_MODE_MP : -return ovpn_peer_add_mp (ovpn, peer); + ret =ovpn_peer_add_mp (ovpn, peer); +break ;case OVPN_MODE_P2P : -return ovpn_peer_add_p2p (ovpn, peer); + ret =ovpn_peer_add_p2p (ovpn, peer); +break ; } +out: +netdev_unlock (ovpn->dev); -return -EOPNOTSUPP ; +return ret; }/**
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 287/377 gcc-plugins: Always define CONST_CAST_GIMPLE and CONST_CAST_TREE
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook <[email protected]>
[ Upstream commit 905c559e51497b8bfdbb68df8be56d2f70f0de8e ]
For gcc-16, the CONST_CAST macro family was removed. Add back what we were using in gcc-common.h, as they are simple wrappers.
See GCC commits:
c3d96ff9e916c02584aa081f03ab999292efbb50
458c7926d48959abcb2c1adaa22458e27459a551
--- scripts/gcc-plugins/gcc-common.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
scripts/gcc-plugins/gcc-common.h +3 -1
@@ -309,7 +309,9 @@ typedef const gimple *const_gimple_ptr;#define gimple gimple_ptr#define const_gimple const_gimple_ptr#undef CONST_CAST_GIMPLE -#define CONST_CAST_GIMPLE (X ) CONST_CAST(gimple, (X)) +#define CONST_CAST_GIMPLE (X ) const_cast<gimple>((X)) +#undef CONST_CAST_TREE +#define CONST_CAST_TREE (X ) const_cast<tree>((X))/* gimple related */ static inline gimple gimple_build_assign_with_ops(enum tree_code subcode, tree lhs, tree op1, tree op2 MEM_STAT_DECL)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 288/377 x86/xen: Fix xen_e820_swap_entry_with_ram()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juergen Gross <[email protected]>
[ Upstream commit 28e03f78e69cf6628b81f24777799778528a84c1 ]
When swapping a not page-aligned E820 map entry with RAM, the start address of the modified entry is calculated wrong (the offset into the page is subtracted instead of being added to the page address).
Message-ID: <[email protected]>
--- arch/x86/xen/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/xen/setup.c +1 -1
@@ -655,7 +655,7 @@ static void __init xen_e820_swap_entry_with_ram(struct e820_entry *swap_entry)/* Fill new entry (keep size and page offset). */ entry->type = swap_entry->type; entry->addr = entry_end - swap_size + - swap_addr - swap_entry->addr; + swap_entry->addr - swap_addr; entry->size = swap_entry->size;/* Convert old entry to RAM, align to pages. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 289/377 ovpn: disable BHs when updating device stats
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ralf Lici <[email protected]>
[ Upstream commit 0c0dddc07d272a8d25922e48041e8e4d2434df7e ]
ovpn updates dev->dstats from both process and softirq contexts. In particular, TCP paths may run from socket callbacks, workqueues or strparser work, while UDP receive and ovpn's ndo_start_xmit path may update the same per-device dstats from BH context.
Add ovpn device drop-stat helpers that disable BHs around dev_dstats_rx_dropped() and dev_dstats_tx_dropped(), and use them for drop accounting.
The successful RX dev_dstats_rx_add() update is already covered by the BH-disabled section around gro_cells_receive(). For the successful TCP TX dev_dstats_tx_add() update, replace the existing preempt-disabled section with a BH-disabled one.
--- drivers/net/ovpn/io.c | 12 ++++++------ drivers/net/ovpn/stats.h | 16 ++++++++++++++++ drivers/net/ovpn/tcp.c | 10 +++++----- drivers/net/ovpn/udp.c | 2 +- 4 files changed, 28 insertions(+), 12 deletions(-)
drivers/net/ovpn/io.c +6 -6
@@ -196,7 +196,7 @@ void ovpn_decrypt_post(void *data, int ret) skb =NULL ; drop:if (unlikely (skb)) -dev_dstats_rx_dropped (peer->ovpn->dev); +ovpn_dev_dstats_rx_dropped (peer->ovpn->dev);kfree_skb (skb); drop_nocount:if (likely (peer))
@@ -220,7 +220,7 @@ void ovpn_recv(struct ovpn_peer *peer, struct sk_buff *skb)net_info_ratelimited ("%s: no available key for peer %u, key-id: %u\n" ,netdev_name (peer->ovpn->dev), peer->id, key_id); -dev_dstats_rx_dropped (peer->ovpn->dev); +ovpn_dev_dstats_rx_dropped (peer->ovpn->dev);kfree_skb (skb);ovpn_peer_put (peer);return ;
@@ -298,7 +298,7 @@ void ovpn_encrypt_post(void *data, int ret)rcu_read_unlock (); err:if (unlikely (skb)) -dev_dstats_tx_dropped (peer->ovpn->dev); +ovpn_dev_dstats_tx_dropped (peer->ovpn->dev);if (likely (peer))ovpn_peer_put (peer);if (likely (ks))
@@ -340,7 +340,7 @@ static void ovpn_send(struct ovpn_priv *ovpn, struct sk_buff *skb,*/ skb_list_walk_safe(skb, curr, next) {if (unlikely (!ovpn_encrypt_one (peer, curr))) { -dev_dstats_tx_dropped (ovpn->dev); +ovpn_dev_dstats_tx_dropped (ovpn->dev);kfree_skb (curr); } }
@@ -411,7 +411,7 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev)if (unlikely (!curr)) {net_err_ratelimited ("%s: skb_share_check failed for payload packet\n" ,netdev_name (dev)); -dev_dstats_tx_dropped (ovpn->dev); +ovpn_dev_dstats_tx_dropped (ovpn->dev);continue ; }
@@ -437,7 +437,7 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev) drop:ovpn_peer_put (peer); drop_no_peer: -dev_dstats_tx_dropped (ovpn->dev); +ovpn_dev_dstats_tx_dropped (ovpn->dev);skb_tx_error (skb);kfree_skb_list (skb);return NETDEV_TX_OK ;
drivers/net/ovpn/stats.h +16 -0
@@ -11,6 +11,8 @@ #ifndef _NET_OVPN_OVPNSTATS_H_ #define _NET_OVPN_OVPNSTATS_H_ +#include <linux/netdevice.h> + /* one stat */ struct ovpn_peer_stat { atomic64_t bytes;
@@ -44,4 +46,18 @@ static inline void ovpn_peer_stats_increment_tx(struct ovpn_peer_stats *stats, ovpn_peer_stats_increment(&stats->tx, n); } +static inline void ovpn_dev_dstats_tx_dropped (struct net_device *dev) +{ +local_bh_disable (); +dev_dstats_tx_dropped (dev); +local_bh_enable (); +} + +static inline void ovpn_dev_dstats_rx_dropped (struct net_device *dev) +{ +local_bh_disable (); +dev_dstats_rx_dropped (dev); +local_bh_enable (); +} +#endif /* _NET_OVPN_OVPNSTATS_H_ */
drivers/net/ovpn/tcp.c +5 -5
@@ -152,7 +152,7 @@ static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb)if (WARN_ON (!ovpn_peer_hold (peer))) goto err_nopeer;schedule_work (&peer->tcp.defer_del_work); -dev_dstats_rx_dropped (peer->ovpn->dev); +ovpn_dev_dstats_rx_dropped (peer->ovpn->dev); err_nopeer:kfree_skb (skb); }
@@ -298,9 +298,9 @@ static void ovpn_tcp_send_sock(struct ovpn_peer *peer, struct sock *sk) }while (peer->tcp.out_msg.len >0 );if (!peer->tcp.out_msg.len) { -preempt_disable (); +local_bh_disable ();dev_dstats_tx_add (peer->ovpn->dev, skb->len); -preempt_enable (); +local_bh_enable (); }kfree_skb (peer->tcp.out_msg.skb);
@@ -331,7 +331,7 @@ static void ovpn_tcp_send_sock_skb(struct ovpn_peer *peer, struct sock *sk,ovpn_tcp_send_sock (peer, sk);if (peer->tcp.out_msg.skb) { -dev_dstats_tx_dropped (peer->ovpn->dev); +ovpn_dev_dstats_tx_dropped (peer->ovpn->dev);kfree_skb (skb);return ; }
@@ -353,7 +353,7 @@ void ovpn_tcp_send_skb(struct ovpn_peer *peer, struct sock *sk,if (sock_owned_by_user (sk)) {if (skb_queue_len (&peer->tcp.out_queue) >=READ_ONCE (net_hotdata.max_backlog)) { -dev_dstats_tx_dropped (peer->ovpn->dev); +ovpn_dev_dstats_tx_dropped (peer->ovpn->dev);kfree_skb (skb); goto unlock; }
drivers/net/ovpn/udp.c +1 -1
@@ -126,7 +126,7 @@ static int ovpn_udp_encap_recv(struct sock *sk, struct sk_buff *skb)return 0 ; drop: -dev_dstats_rx_dropped (ovpn->dev); +ovpn_dev_dstats_rx_dropped (ovpn->dev); drop_noovpn:kfree_skb (skb);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 290/377 tls: Preserve sk_err across recvmsg() when data has been copied
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit f508262ae9f21fe0e6c0749948b9dc7dd5a62a70 ]
The sk_err check in tls_rx_rec_wait() consumes the error via sock_error(), which clears sk_err atomically. When the caller (tls_sw_recvmsg, tls_sw_splice_read, or tls_sw_read_sock) already has bytes copied to userspace, it returns those bytes and discards the error from this call. sk_err is now zero on the socket, so the next read syscall observes only RCV_SHUTDOWN and reports a clean EOF instead of the actual error (typically -ECONNRESET).
The race is reachable when tls_read_flush_backlog()'s periodic sk_flush_backlog() triggers tcp_reset() in the middle of a multi-record read.
Pass a has_copied flag to tls_rx_rec_wait(). When has_copied is false, consume sk_err via sock_error() as before. When has_copied is true, report the error from READ_ONCE() but leave sk_err set:
the caller returns the byte count and discards the err from this call, and the next read syscall surfaces the preserved sk_err. This mirrors the tcp_recvmsg() preserve-and-surface pattern.
The decrypt-abort path is unaffected: tls_err_abort() raises sk_err to EBADMSG after tls_rx_rec_wait() returns, and nothing on the caller's return path consumes it, so the EBADMSG surfaces on the next read.
tls_sw_splice_read() passes has_copied=false: it processes one record per call, so no bytes have been copied within the function when tls_rx_rec_wait() runs. A reset that arrives between iterations of splice_direct_to_actor() (the sendfile() path) is still consumed by sock_error() in the later call, and the outer loop returns the prior iterations' byte count and drops the error. tcp_splice_read() exhibits the same pattern at the iteration boundary; addressing it belongs at the splice_direct_to_actor() layer and is out of scope here.
--- net/tls/tls_sw.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
net/tls/tls_sw.c +14 -6
@@ -1366,9 +1366,14 @@ void tls_sw_splice_eof(struct socket *sock)mutex_unlock (&tls_ctx->tx_lock); } +/* When has_copied is true the caller has already moved bytes to +* userspace. Report sk_err but leave it set so the next read +* surfaces it instead of a spurious EOF, otherwise sk_err is +* consumed via sock_error(). +*/ static int tls_rx_rec_wait (struct sock *sk,struct sk_psock *psock,bool nonblock, -bool released) +bool released,bool has_copied) {struct tls_context *tls_ctx =tls_get_ctx (sk);struct tls_sw_context_rx *ctx =tls_sw_ctx_rx (tls_ctx);
@@ -1386,8 +1391,11 @@ tls_rx_rec_wait(struct sock *sk, struct sk_psock *psock, bool nonblock,if (!sk_psock_queue_empty (psock))return 0 ; -if (sk->sk_err) +if (sk->sk_err) { +if (has_copied) +return -READ_ONCE (sk->sk_err);return sock_error (sk); + }if (ret <0 )return ret;
@@ -1423,7 +1431,7 @@ tls_rx_rec_wait(struct sock *sk, struct sk_psock *psock, bool nonblock, }if (unlikely (!tls_strp_msg_load (&ctx->strp, released))) -return tls_rx_rec_wait (sk, psock, nonblock, false); +return tls_rx_rec_wait (sk, psock, nonblock, false, has_copied);return 1 ; }
@@ -2111,7 +2119,7 @@ int tls_sw_recvmsg(struct sock *sk,int to_decrypt, chunk; err =tls_rx_rec_wait (sk, psock, flags &MSG_DONTWAIT , - released); + released, !!(decrypted + copied));if (err <=0 ) {if (psock) { chunk = sk_msg_recvmsg(sk, psock, msg, len,
@@ -2298,7 +2306,7 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,struct tls_decrypt_arg darg; err =tls_rx_rec_wait (sk,NULL , flags &SPLICE_F_NONBLOCK , - true); + true, false);if (err <=0 ) goto splice_read_end;
@@ -2384,7 +2392,7 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc, }else {struct tls_decrypt_arg darg; - err =tls_rx_rec_wait (sk,NULL , true, released); + err =tls_rx_rec_wait (sk,NULL , true, released, !!copied);if (err <=0 ) goto read_sock_end;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 291/377 net/mlx5: Do not restore destination-less TC rules
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeroen Massar <[email protected]>
[ Upstream commit 8d0a5af8b1ba598e7340761729801624e7a9330e ]
After IPsec policy/state TX rules are added, any TC flow rule, which forwards packets to uplink, is modified to forward to IPsec TX tables. As these tables are destroyed dynamically, whenever there is no reference to them, the destinations of this kind of rules must be restored to uplink, unless there is no destination for that rule.
The flow rules FLOW_ACTION_ACCEPT, DROP, TRAP, GOTO and SAMPLE do not have a destination port, and thus out_count = 0.
At cleanup time of the rules in mlx5_esw_ipsec_modify_flow_dests we call mlx5_eswitch_restore_ipsec_rule but as the above types do not have a destination we get an underflow of out_count, as the port is passed, which is esw_attr->out_count - 1.
This change avoids calling mlx5_eswitch_restore_ipsec_rule when there are no output destinations and thus avoids the underflow.
--- drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +2 -1
@@ -142,7 +142,8 @@ static int mlx5_esw_ipsec_modify_flow_dests(struct mlx5_eswitch *esw, attr = flow->attr; esw_attr = attr->esw_attr; -if (esw_attr->out_count - esw_attr->split_count >1 ) +if (!esw_attr->out_count || + esw_attr->out_count - esw_attr->split_count >1 )return 0 ; err = mlx5_eswitch_restore_ipsec_rule(esw, flow->rule[0], esw_attr,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 292/377 scsi: sd: Fix return code handling in sd_spinup_disk()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Christie <[email protected]>
[ Upstream commit 6ea68a8dc7d2711504d944811981a5304af7d7a9 ]
As found by smatch-ci, scsi_execute_cmd() can return negative or positve values so we should use a int instead of unsigned int.
--- drivers/scsi/sd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/scsi/sd.c +1 -2
@@ -2398,8 +2398,7 @@ sd_spinup_disk(struct scsi_disk *sdkp) {static const u8 cmd[10 ] = {TEST_UNIT_READY };unsigned long spintime_expire =0 ; -int spintime, sense_valid =0 ; -unsigned int the_result; +int the_result, spintime, sense_valid =0 ;struct scsi_sense_hdr sshdr;struct scsi_failure failure_defs[] = {/* Do not retry Medium Not Present */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 293/377 ASoC: codecs: fs210x: fix possible buffer overflow
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander A. Klimov <[email protected]>
[ Upstream commit 0d435a7ebcd4e97e47673c1ab6fb27f973a053ec ]
In fs210x_effect_scene_info(), a string was copied like this:
strscpy(DST, SRC, strlen(SRC) + 1);
A buffer overflow would happen if strlen(SRC) >= sizeof(DST). Actually, strscpy() must be used this way:
strscpy(DST, SRC, sizeof(DST));
strscpy(DST, SRC); // defaults to sizeof(DST)
--- sound/soc/codecs/fs210x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/codecs/fs210x.c +1 -1
@@ -968,7 +968,7 @@ static int fs210x_effect_scene_info(struct snd_kcontrol *kcontrol,if (scene->name) name = scene->name; -strscpy (uinfo->value.enumerated.name, name,strlen (name) +1 ); +strscpy (uinfo->value.enumerated.name, name);return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 294/377 ALSA: scarlett2: Add missing error check when initialise Autogain Status
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Robertus Diawan Chris <[email protected]>
[ Upstream commit c0e4fffc0f474b7ed10adee4ab2bc1a66d36fc72 ]
When initialise new control with scarlett2_add_new_ctl() function for Autogain Status, scarlett2_add_new_ctl() might throw an error. So, add error check after initialise new control for Autogain Status.
This is reported by Coverity Scan with CID 1598781 as UNUSED_VALUE.
--- sound/usb/mixer_scarlett2.c | 2 ++ 1 file changed, 2 insertions(+)
sound/usb/mixer_scarlett2.c +2 -0
@@ -6707,6 +6707,8 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) err =scarlett2_add_new_ctl ( mixer, &scarlett2_autogain_status_ctl, i,1 , s, &private->autogain_status_ctls[i]); +if (err <0 ) +return err; }/* Add autogain target controls */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 295/377 io_uring/net: punt IORING_OP_BIND async if it needs file create
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jens Axboe <[email protected]>
[ Upstream commit ccd25890f73c082fe2657ed227b497d6ac5fdc40 ]
For two reasons:
1) An opcode cannot block inside io_uring_enter() doing submissions, as it'll stall the submission side pipeline.
2) Ending up in sb_start_write() -> __sb_start_write() -> percpu_down_read_freezable() introduces a new lockdep edge, which it correctly complains about.
Check if the socket type is AF_UNIX and has a non-empty pathname. If it does, mark it REQ_F_FORCE_ASYNC to punt the submission to io-wq rather than attempt to do it inline.
--- io_uring/net.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
io_uring/net.c +25 -1
@@ -4,6 +4,7 @@#include <linux/file.h> #include <linux/slab.h> #include <linux/net.h> +#include <linux/un.h> #include <linux/compat.h> #include <net/compat.h> #include <linux/io_uring.h>
@@ -1837,11 +1838,29 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)return IOU_COMPLETE ; } +/* +* Check if bind request would potentially end up with filename_create(), +* which in turn end up in mnt_want_write() which will grab the fs +* percpu start write sem. This can trigger a lockdep warning. +*/ +static int io_bind_file_create (const struct io_async_msghdr *io,int addr_len) +{ +const struct sockaddr_un *sun; + +if (io->addr.ss_family !=AF_UNIX ) +return 0 ; +if (addr_len <= offsetof(struct sockaddr_un , sun_path)) +return 0 ; + sun = (const struct sockaddr_un *) &io->addr; +return sun->sun_path[0 ] !='\0' ; +} +int io_bind_prep (struct io_kiocb *req,const struct io_uring_sqe *sqe) { struct io_bind *bind = io_kiocb_to_cmd(req, struct io_bind);struct sockaddr __user *uaddr;struct io_async_msghdr *io; +int ret;if (sqe->len || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in)return -EINVAL ;
@@ -1852,7 +1871,12 @@ int io_bind_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) io =io_msg_alloc_async (req);if (unlikely (!io))return -ENOMEM ; -return move_addr_to_kernel (uaddr, bind->addr_len, &io->addr); + ret =move_addr_to_kernel (uaddr, bind->addr_len, &io->addr); +if (unlikely (ret)) +return ret; +if (io_bind_file_create (io, bind->addr_len)) + req->flags |=REQ_F_FORCE_ASYNC ; +return 0 ; }int io_bind (struct io_kiocb *req,unsigned int issue_flags)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 296/377 vsock/virtio: fix zerocopy completion for multi-skb sends
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefano Garzarella <[email protected]>
[ Upstream commit ae38d9179190a956e2a87a69ef1dd6f451b51c4d ]
When a large message is fragmented into multiple skbs, the zerocopy uarg is only allocated and attached to the last skb in the loop. Non-final skbs carry pinned user pages with no completion tracking, so the kernel has no way to notify userspace when those pages are safe to reuse. If the loop breaks early the uarg is never allocated at all, leaking pinned pages with no completion notification.
Fix this by following the approach used by TCP: allocate the zerocopy uarg (if not provided by the caller) before the send loop and attach it to every skb via skb_zcopy_set(), which takes a reference per skb. Each skb's completion properly decrements the refcount, and the notification only fires after the last skb is freed.
On failure, if no data was sent, the uarg is cleanly aborted via net_zcopy_put_abort().
This issue was initially discovered by sashiko while reviewing commit 1cb36e252211 ("vsock/virtio: fix MSG_ZEROCOPY pinned-pages accounting") but was pre-existing.
--- net/vmw_vsock/virtio_transport_common.c | 83 ++++++++++--------------- 1 file changed, 34 insertions(+), 49 deletions(-)
net/vmw_vsock/virtio_transport_common.c +34 -49
@@ -72,34 +72,6 @@ static bool virtio_transport_can_zcopy(const struct virtio_transport *t_ops,return true; } -static int virtio_transport_init_zcopy_skb (struct vsock_sock *vsk, -struct sk_buff *skb, -struct msghdr *msg, -size_t pkt_len, -bool zerocopy) -{ -struct ubuf_info *uarg; - -if (msg->msg_ubuf) { - uarg = msg->msg_ubuf; -net_zcopy_get (uarg); - }else { -struct ubuf_info_msgzc *uarg_zc; - - uarg =msg_zerocopy_realloc (sk_vsock (vsk), - pkt_len,NULL , false); -if (!uarg) -return -1 ; - - uarg_zc =uarg_to_msgzc (uarg); - uarg_zc->zerocopy = zerocopy ?1 :0 ; - } - -skb_zcopy_init (skb, uarg); - -return 0 ; -} - static int virtio_transport_fill_skb(struct sk_buff *skb, struct virtio_vsock_pkt_info *info, size_t len,
@@ -319,8 +291,10 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,u32 src_cid, src_port, dst_cid, dst_port;const struct virtio_transport *t_ops;struct virtio_vsock_sock *vvs; +struct ubuf_info *uarg =NULL ;u32 pkt_len = info->pkt_len;bool can_zcopy = false; +bool have_uref = false;u32 rest_len;int ret;
@@ -362,6 +336,25 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,if (can_zcopy) max_skb_len =min_t (u32,VIRTIO_VSOCK_MAX_PKT_BUF_SIZE , (MAX_SKB_FRAGS *PAGE_SIZE )); + +if (info->msg->msg_flags &MSG_ZEROCOPY && + info->op ==VIRTIO_VSOCK_OP_RW ) { + uarg = info->msg->msg_ubuf; + +if (!uarg) { + uarg =msg_zerocopy_realloc (sk_vsock (vsk), + pkt_len,NULL , false); +if (!uarg) { +virtio_transport_put_credit (vvs, pkt_len); +return -ENOMEM ; + } + +if (!can_zcopy) +uarg_to_msgzc (uarg)->zerocopy =0 ; + + have_uref = true; + } + } } rest_len = pkt_len;
@@ -380,27 +373,7 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,break ; } -/* We process buffer part by part, allocating skb on -* each iteration. If this is last skb for this buffer -* and MSG_ZEROCOPY mode is in use - we must allocate -* completion for the current syscall. -* -* Pass pkt_len because msg iter is already consumed -* by virtio_transport_fill_skb(), so iter->count -* can not be used for RLIMIT_MEMLOCK pinned-pages -* accounting done by msg_zerocopy_realloc(). -*/ -if (info->msg && info->msg->msg_flags &MSG_ZEROCOPY && - skb_len == rest_len && info->op ==VIRTIO_VSOCK_OP_RW ) { -if (virtio_transport_init_zcopy_skb (vsk, skb, - info->msg, - pkt_len, - can_zcopy)) { -kfree_skb (skb); - ret = -ENOMEM ; -break ; - } - } +skb_zcopy_set (skb, uarg,NULL );virtio_transport_inc_tx_pkt (vvs, skb);
@@ -424,6 +397,18 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,virtio_transport_put_credit (vvs, rest_len); +/* msg_zerocopy_realloc() initializes the ubuf_info refcnt to 1. +* skb_zcopy_set() increases it for each skb, so we can drop that +* initial reference to keep it balanced. +*/ +if (have_uref) { +if (rest_len == pkt_len) +/* No data sent, abort the notification. */ +net_zcopy_put_abort (uarg, true); +else +net_zcopy_put (uarg); + } +/* Return number of bytes, if any data has been sent. */ if (rest_len != pkt_len) ret = pkt_len - rest_len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 297/377 btrfs: add macros to facilitate printing of keys
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
[ Upstream commit 95de4b097e25225d4deb5a33a4bfc27bb441f2d8 ]
There's a lot of places where we need to print a key, and it's tiresome to type the format specifier, typically "(%llu %u %llu)", as well as passing 3 arguments to a prink family function (key->objectid, key->type, key->offset).
So add a couple macros for this just like we have for csum values in btrfs_inode.h (CSUM_FMT and CSUM_FMT_VALUE).
This also ensures that we consistently print a key in the same format, always as "(%llu %llu %llu)", which is the most common format we use, but we have a few variations such as "[%llu %llu %llu]" for no good reason.
This patch introduces the macros while the next one makes use of it. This is to ease backports of future patches, since then we can backport this patch which is simple and short and then backport those future patches, as the next patch in the series that makes use of these new macros is quite large and may have some dependencies.
Stable-dep-of: 1e92637722ae ("btrfs: check for subvolume before deleting squota qgroup")
--- fs/btrfs/fs.h | 3 +++ 1 file changed, 3 insertions(+)
fs/btrfs/fs.h +3 -0
@@ -73,6 +73,9 @@ struct btrfs_space_info;#define BTRFS_SUPER_INFO_SIZE 4096static_assert (sizeof (struct btrfs_super_block ) ==BTRFS_SUPER_INFO_SIZE ); +#define BTRFS_KEY_FMT "(%llu %u %llu)" +#define BTRFS_KEY_FMT_VALUE (key) (key)->objectid, (key)->type, (key)->offset +/* * Number of metadata items necessary for an unlink operation: *
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 298/377 btrfs: use the key format macros when printing keys
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
[ Upstream commit af1e800c0244a04f5eb0993745c23d974f262628 ]
Change all locations that print a key to use the new macros to print them in order to ensure a consistent style and avoid repetitive code.
Stable-dep-of: 1e92637722ae ("btrfs: check for subvolume before deleting squota qgroup")
--- fs/btrfs/backref.c | 11 +++++------ fs/btrfs/ctree.c | 17 +++++++---------- fs/btrfs/extent-tree.c | 14 +++++++------- fs/btrfs/inode.c | 4 ++-- fs/btrfs/print-tree.c | 14 ++++++-------- fs/btrfs/qgroup.c | 6 ++---- fs/btrfs/relocation.c | 4 ++-- fs/btrfs/root-tree.c | 4 ++-- fs/btrfs/send.c | 10 ++++------ fs/btrfs/tree-checker.c | 21 +++++++++------------ fs/btrfs/tree-log.c | 38 ++++++++++++++++++-------------------- 11 files changed, 64 insertions(+), 79 deletions(-)
fs/btrfs/backref.c +5 -6
@@ -666,10 +666,9 @@ static int resolve_indirect_ref(struct btrfs_backref_walk_ctx *ctx, ret =btrfs_search_old_slot (root, &search_key, path, ctx->time_seq);btrfs_debug (ctx->fs_info, -"search slot in root %llu (level %d, ref count %d) returned %d for key (%llu %u %llu)" , - ref->root_id, level, ref->count, ret, - ref->key_for_search.objectid, ref->key_for_search.type, - ref->key_for_search.offset); +"search slot in root %llu (level %d, ref count %d) returned %d for key " BTRFS_KEY_FMT , + ref->root_id, level, ref->count, ret, +BTRFS_KEY_FMT_VALUE (&ref->key_for_search));if (ret <0 ) goto out;
@@ -3323,9 +3322,9 @@ static int handle_indirect_tree_backref(struct btrfs_trans_handle *trans, eb = path->nodes[level];if (btrfs_node_blockptr (eb, path->slots[level]) != cur->bytenr) {btrfs_err (fs_info, -"couldn't find block (%llu) (level %d) in tree (%llu) with key (%llu %u %llu)" , +"couldn't find block (%llu) (level %d) in tree (%llu) with key " BTRFS_KEY_FMT , cur->bytenr, level -1 ,btrfs_root_id (root), - tree_key->objectid, tree_key->type, tree_key->offset); +BTRFS_KEY_FMT_VALUE (tree_key));btrfs_put_root (root); ret = -ENOENT ; goto out;
fs/btrfs/ctree.c +7 -10
@@ -2599,12 +2599,11 @@ void btrfs_set_item_key_safe(struct btrfs_trans_handle *trans,if (unlikely (btrfs_comp_keys (&disk_key, new_key) >=0 )) {btrfs_print_leaf (eb);btrfs_crit (fs_info, -"slot %u key (%llu %u %llu) new key (%llu %u %llu)" , +"slot %u key " BTRFS_KEY_FMT " new key " BTRFS_KEY_FMT , slot,btrfs_disk_key_objectid (&disk_key),btrfs_disk_key_type (&disk_key),btrfs_disk_key_offset (&disk_key), - new_key->objectid, new_key->type, - new_key->offset); +BTRFS_KEY_FMT_VALUE (new_key));BUG (); } }
@@ -2613,12 +2612,11 @@ void btrfs_set_item_key_safe(struct btrfs_trans_handle *trans,if (unlikely (btrfs_comp_keys (&disk_key, new_key) <=0 )) {btrfs_print_leaf (eb);btrfs_crit (fs_info, -"slot %u key (%llu %u %llu) new key (%llu %u %llu)" , +"slot %u key " BTRFS_KEY_FMT " new key " BTRFS_KEY_FMT , slot,btrfs_disk_key_objectid (&disk_key),btrfs_disk_key_type (&disk_key),btrfs_disk_key_offset (&disk_key), - new_key->objectid, new_key->type, - new_key->offset); +BTRFS_KEY_FMT_VALUE (new_key));BUG (); } }
@@ -2677,10 +2675,9 @@ static bool check_sibling_keys(const struct extent_buffer *left,btrfs_crit (left->fs_info,"right extent buffer:" );btrfs_print_tree (right, false);btrfs_crit (left->fs_info, -"bad key order, sibling blocks, left last (%llu %u %llu) right first (%llu %u %llu)" , - left_last.objectid, left_last.type, - left_last.offset, right_first.objectid, - right_first.type, right_first.offset); +"bad key order, sibling blocks, left last " BTRFS_KEY_FMT " right first " BTRFS_KEY_FMT , +BTRFS_KEY_FMT_VALUE (&left_last), +BTRFS_KEY_FMT_VALUE (&right_first));return true; }return false;
fs/btrfs/extent-tree.c +7 -7
@@ -165,8 +165,8 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,if (unlikely (num_refs ==0 )) { ret = -EUCLEAN ;btrfs_err (fs_info, -"unexpected zero reference count for extent item (%llu %u %llu)" , - key.objectid, key.type, key.offset); +"unexpected zero reference count for extent item " BTRFS_KEY_FMT , +BTRFS_KEY_FMT_VALUE (&key));btrfs_abort_transaction (trans, ret);return ret; }
@@ -597,8 +597,8 @@ static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans, num_refs =btrfs_shared_data_ref_count (leaf, ref2); }else {btrfs_err (trans->fs_info, -"unrecognized backref key (%llu %u %llu)" , - key.objectid, key.type, key.offset); +"unrecognized backref key " BTRFS_KEY_FMT , +BTRFS_KEY_FMT_VALUE (&key));btrfs_abort_transaction (trans, -EUCLEAN );return -EUCLEAN ; }
@@ -3324,9 +3324,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,if (iref) {if (unlikely (path->slots[0 ] != extent_slot)) {abort_and_dump (trans, path, -"invalid iref, extent item key (%llu %u %llu) slot %u doesn't have wanted iref" , - key.objectid, key.type, - key.offset, path->slots[0 ]); +"invalid iref, extent item key " BTRFS_KEY_FMT " slot %u doesn't have wanted iref" , +BTRFS_KEY_FMT_VALUE (&key), + path->slots[0 ]); ret = -EUCLEAN ; goto out; }
fs/btrfs/inode.c +2 -2
@@ -5668,9 +5668,9 @@ static int btrfs_inode_by_name(struct btrfs_inode *dir, struct dentry *dentry, location->type != BTRFS_ROOT_ITEM_KEY)) { ret = -EUCLEAN ;btrfs_warn (root->fs_info, -"%s gets something invalid in DIR_ITEM (name %s, directory ino %llu, location(%llu %u %llu))" , +"%s gets something invalid in DIR_ITEM (name %s, directory ino %llu, location " BTRFS_KEY_FMT ")" , __func__, fname.disk_name.name,btrfs_ino (dir), - location->objectid, location->type, location->offset); +BTRFS_KEY_FMT_VALUE (location)); }if (!ret) *type =btrfs_dir_ftype (path->nodes[0 ], di);
fs/btrfs/print-tree.c +6 -8
@@ -131,7 +131,7 @@ static void print_extent_item(const struct extent_buffer *eb, int slot, int typestruct btrfs_tree_block_info *info; info = (struct btrfs_tree_block_info *)(ei +1 );btrfs_tree_block_key (eb, info, &key); -pr_info ("\t\ttree block key (%llu %u %llu) level %d\n" , +pr_info ("\t\ttree block key " BTRFS_KEY_FMT " level %d\n" ,btrfs_disk_key_objectid (&key), key.type,btrfs_disk_key_offset (&key),btrfs_tree_block_level (eb, info));
@@ -277,9 +277,8 @@ static void print_dir_item(const struct extent_buffer *eb, int i)struct btrfs_key location;btrfs_dir_item_key_to_cpu (eb, di, &location); -pr_info ("\t\tlocation key (%llu %u %llu) type %d\n" , - location.objectid, location.type, location.offset, -btrfs_dir_ftype (eb, di)); +pr_info ("\t\tlocation key " BTRFS_KEY_FMT " type %d\n" , +BTRFS_KEY_FMT_VALUE (&location),btrfs_dir_ftype (eb, di));pr_info ("\t\ttransid %llu data_len %u name_len %u\n" ,btrfs_dir_transid (eb, di), data_len, name_len); di = (struct btrfs_dir_item *)((char *)di + len);
@@ -598,10 +597,9 @@ void btrfs_print_tree(const struct extent_buffer *c, bool follow)print_eb_refs_lock (c);for (i =0 ; i < nr; i++) {btrfs_node_key_to_cpu (c, &key, i); -pr_info ("\tkey %d (%llu %u %llu) block %llu gen %llu\n" , - i, key.objectid, key.type, key.offset, -btrfs_node_blockptr (c, i), -btrfs_node_ptr_generation (c, i)); +pr_info ("\tkey %d " BTRFS_KEY_FMT " block %llu gen %llu\n" , + i,BTRFS_KEY_FMT_VALUE (&key),btrfs_node_blockptr (c, i), +btrfs_node_ptr_generation (c, i)); }if (!follow)return ;
fs/btrfs/qgroup.c +2 -4
@@ -3734,10 +3734,8 @@ static int qgroup_rescan_leaf(struct btrfs_trans_handle *trans, path, 1, 0);btrfs_debug (fs_info, -"current progress key (%llu %u %llu), search_slot ret %d" , - fs_info->qgroup_rescan_progress.objectid, - fs_info->qgroup_rescan_progress.type, - fs_info->qgroup_rescan_progress.offset, ret); +"current progress key " BTRFS_KEY_FMT ", search_slot ret %d" , +BTRFS_KEY_FMT_VALUE (&fs_info->qgroup_rescan_progress), ret);if (ret) {/*
fs/btrfs/relocation.c +2 -2
@@ -615,8 +615,8 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,btrfs_disk_key_to_cpu (&cpu_key, &root->root_item.drop_progress);btrfs_err (fs_info, -"cannot relocate partially dropped subvolume %llu, drop progress key (%llu %u %llu)" , - objectid, cpu_key.objectid, cpu_key.type, cpu_key.offset); +"cannot relocate partially dropped subvolume %llu, drop progress key " BTRFS_KEY_FMT , + objectid,BTRFS_KEY_FMT_VALUE (&cpu_key)); ret = -EUCLEAN ; goto fail; }
fs/btrfs/root-tree.c +2 -2
@@ -147,8 +147,8 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_rootif (unlikely (ret >0 )) {btrfs_crit (fs_info, -"unable to find root key (%llu %u %llu) in tree %llu" , - key->objectid, key->type, key->offset,btrfs_root_id (root)); +"unable to find root key " BTRFS_KEY_FMT " in tree %llu" , +BTRFS_KEY_FMT_VALUE (key),btrfs_root_id (root)); ret = -EUCLEAN ;btrfs_abort_transaction (trans, ret);return ret;
fs/btrfs/send.c +4 -6
@@ -1053,10 +1053,8 @@ static int iterate_inode_ref(struct btrfs_root *root, struct btrfs_path *path, }if (unlikely (start < p->buf)) {btrfs_err (root->fs_info, -"send: path ref buffer underflow for key (%llu %u %llu)" , - found_key->objectid, - found_key->type, - found_key->offset); +"send: path ref buffer underflow for key " BTRFS_KEY_FMT , +BTRFS_KEY_FMT_VALUE (found_key)); ret = -EINVAL ; goto out; }
@@ -7276,8 +7274,8 @@ static int search_key_again(const struct send_ctx *sctx,if (unlikely (ret >0 )) {btrfs_print_tree (path->nodes[path->lowest_level], false);btrfs_err (root->fs_info, -"send: key (%llu %u %llu) not found in %s root %llu, lowest_level %d, slot %d" , - key->objectid, key->type, key->offset, +"send: key " BTRFS_KEY_FMT " not found in %s root %llu, lowest_level %d, slot %d" , +BTRFS_KEY_FMT_VALUE (key), (root == sctx->parent_root ?"parent" :"send" ),btrfs_root_id (root), path->lowest_level, path->slots[path->lowest_level]);
fs/btrfs/tree-checker.c +9 -12
@@ -1635,10 +1635,9 @@ static int check_extent_item(struct extent_buffer *leaf,if (unlikely (prev_end > key->objectid)) {extent_err (leaf, slot, -"previous extent [%llu %u %llu] overlaps current extent [%llu %u %llu]" , - prev_key->objectid, prev_key->type, - prev_key->offset, key->objectid, key->type, - key->offset); +"previous extent " BTRFS_KEY_FMT " overlaps current extent " BTRFS_KEY_FMT , +BTRFS_KEY_FMT_VALUE (prev_key), +BTRFS_KEY_FMT_VALUE (key));return -EUCLEAN ; } }
@@ -2077,10 +2076,9 @@ enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf)/* Make sure the keys are in the right order */ if (unlikely (btrfs_comp_cpu_keys (&prev_key, &key) >=0 )) {generic_err (leaf, slot, -"bad key order, prev (%llu %u %llu) current (%llu %u %llu)" , - prev_key.objectid, prev_key.type, - prev_key.offset, key.objectid, key.type, - key.offset); +"bad key order, prev " BTRFS_KEY_FMT " current " BTRFS_KEY_FMT , +BTRFS_KEY_FMT_VALUE (&prev_key), +BTRFS_KEY_FMT_VALUE (&key));return BTRFS_TREE_BLOCK_BAD_KEY_ORDER ; }
@@ -2198,10 +2196,9 @@ enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node)if (unlikely (btrfs_comp_cpu_keys (&key, &next_key) >=0 )) {generic_err (node, slot, -"bad key order, current (%llu %u %llu) next (%llu %u %llu)" , - key.objectid, key.type, key.offset, - next_key.objectid, next_key.type, - next_key.offset); +"bad key order, current " BTRFS_KEY_FMT " next " BTRFS_KEY_FMT , +BTRFS_KEY_FMT_VALUE (&key), +BTRFS_KEY_FMT_VALUE (&next_key));return BTRFS_TREE_BLOCK_BAD_KEY_ORDER ; } }
fs/btrfs/tree-log.c +18 -20
@@ -199,9 +199,9 @@ static void do_abort_log_replay(struct walk_control *wc, const char *function,if (wc->log_leaf) {btrfs_crit (fs_info, -"log tree (for root %llu) leaf currently being processed (slot %d key %llu %u %llu):" , +"log tree (for root %llu) leaf currently being processed (slot %d key " BTRFS_KEY_FMT "):" ,btrfs_root_id (wc->root), wc->log_slot, - wc->log_key.objectid, wc->log_key.type, wc->log_key.offset); +BTRFS_KEY_FMT_VALUE (&wc->log_key));btrfs_print_leaf (wc->log_leaf); }
@@ -511,9 +511,9 @@ static int overwrite_item(struct walk_control *wc) ret =btrfs_search_slot (NULL , root, &wc->log_key, wc->subvol_path,0 ,0 );if (ret <0 ) {btrfs_abort_log_replay (wc, ret, -"failed to search subvolume tree for key (%llu %u %llu) root %llu" , - wc->log_key.objectid, wc->log_key.type, - wc->log_key.offset,btrfs_root_id (root)); +"failed to search subvolume tree for key " BTRFS_KEY_FMT " root %llu" , +BTRFS_KEY_FMT_VALUE (&wc->log_key), +btrfs_root_id (root));return ret; }
@@ -619,9 +619,8 @@ static int overwrite_item(struct walk_control *wc)btrfs_extend_item (trans, wc->subvol_path, item_size - found_size); }else if (ret) {btrfs_abort_log_replay (wc, ret, -"failed to insert item for key (%llu %u %llu)" , - wc->log_key.objectid, wc->log_key.type, - wc->log_key.offset); +"failed to insert item for key " BTRFS_KEY_FMT , +BTRFS_KEY_FMT_VALUE (&wc->log_key));return ret; } dst_ptr =btrfs_item_ptr_offset (dst_eb, dst_slot);
@@ -830,9 +829,9 @@ static noinline int replay_one_extent(struct walk_control *wc) &wc->log_key, sizeof(*item));if (ret) {btrfs_abort_log_replay (wc, ret, -"failed to insert item with key (%llu %u %llu) root %llu" , - wc->log_key.objectid, wc->log_key.type, - wc->log_key.offset,btrfs_root_id (root)); +"failed to insert item with key " BTRFS_KEY_FMT " root %llu" , +BTRFS_KEY_FMT_VALUE (&wc->log_key), +btrfs_root_id (root)); goto out; } dest_offset = btrfs_item_ptr_offset(wc->subvol_path->nodes[0],
@@ -1349,9 +1348,9 @@ static inline int __add_inode_ref(struct walk_control *wc, ret =btrfs_search_slot (NULL , root, &search_key, wc->subvol_path,0 ,0 );if (ret <0 ) {btrfs_abort_log_replay (wc, ret, -"failed to search subvolume tree for key (%llu %u %llu) root %llu" , - search_key.objectid, search_key.type, - search_key.offset,btrfs_root_id (root)); +"failed to search subvolume tree for key " BTRFS_KEY_FMT " root %llu" , +BTRFS_KEY_FMT_VALUE (&search_key), +btrfs_root_id (root));return ret; }else if (ret ==0 ) {/*
@@ -1484,9 +1483,9 @@ static int unlink_old_inode_refs(struct walk_control *wc, struct btrfs_inode *in }if (ret <0 ) {btrfs_abort_log_replay (wc, ret, -"failed to search subvolume tree for key (%llu %u %llu) root %llu" , - wc->log_key.objectid, wc->log_key.type, - wc->log_key.offset,btrfs_root_id (root)); +"failed to search subvolume tree for key " BTRFS_KEY_FMT " root %llu" , +BTRFS_KEY_FMT_VALUE (&wc->log_key), +btrfs_root_id (root)); goto out; }
@@ -2701,10 +2700,9 @@ static noinline int replay_dir_deletes(struct walk_control *wc, wc->subvol_path, 0, 0);if (ret <0 ) {btrfs_abort_log_replay (wc, ret, -"failed to search root %llu for key (%llu %u %llu)" , +"failed to search root %llu for key " BTRFS_KEY_FMT ,btrfs_root_id (root), - dir_key.objectid, dir_key.type, - dir_key.offset); +BTRFS_KEY_FMT_VALUE (&dir_key)); goto out; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 299/377 btrfs: dont search back for dir inode item in INO_LOOKUP_USER
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
[ Upstream commit 70085399b1a1623ef488d96b4c2d0c67be1d0607 ]
We don't need to search back to the inode item, the directory inode number is in key.offset, so simply use that. If we can't find the directory we'll get an ENOENT at the iget().
Note: The patch was taken from v5 of fscrypt patchset
(https://lore.kernel.org/linux-btrfs/[email protected]/)
which was handled over time by various people: Omar Sandoval, Sweet Tea Dorminy, Josef Bacik.
Stable-dep-of: 1e92637722ae ("btrfs: check for subvolume before deleting squota qgroup")
--- fs/btrfs/ioctl.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-)
fs/btrfs/ioctl.c +3 -20
@@ -1832,7 +1832,7 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap,struct btrfs_root_ref *rref;struct btrfs_root *root =NULL ;struct btrfs_path *path; -struct btrfs_key key, key2; +struct btrfs_key key;struct extent_buffer *leaf;char *ptr;int slot;
@@ -1887,24 +1887,6 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap,read_extent_buffer (leaf, ptr, (unsigned long )(iref +1 ), len); -/* Check the read+exec permission of this directory */ - ret =btrfs_previous_item (root, path, dirid, -BTRFS_INODE_ITEM_KEY ); -if (ret <0 ) { - goto out_put; - }else if (ret >0 ) { - ret = -ENOENT ; - goto out_put; - } - - leaf = path->nodes[0 ]; - slot = path->slots[0 ]; -btrfs_item_key_to_cpu (leaf, &key2, slot); -if (key2.objectid != dirid) { - ret = -ENOENT ; - goto out_put; - } -/* * We don't need the path anymore, so release it and * avoid deadlocks and lockdep warnings in case
@@ -1912,11 +1894,12 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap,* btree and lock the same leaf. */ btrfs_release_path (path); - temp_inode =btrfs_iget (key2.objectid, root); + temp_inode =btrfs_iget (key.offset, root);if (IS_ERR (temp_inode)) { ret =PTR_ERR (temp_inode); goto out_put; } +/* Check the read+exec permission of this directory. */ ret =inode_permission (idmap, &temp_inode->vfs_inode,MAY_READ |MAY_EXEC );iput (&temp_inode->vfs_inode);
Signature · 1 line
2.53.0
Re: [PATCH 6.18 299/377] btrfs: dont search back for dir inode item in INO_LOOKUP_USER
Quoted 2 lines · Greg Kroah-Hartman
6.18-stable review patch. If anyone has any objections, please let me know.
Hi Greg.
This is not a bugfix, rather, it is a cleanup.
Even though it's kinda small and limited to a single function, I'm not sure it's worth the stable backport.
Is there any specific reason you picked this patch?
--nX
Quoted 81 lines
------------------
From: Josef Bacik <[email protected]>
[ Upstream commit
70085399b1a1623ef488d96b4c2d0c67be1d0607]We don't need to search back to the inode item, the directory inode number is in key.offset, so simply use that. If we can't find the directory we'll get an ENOENT at the
iget().Note: The patch was taken from v5 of fscrypt patchset
(https://lore.kernel.org/linux-btrfs/[email protected]/)
which was handled over time by various people: Omar Sandoval, Sweet Tea Dorminy, Josef Bacik.Reviewed-by Johannes Thumshirn <[email protected]>Signed-off-by Josef Bacik <[email protected]>Signed-off-by Daniel Vacek <[email protected]>Reviewed-by David Sterba <[email protected]>[ add note ]Signed-off-by David Sterba <[email protected]>Stable-dep-of:
1e92637722ae("btrfs: check for subvolume before deleting squota qgroup")Signed-off-by Sasha Levin <[email protected]>--- fs/btrfs/ioctl.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-)fs/btrfs/ioctl.c +3
-21@@ -1832,7 +1832,7 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap,struct btrfs_root_ref *rref;struct btrfs_root *root =NULL ;struct btrfs_path *path; -struct btrfs_key key, key2; +struct btrfs_key key;struct extent_buffer *leaf;char *ptr;int slot;@@ -1887,24 +1887,6 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap,read_extent_buffer (leaf, ptr, (unsigned long )(iref +1 ), len); -/* Check the read+exec permission of this directory */ - ret =btrfs_previous_item (root, path, dirid, -BTRFS_INODE_ITEM_KEY ); -if (ret <0 ) { - goto out_put; - }else if (ret >0 ) { - ret = -ENOENT ; - goto out_put; - } - - leaf = path->nodes[0 ]; - slot = path->slots[0 ]; -btrfs_item_key_to_cpu (leaf, &key2, slot); -if (key2.objectid != dirid) { - ret = -ENOENT ; - goto out_put; - } -/* * We don't need the path anymore, so release it and * avoid deadlocks and lockdep warnings in case @@ -1912,11 +1894,12 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap,* btree and lock the same leaf. */ btrfs_release_path (path); - temp_inode =btrfs_iget (key2.objectid, root); + temp_inode =btrfs_iget (key.offset, root);if (IS_ERR (temp_inode)) { ret =PTR_ERR (temp_inode); goto out_put; } +/* Check the read+exec permission of this directory. */ ret =inode_permission (idmap, &temp_inode->vfs_inode,MAY_READ |MAY_EXEC );iput (&temp_inode->vfs_inode); --2.53.0
Sasha Levin
maintainerRe: [PATCH 6.18 299/377] btrfs: dont search back for dir inode item in INO_LOOKUP_USER
Quoted 4 lines · Daniel Vacek
This is not a bugfix, rather, it is a cleanup.
Even though it's kinda small and limited to a single function, I'm not sure it's worth the stable backport.
Is there any specific reason you picked this patch?
You're right that it's a cleanup on its own. It wasn't selected as a standalone backport - it was pulled in as a dependency (it carries
Stable-dep-of: 1e92637722ae "btrfs: check for subvolume before deleting squota qgroup") so that the squota qgroup fix applies cleanly.
--
Thanks,
Sasha
Re: [PATCH 6.18 299/377] btrfs: dont search back for dir inode item in INO_LOOKUP_USER
Quoted 10 lines · Sasha Levin
Quoted 4 lines · Daniel Vacek
This is not a bugfix, rather, it is a cleanup.
Even though it's kinda small and limited to a single function, I'm not sure it's worth the stable backport.
Is there any specific reason you picked this patch?You're right that it's a cleanup on its own. It wasn't selected as a standalone backport - it was pulled in as a dependency (it carries
Stable-dep-of:1e92637722ae"btrfs: check for subvolume before deleting squota qgroup") so that the squota qgroup fix applies cleanly.
Nah, right. My bad, I missed that. Sorry about the noise.
--nX
Quoted 3 lines
--
Thanks,
Sasha
Greg Kroah-Hartman
maintainerPATCH 300/377 btrfs: remaining BTRFS_PATH_AUTO_FREE conversions
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
[ Upstream commit 10934c131f9bcfb616dd8be9456f11efd6b240ec ]
Do the remaining btrfs_path conversion to the auto cleaning, this seems to be the last one. Most of the conversions are trivial, only adding the declaration and removing the freeing, or changing the goto patterns to return.
There are some functions with many changes, like __btrfs_free_extent(), btrfs_remove_from_free_space_tree() or btrfs_add_to_free_space_tree() but it still follows the same pattern.
Stable-dep-of: 1e92637722ae ("btrfs: check for subvolume before deleting squota qgroup")
--- fs/btrfs/block-group.c | 3 +- fs/btrfs/dir-item.c | 3 +- fs/btrfs/extent-tree.c | 41 +++++------ fs/btrfs/free-space-tree.c | 29 ++++---- fs/btrfs/inode-item.c | 3 +- fs/btrfs/inode.c | 3 +- fs/btrfs/ioctl.c | 37 ++++------ fs/btrfs/qgroup.c | 142 ++++++++++++++----------------------- fs/btrfs/super.c | 10 +-- fs/btrfs/tree-log.c | 4 +- fs/btrfs/volumes.c | 3 +- fs/btrfs/xattr.c | 3 +- 12 files changed, 105 insertions(+), 176 deletions(-)
fs/btrfs/block-group.c +1 -2
@@ -1065,7 +1065,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, struct btrfs_chunk_map *map) {struct btrfs_fs_info *fs_info = trans->fs_info; -struct btrfs_path *path; +BTRFS_PATH_AUTO_FREE (path);struct btrfs_block_group *block_group;struct btrfs_free_cluster *cluster;struct inode *inode;
@@ -1305,7 +1305,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,btrfs_put_block_group (block_group);if (remove_rsv)btrfs_dec_delayed_refs_rsv_bg_updates (fs_info); -btrfs_free_path (path);return ret; }
fs/btrfs/dir-item.c +1 -2
@@ -112,7 +112,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans,int ret =0 ;int ret2 =0 ;struct btrfs_root *root = dir->root; -struct btrfs_path *path; +BTRFS_PATH_AUTO_FREE (path);struct btrfs_dir_item *dir_item;struct extent_buffer *leaf;unsigned long name_ptr;
@@ -164,7 +164,6 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, ret2 =btrfs_insert_delayed_dir_index (trans, name->name, name->len, dir, &disk_key, type, index); out_free: -btrfs_free_path (path);if (ret)return ret;if (ret2)
fs/btrfs/extent-tree.c +16 -25
139 lines not on this page · raw message
fs/btrfs/free-space-tree.c +13 -16
@@ -841,7 +841,7 @@ int btrfs_remove_from_free_space_tree(struct btrfs_trans_handle *trans, u64 start, u64 size) {struct btrfs_block_group *block_group; -struct btrfs_path *path; +BTRFS_PATH_AUTO_FREE (path);int ret;if (!btrfs_fs_compat_ro (trans->fs_info,FREE_SPACE_TREE ))
@@ -851,7 +851,7 @@ int btrfs_remove_from_free_space_tree(struct btrfs_trans_handle *trans,if (unlikely (!path)) { ret = -ENOMEM ;btrfs_abort_transaction (trans, ret); - goto out; +return ret; } block_group =btrfs_lookup_block_group (trans->fs_info, start);
@@ -859,7 +859,7 @@ int btrfs_remove_from_free_space_tree(struct btrfs_trans_handle *trans,DEBUG_WARN ("no block group found for start=%llu" , start); ret = -ENOENT ;btrfs_abort_transaction (trans, ret); - goto out; +return ret; }mutex_lock (&block_group->free_space_lock);
@@ -869,8 +869,7 @@ int btrfs_remove_from_free_space_tree(struct btrfs_trans_handle *trans,btrfs_abort_transaction (trans, ret);btrfs_put_block_group (block_group); -out: -btrfs_free_path (path); +return ret; }
@@ -1023,7 +1022,7 @@ int btrfs_add_to_free_space_tree(struct btrfs_trans_handle *trans, u64 start, u64 size) {struct btrfs_block_group *block_group; -struct btrfs_path *path; +BTRFS_PATH_AUTO_FREE (path);int ret;if (!btrfs_fs_compat_ro (trans->fs_info,FREE_SPACE_TREE ))
@@ -1033,7 +1032,7 @@ int btrfs_add_to_free_space_tree(struct btrfs_trans_handle *trans,if (unlikely (!path)) { ret = -ENOMEM ;btrfs_abort_transaction (trans, ret); - goto out; +return ret; } block_group =btrfs_lookup_block_group (trans->fs_info, start);
@@ -1041,7 +1040,7 @@ int btrfs_add_to_free_space_tree(struct btrfs_trans_handle *trans,DEBUG_WARN ("no block group found for start=%llu" , start); ret = -ENOENT ;btrfs_abort_transaction (trans, ret); - goto out; +return ret; }mutex_lock (&block_group->free_space_lock);
@@ -1051,8 +1050,7 @@ int btrfs_add_to_free_space_tree(struct btrfs_trans_handle *trans,btrfs_abort_transaction (trans, ret);btrfs_put_block_group (block_group); -out: -btrfs_free_path (path); +return ret; }
@@ -1466,7 +1464,7 @@ int btrfs_remove_block_group_free_space(struct btrfs_trans_handle *trans, struct btrfs_block_group *block_group) {struct btrfs_root *root =btrfs_free_space_root (block_group); -struct btrfs_path *path; +BTRFS_PATH_AUTO_FREE (path);struct btrfs_key key, found_key;struct extent_buffer *leaf;u64 start, end;
@@ -1485,7 +1483,7 @@ int btrfs_remove_block_group_free_space(struct btrfs_trans_handle *trans,if (unlikely (!path)) { ret = -ENOMEM ;btrfs_abort_transaction (trans, ret); - goto out; +return ret; } start = block_group->start;
@@ -1499,7 +1497,7 @@ int btrfs_remove_block_group_free_space(struct btrfs_trans_handle *trans, ret =btrfs_search_prev_slot (trans, root, &key, path,-1 ,1 );if (unlikely (ret)) {btrfs_abort_transaction (trans, ret); - goto out; +return ret; } leaf = path->nodes[0 ];
@@ -1530,14 +1528,13 @@ int btrfs_remove_block_group_free_space(struct btrfs_trans_handle *trans, ret =btrfs_del_items (trans, root, path, path->slots[0 ], nr);if (unlikely (ret)) {btrfs_abort_transaction (trans, ret); - goto out; +return ret; }btrfs_release_path (path); } ret =0 ; -out: -btrfs_free_path (path); +return ret; }
fs/btrfs/inode-item.c +1 -2
@@ -444,7 +444,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, struct btrfs_truncate_control *control) {struct btrfs_fs_info *fs_info = root->fs_info; -struct btrfs_path *path; +BTRFS_PATH_AUTO_FREE (path);struct extent_buffer *leaf;struct btrfs_file_extent_item *fi;struct btrfs_key key;
@@ -730,6 +730,5 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,if (!ret && control->last_size > new_size) control->last_size = new_size; -btrfs_free_path (path);return ret; }
fs/btrfs/inode.c +1 -2
@@ -4448,7 +4448,7 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, {struct btrfs_root *root = dir->root;struct btrfs_inode *inode =BTRFS_I (d_inode (dentry)); -struct btrfs_path *path; +BTRFS_PATH_AUTO_FREE (path);struct extent_buffer *leaf;struct btrfs_dir_item *di;struct btrfs_key key;
@@ -4541,7 +4541,6 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,if (ret)btrfs_abort_transaction (trans, ret); out: -btrfs_free_path (path);fscrypt_free_filename (&fname);return ret; }
fs/btrfs/ioctl.c +13 -24
@@ -1613,7 +1613,7 @@ static noinline int search_ioctl(struct btrfs_root *root, {struct btrfs_fs_info *info = root->fs_info;struct btrfs_key key; -struct btrfs_path *path; +BTRFS_PATH_AUTO_FREE (path);int ret;int num_found =0 ;unsigned long sk_offset =0 ;
@@ -1633,10 +1633,8 @@ static noinline int search_ioctl(struct btrfs_root *root, }else {/* Look up the root from the arguments. */ root =btrfs_get_fs_root (info, sk->tree_id, true); -if (IS_ERR (root)) { -btrfs_free_path (path); +if (IS_ERR (root))return PTR_ERR (root); - } } key.objectid = sk->min_objectid;
@@ -1670,7 +1668,6 @@ static noinline int search_ioctl(struct btrfs_root *root, sk->nr_items = num_found;btrfs_put_root (root); -btrfs_free_path (path);return ret; }
@@ -1753,7 +1750,7 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info,int total_len =0 ;struct btrfs_inode_ref *iref;struct extent_buffer *l; -struct btrfs_path *path; +BTRFS_PATH_AUTO_FREE (path);if (dirid ==BTRFS_FIRST_FREE_OBJECTID ) { name[0 ]='\0' ;
@@ -1814,7 +1811,6 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info, ret =0 ; out:btrfs_put_root (root); -btrfs_free_path (path);return ret; }
@@ -1831,7 +1827,7 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap,struct btrfs_inode_ref *iref;struct btrfs_root_ref *rref;struct btrfs_root *root =NULL ; -struct btrfs_path *path; +BTRFS_PATH_AUTO_FREE (path);struct btrfs_key key;struct extent_buffer *leaf;char *ptr;
@@ -1852,10 +1848,8 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap, ptr = &args->path[BTRFS_INO_LOOKUP_USER_PATH_MAX -1 ]; root =btrfs_get_fs_root (fs_info, treeid, true); -if (IS_ERR (root)) { - ret =PTR_ERR (root); - goto out; - } +if (IS_ERR (root)) +return PTR_ERR (root); key.objectid = dirid; key.type =BTRFS_INODE_REF_KEY ;
@@ -1930,12 +1924,10 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap, key.type =BTRFS_ROOT_REF_KEY ; key.offset = args->treeid; ret =btrfs_search_slot (NULL , fs_info->tree_root, &key, path,0 ,0 ); -if (ret <0 ) { - goto out; - }else if (ret >0 ) { - ret = -ENOENT ; - goto out; - } +if (ret <0 ) +return ret; +else if (ret >0 ) +return -ENOENT ; leaf = path->nodes[0 ]; slot = path->slots[0 ];
@@ -1945,10 +1937,8 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap, item_len =btrfs_item_size (leaf, slot);/* Check if dirid in ROOT_REF corresponds to passed dirid */ rref = btrfs_item_ptr(leaf, slot, struct btrfs_root_ref); -if (args->dirid !=btrfs_root_ref_dirid (leaf, rref)) { - ret = -EINVAL ; - goto out; - } +if (args->dirid !=btrfs_root_ref_dirid (leaf, rref)) +return -EINVAL ;/* Copy subvolume's name */ item_off +=sizeof (struct btrfs_root_ref );
@@ -1958,8 +1948,7 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap, out_put:btrfs_put_root (root); -out: -btrfs_free_path (path); +return ret; }
fs/btrfs/qgroup.c +53 -89
389 lines not on this page · raw message
fs/btrfs/super.c +3 -7
@@ -805,17 +805,15 @@ char *btrfs_get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info,struct btrfs_root_ref *root_ref;struct btrfs_inode_ref *inode_ref;struct btrfs_key key; -struct btrfs_path *path =NULL ; +BTRFS_PATH_AUTO_FREE (path);char *name =NULL , *ptr;u64 dirid;int len;int ret; path =btrfs_alloc_path (); -if (!path) { - ret = -ENOMEM ; - goto err; - } +if (!path) +return ERR_PTR (-ENOMEM ); name =kmalloc (PATH_MAX ,GFP_KERNEL );if (!name) {
@@ -903,7 +901,6 @@ char *btrfs_get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info, fs_root =NULL ; } -btrfs_free_path (path);if (ptr == name +PATH_MAX -1 ) { name[0 ] ='/' ; name[1 ] ='\0' ;
@@ -914,7 +911,6 @@ char *btrfs_get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info, err:btrfs_put_root (fs_root); -btrfs_free_path (path);kfree (name);return ERR_PTR (ret); }
fs/btrfs/tree-log.c +1 -3
@@ -2647,7 +2647,7 @@ static noinline int replay_dir_deletes(struct walk_control *wc,int ret =0 ;struct btrfs_key dir_key;struct btrfs_key found_key; -struct btrfs_path *log_path; +BTRFS_PATH_AUTO_FREE (log_path);struct btrfs_inode *dir; dir_key.objectid = dirid;
@@ -2664,7 +2664,6 @@ static noinline int replay_dir_deletes(struct walk_control *wc,* we replay the deletes before we copy in the inode item from the log. */ if (IS_ERR (dir)) { -btrfs_free_path (log_path); ret =PTR_ERR (dir);if (ret == -ENOENT ) ret =0 ;
@@ -2744,7 +2743,6 @@ static noinline int replay_dir_deletes(struct walk_control *wc, ret =0 ; out:btrfs_release_path (wc->subvol_path); -btrfs_free_path (log_path);iput (&dir->vfs_inode);return ret; }
fs/btrfs/volumes.c +1 -2
@@ -4205,7 +4205,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)struct btrfs_root *chunk_root = fs_info->chunk_root;u64 chunk_type;struct btrfs_chunk *chunk; -struct btrfs_path *path =NULL ; +BTRFS_PATH_AUTO_FREE (path);struct btrfs_key key;struct btrfs_key found_key;struct extent_buffer *leaf;
@@ -4382,7 +4382,6 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info) goto again; } error: -btrfs_free_path (path);if (enospc_errors) {btrfs_info (fs_info,"%d enospc errors during balance" , enospc_errors);
fs/btrfs/xattr.c +1 -2
@@ -85,7 +85,7 @@ int btrfs_setxattr(struct btrfs_trans_handle *trans, struct inode *inode, {struct btrfs_dir_item *di =NULL ;struct btrfs_root *root =BTRFS_I (inode)->root; -struct btrfs_path *path; +BTRFS_PATH_AUTO_FREE (path);size_t name_len =strlen (name);int ret =0 ;
@@ -212,7 +212,6 @@ int btrfs_setxattr(struct btrfs_trans_handle *trans, struct inode *inode,*/ } out: -btrfs_free_path (path);if (!ret) {set_bit (BTRFS_INODE_COPY_EVERYTHING , &BTRFS_I (inode)->runtime_flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 301/377 btrfs: check squota parent usage on membership change
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boris Burkov <[email protected]>
[ Upstream commit 9c46bcda5f347febdbb4d117fb21a37ffcec5fa4 ]
We could have detected the quick inherit bug more directly if we had an extra warning about squota hierarchy consistency while modifying the hierarchy. In squotas, the parent usage always simply adds up to the sum of its children, so we can just check for that when changing membership and detect more accounting bugs.
Stable-dep-of: 1e92637722ae ("btrfs: check for subvolume before deleting squota qgroup")
--- fs/btrfs/qgroup.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
fs/btrfs/qgroup.c +39 -0
@@ -346,6 +346,42 @@ int btrfs_verify_qgroup_counts(const struct btrfs_fs_info *fs_info, u64 qgroupid }#endif +static bool squota_check_parent_usage (struct btrfs_fs_info *fs_info,struct btrfs_qgroup *parent) +{ +u64 excl_sum =0 ; +u64 rfer_sum =0 ; +u64 excl_cmpr_sum =0 ; +u64 rfer_cmpr_sum =0 ; +struct btrfs_qgroup_list *glist; +int nr_members =0 ; +bool mismatch; + +if (btrfs_qgroup_mode (fs_info) !=BTRFS_QGROUP_MODE_SIMPLE ) +return false; +if (btrfs_qgroup_level (parent->qgroupid) ==0 ) +return false; + +/* Eligible parent qgroup. Squota; level > 0; empty members list. */ +list_for_each_entry (glist, &parent->members, next_member) { + excl_sum += glist->member->excl; + rfer_sum += glist->member->rfer; + excl_cmpr_sum += glist->member->excl_cmpr; + rfer_cmpr_sum += glist->member->rfer_cmpr; + nr_members++; + } + mismatch = (parent->excl != excl_sum || parent->rfer != rfer_sum || + parent->excl_cmpr != excl_cmpr_sum || parent->rfer_cmpr != excl_cmpr_sum); + +WARN (mismatch, +"parent squota qgroup %hu/%llu has mismatched usage from its %d members. " +"%llu %llu %llu %llu vs %llu %llu %llu %llu\n" , +btrfs_qgroup_level (parent->qgroupid), +btrfs_qgroup_subvolid (parent->qgroupid), nr_members, parent->excl, + parent->rfer, parent->excl_cmpr, parent->rfer_cmpr, excl_sum, + rfer_sum, excl_cmpr_sum, rfer_cmpr_sum); +return mismatch; +} + __printf(2, 3)static void qgroup_mark_inconsistent (struct btrfs_fs_info *fs_info,const char *fmt, ...) {
@@ -1565,6 +1601,7 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, u64 src, u64 dst goto out; } ret =quick_update_accounting (fs_info, src, dst,1 ); +squota_check_parent_usage (fs_info, parent);spin_unlock (&fs_info->qgroup_lock); out:kfree (prealloc);
@@ -1623,6 +1660,8 @@ static int __del_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,spin_lock (&fs_info->qgroup_lock);del_relation_rb (fs_info, src, dst); ret =quick_update_accounting (fs_info, src, dst,-1 ); +ASSERT (parent); +squota_check_parent_usage (fs_info, parent);spin_unlock (&fs_info->qgroup_lock); } out:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 302/377 btrfs: relax squota parent qgroup deletion rule
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boris Burkov <[email protected]>
[ Upstream commit adb0af40fe89fd42f1ef277bf60d9cfa7c2ae472 ]
Currently, with squotas, we do not allow removing a parent qgroup with no members if it still has usage accounted to it. This makes it really difficult to recover from accounting bugs, as we have no good way of getting back to 0 usage.
Instead, allow deletion (it's safe at 0 members..) while still warning about the inconsistency by adding a squota parent check.
Stable-dep-of: 1e92637722ae ("btrfs: check for subvolume before deleting squota qgroup")
--- fs/btrfs/qgroup.c | 50 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 15 deletions(-)
fs/btrfs/qgroup.c +35 -15
@@ -1723,6 +1723,36 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)return ret; } +static bool can_delete_parent_qgroup (struct btrfs_qgroup *qgroup) + +{ +ASSERT (btrfs_qgroup_level (qgroup->qgroupid)); +return list_empty (&qgroup->members); +} + +/* +* Return true if we can delete the squota qgroup and false otherwise. +* +* Rules for whether we can delete: +* +* A subvolume qgroup can be removed iff the subvolume is fully deleted, which +* is iff there is 0 usage in the qgroup. +* +* A higher level qgroup can be removed iff it has no members. +* Note: We audit its usage to warn on inconsitencies without blocking deletion. +*/ +static bool can_delete_squota_qgroup (struct btrfs_fs_info *fs_info,struct btrfs_qgroup *qgroup) +{ +ASSERT (btrfs_qgroup_mode (fs_info) ==BTRFS_QGROUP_MODE_SIMPLE ); + +if (btrfs_qgroup_level (qgroup->qgroupid) >0 ) { +squota_check_parent_usage (fs_info, qgroup); +return can_delete_parent_qgroup (qgroup); + } + +return !(qgroup->rfer || qgroup->excl || qgroup->rfer_cmpr || qgroup->excl_cmpr); +} +/* * Return 0 if we can not delete the qgroup (not empty or has children etc). * Return >0 if we can delete the qgroup.
@@ -1733,23 +1763,13 @@ static int can_delete_qgroup(struct btrfs_fs_info *fs_info, struct btrfs_qgroupstruct btrfs_key key;BTRFS_PATH_AUTO_FREE (path); -/* -* Squota would never be inconsistent, but there can still be case -* where a dropped subvolume still has qgroup numbers, and squota -* relies on such qgroup for future accounting. -* -* So for squota, do not allow dropping any non-zero qgroup. -*/ -if (btrfs_qgroup_mode (fs_info) ==BTRFS_QGROUP_MODE_SIMPLE && - (qgroup->rfer || qgroup->excl || qgroup->excl_cmpr || qgroup->rfer_cmpr)) -return 0 ; +/* Since squotas cannot be inconsistent, they have special rules for deletion. */ +if (btrfs_qgroup_mode (fs_info) ==BTRFS_QGROUP_MODE_SIMPLE ) +return can_delete_squota_qgroup (fs_info, qgroup);/* For higher level qgroup, we can only delete it if it has no child. */ -if (btrfs_qgroup_level (qgroup->qgroupid)) { -if (!list_empty (&qgroup->members)) -return 0 ; -return 1 ; - } +if (btrfs_qgroup_level (qgroup->qgroupid)) +return can_delete_parent_qgroup (qgroup);/* * For level-0 qgroups, we can only delete it if it has no subvolume
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 303/377 btrfs: check for subvolume before deleting squota qgroup
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boris Burkov <[email protected]>
[ Upstream commit 1e92637722ae4bd417f7a37e8d1485dc23b93935 ]
The invariant that we want to maintain with subvolume qgroups is that the qgroup can only be deleted if there is no root. With squotas, we thought that it was sufficient to just check the usage, because we assumed that deleting a subvolume will drive it's qgroups usage to 0, and thus 0 usage implies no subvolume.
However, this is false, for two reasons:
- A subvol whose extents are all from before squotas was enabled.
- A subvol that was created in this transaction and for which we have not yet run any delayed refs.
In both cases, deleting the qgroup breaks the desired invariant and we are left with a subvolume with no qgroup but squotas are enabled.
Fix this by unifying the deletion check logic between full qgroups and squotas. Squotas do all the same checks *and* the additional usage == 0 check, which is the one extra rule peculiar to squotas.
--- fs/btrfs/qgroup.c | 50 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-)
fs/btrfs/qgroup.c +25 -25
@@ -1723,32 +1723,24 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)return ret; } -static bool can_delete_parent_qgroup (struct btrfs_qgroup *qgroup) - +static bool can_delete_parent_qgroup (struct btrfs_fs_info *fs_info,struct btrfs_qgroup *qgroup) {ASSERT (btrfs_qgroup_level (qgroup->qgroupid)); +if (btrfs_qgroup_mode (fs_info) ==BTRFS_QGROUP_MODE_SIMPLE ) +squota_check_parent_usage (fs_info, qgroup);return list_empty (&qgroup->members); }/* -* Return true if we can delete the squota qgroup and false otherwise. -* -* Rules for whether we can delete: -* -* A subvolume qgroup can be removed iff the subvolume is fully deleted, which -* is iff there is 0 usage in the qgroup. -* -* A higher level qgroup can be removed iff it has no members. -* Note: We audit its usage to warn on inconsitencies without blocking deletion. +* Because a shared extent can outlive its owning subvolume, we cannot delete a +* subvol squota qgroup until all of the extents it owns are gone, even if the +* subvolume itself has been deleted. */ -static bool can_delete_squota_qgroup (struct btrfs_fs_info *fs_info,struct btrfs_qgroup *qgroup) +static bool can_delete_squota_subvol_qgroup (struct btrfs_fs_info *fs_info, +struct btrfs_qgroup *qgroup) {ASSERT (btrfs_qgroup_mode (fs_info) ==BTRFS_QGROUP_MODE_SIMPLE ); - -if (btrfs_qgroup_level (qgroup->qgroupid) >0 ) { -squota_check_parent_usage (fs_info, qgroup); -return can_delete_parent_qgroup (qgroup); - } +ASSERT (btrfs_qgroup_level (qgroup->qgroupid) ==0 );return !(qgroup->rfer || qgroup->excl || qgroup->rfer_cmpr || qgroup->excl_cmpr); }
@@ -1762,14 +1754,11 @@ static int can_delete_qgroup(struct btrfs_fs_info *fs_info, struct btrfs_qgroup {struct btrfs_key key;BTRFS_PATH_AUTO_FREE (path); - -/* Since squotas cannot be inconsistent, they have special rules for deletion. */ -if (btrfs_qgroup_mode (fs_info) ==BTRFS_QGROUP_MODE_SIMPLE ) -return can_delete_squota_qgroup (fs_info, qgroup); +int ret;/* For higher level qgroup, we can only delete it if it has no child. */ if (btrfs_qgroup_level (qgroup->qgroupid)) -return can_delete_parent_qgroup (qgroup); +return can_delete_parent_qgroup (fs_info, qgroup);/* * For level-0 qgroups, we can only delete it if it has no subvolume
@@ -1785,10 +1774,21 @@ static int can_delete_qgroup(struct btrfs_fs_info *fs_info, struct btrfs_qgroupreturn -ENOMEM ;/* -* The @ret from btrfs_find_root() exactly matches our definition for -* the return value, thus can be returned directly. +* Any subvol qgroup, regardless of mode, cannot be deleted if the +* subvol still exists. +*/ + ret =btrfs_find_root (fs_info->tree_root, &key, path,NULL ,NULL ); +/* +* btrfs_find_root returns <0 on error, 0 if found, and >0 if not, +* so the "found" and "error" cases match our desired return values. */ -return btrfs_find_root (fs_info->tree_root, &key, path,NULL ,NULL ); +if (ret <=0 ) +return ret; + +/* Squotas require additional checks, even if the subvol is deleted. */ +if (btrfs_qgroup_mode (fs_info) ==BTRFS_QGROUP_MODE_SIMPLE ) +return can_delete_squota_subvol_qgroup (fs_info, qgroup); +return 1 ; }int btrfs_remove_qgroup (struct btrfs_trans_handle *trans,u64 qgroupid)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 304/377 btrfs: fix squota accounting during enable generation
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boris Burkov <[email protected]>
[ Upstream commit d7c600554816b8ef70adffe078a0e360c055d82b ]
The first transaction that enables squotas is special and a bit tricky. We have to set BTRFS_FS_QUOTA_ENABLED after the transaction to avoid a deadlock, so any delayed refs that run before we set the bit are not squota accounted. For data this is fine, we don't get an owner_ref, so there is no real harm, it's as if the extent predated squotas. However for metadata, the tree block will have gen == enable_gen so when we free it later, we will decrement the squota accounting, which can result in an underflow. Before it is freed, btrfs check shows errors, as we have mismatched usage between the node generations/owners and the squota values.
There are two angles to this fix:
1. For extents that come in delayed_refs that run during the enable_gen transaction, we must actually set enable_gen to the *next* transaction. That is the first transaction that we can really properly account in any way.
2. For extents that come in between the end of our transaction handle and the time we set the BTRFS_FS_QUOTA_ENABLED bit, we need an additional bit, BTRFS_FS_SQUOTA_ENABLING which only affects recording squota deltas, so we do pick up those extents. Otherwise, we would miss them, even for enable_gen + 1.
--- fs/btrfs/fs.h | 1 + fs/btrfs/qgroup.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-)
fs/btrfs/fs.h +1 -0
@@ -136,6 +136,7 @@ enum {BTRFS_FS_LOG_RECOVERING ,BTRFS_FS_OPEN ,BTRFS_FS_QUOTA_ENABLED , +BTRFS_FS_SQUOTA_ENABLING ,BTRFS_FS_UPDATE_UUID_TREE_GEN ,BTRFS_FS_CREATING_FREE_SPACE_TREE , BTRFS_FS_BTREE_ERR,
fs/btrfs/qgroup.c +27 -4
@@ -1111,7 +1111,13 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info,if (simple) { fs_info->qgroup_flags |=BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE ;btrfs_set_fs_incompat (fs_info,SIMPLE_QUOTA ); -btrfs_set_qgroup_status_enable_gen (leaf, ptr, trans->transid); +/* +* Set the enable generation to the next transaction, as we cannot +* ensure that extents written during this transaction will see any +* state we have set here. So we should treat all extents of the +* transaction as coming in before squotas was enabled. +*/ +btrfs_set_qgroup_status_enable_gen (leaf, ptr, trans->transid +1 ); }else { fs_info->qgroup_flags |=BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT ; }
@@ -1214,7 +1220,15 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info, goto out_free_path; } - fs_info->qgroup_enable_gen = trans->transid; +/* +* Set fs_info->qgroup_enable_gen and BTRFS_FS_SQUOTA_ENABLING +* under the transaction handle. We want to ensure that all extents in +* the next transaction definitely see them. +*/ +if (simple) { + fs_info->qgroup_enable_gen = trans->transid +1 ; +set_bit (BTRFS_FS_SQUOTA_ENABLING , &fs_info->flags); + }mutex_unlock (&fs_info->qgroup_ioctl_lock);/*
@@ -1228,9 +1242,15 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info,*/ ret =btrfs_commit_transaction (trans); trans =NULL ; +mutex_lock (&fs_info->qgroup_ioctl_lock); -if (ret) +if (ret) { +if (simple) { +clear_bit (BTRFS_FS_SQUOTA_ENABLING , &fs_info->flags); + fs_info->qgroup_enable_gen =0 ; + } goto out_free_path; + }/* * Set quota enabled flag after committing the transaction, to avoid
@@ -1240,6 +1260,8 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info,spin_lock (&fs_info->qgroup_lock); fs_info->quota_root = quota_root;set_bit (BTRFS_FS_QUOTA_ENABLED , &fs_info->flags); +if (simple) +clear_bit (BTRFS_FS_SQUOTA_ENABLING , &fs_info->flags);spin_unlock (&fs_info->qgroup_lock);/* Skip rescan for simple qgroups. */
@@ -4930,7 +4952,8 @@ int btrfs_record_squota_delta(struct btrfs_fs_info *fs_info,u64 num_bytes = delta->num_bytes;const int sign = (delta->is_inc ?1 :-1 ); -if (btrfs_qgroup_mode (fs_info) !=BTRFS_QGROUP_MODE_SIMPLE ) +if (btrfs_qgroup_mode (fs_info) !=BTRFS_QGROUP_MODE_SIMPLE && + !test_bit (BTRFS_FS_SQUOTA_ENABLING , &fs_info->flags))return 0 ;if (!btrfs_is_fstree (root))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 305/377 ASoC: amd: acp-sdw-legacy: check CPU DAI name before logging
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cássio Gabriel <[email protected]>
[ Upstream commit 1afd8f06dcb1d561af3b239c5b14a88b87c13454 ]
devm_kasprintf() can fail and return NULL. The legacy AMD SoundWire machine driver logs cpus->dai_name before checking the allocation result.
Move the debug print after the NULL check, matching the ordering used by the SOF AMD SoundWire path after commit 5726b68473f7 ("ASoC: amd/sdw_utils:
avoid NULL deref when devm_kasprintf() fails").
--- sound/soc/amd/acp/acp-sdw-legacy-mach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/amd/acp/acp-sdw-legacy-mach.c +1 -1
@@ -244,9 +244,9 @@ static int create_sdw_dailink(struct snd_soc_card *card, cpus->dai_name =devm_kasprintf (dev,GFP_KERNEL ,"SDW%d Pin%d" , link_num, cpu_pin_id); -dev_dbg (dev,"cpu->dai_name:%s\n" , cpus->dai_name);if (!cpus->dai_name)return -ENOMEM ; +dev_dbg (dev,"cpu->dai_name:%s\n" , cpus->dai_name); codec_maps[j].cpu =0 ; codec_maps[j].codec = j;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 306/377 spi: mtk-snfi: Fix resource leak in mtk_snand_read_page_cache()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 496ba79b9496b8b3747cbc764ebd33ee7325e806 ]
When DMA read times out in mtk_snand_read_page_cache(), the original code erroneously jumped to cleanup label which skips DMA unmapping and ECC disable, causing a resource leak.
--- drivers/spi/spi-mtk-snfi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-mtk-snfi.c +1 -1
@@ -961,7 +961,7 @@ static int mtk_snand_read_page_cache(struct mtk_snand *snf, &snf->op_done, usecs_to_jiffies(SNFI_POLL_INTERVAL))) {dev_err (snf->dev,"DMA timed out for reading from cache.\n" ); ret = -ETIMEDOUT ; - goto cleanup; + goto cleanup2; }// Wait for BUS_SEC_CNTR returning expected value
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 307/377 netfilter: nft_inner: release local_lock before re-enabling softirqs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit a6cb3ff979855f7f0ee9450a947fe8f96c2ba37a ]
Quoting sashiko:
In the error path, local_bh_enable() is called before local_unlock_nested_bh().
--- net/netfilter/nft_inner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nft_inner.c +1 -1
@@ -246,8 +246,8 @@ static bool nft_inner_restore_tun_ctx(const struct nft_pktinfo *pkt,local_lock_nested_bh (&nft_pcpu_tun_ctx.bh_lock); this_cpu_tun_ctx =this_cpu_ptr (&nft_pcpu_tun_ctx.ctx);if (this_cpu_tun_ctx->cookie != (unsigned long )pkt->skb) { -local_bh_enable ();local_unlock_nested_bh (&nft_pcpu_tun_ctx.bh_lock); +local_bh_enable ();return false; } *tun_ctx = *this_cpu_tun_ctx;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 308/377 ALSA: hda/realtek: Use ALC287_FIXUP_TXNW2781_I2C for ASUS Strix Gxx5
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Naim <[email protected]>
[ Upstream commit 4372286ac774536e8e68bc6dfa0f0b0152b31fce ]
These devices were incorrectly using the ALC287_FIXUP_TAS2781_I2C quirk leading to errors:
[ 18.765990] Serial bus multi instantiate pseudo device driver TXNW2781:00: error -ENXIO: IRQ index 0 not found [ 18.768153] Serial bus multi instantiate pseudo device driver TXNW2781:00: error -ENXIO: IRQ index 0 not found [ 18.768476] Serial bus multi instantiate pseudo device driver TXNW2781:00: error -ENXIO: IRQ index 0 not found [ 18.768899] Serial bus multi instantiate pseudo device driver TXNW2781:00: Instantiated 3 I2C devices.
Use the ALC287_FIXUP_TXNW2781_I2C quirk instead to fix this and restore speaker audio on affected devices.
--- sound/hda/codecs/realtek/alc269.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
sound/hda/codecs/realtek/alc269.c +6 -6
@@ -7182,12 +7182,12 @@ static const struct hda_quirk alc269_fixup_tbl[] = {SND_PCI_QUIRK (0x1043 ,0x3e00 ,"ASUS G814FH/FM/FP" ,ALC287_FIXUP_CS35L41_I2C_2 ),SND_PCI_QUIRK (0x1043 ,0x3e20 ,"ASUS G814PH/PM/PP" ,ALC287_FIXUP_CS35L41_I2C_2 ),SND_PCI_QUIRK (0x1043 ,0x3e30 ,"ASUS TP3607SA" ,ALC287_FIXUP_TAS2781_I2C ), -SND_PCI_QUIRK (0x1043 ,0x3ee0 ,"ASUS Strix G815_JHR_JMR_JPR" ,ALC287_FIXUP_TAS2781_I2C ), -SND_PCI_QUIRK (0x1043 ,0x3ef0 ,"ASUS Strix G635LR_LW_LX" ,ALC287_FIXUP_TAS2781_I2C ), -SND_PCI_QUIRK (0x1043 ,0x3f00 ,"ASUS Strix G815LH_LM_LP" ,ALC287_FIXUP_TAS2781_I2C ), -SND_PCI_QUIRK (0x1043 ,0x3f10 ,"ASUS Strix G835LR_LW_LX" ,ALC287_FIXUP_TAS2781_I2C ), -SND_PCI_QUIRK (0x1043 ,0x3f20 ,"ASUS Strix G615LR_LW" ,ALC287_FIXUP_TAS2781_I2C ), -SND_PCI_QUIRK (0x1043 ,0x3f30 ,"ASUS Strix G815LR_LW" ,ALC287_FIXUP_TAS2781_I2C ), +SND_PCI_QUIRK (0x1043 ,0x3ee0 ,"ASUS Strix G815_JHR_JMR_JPR" ,ALC287_FIXUP_TXNW2781_I2C ), +SND_PCI_QUIRK (0x1043 ,0x3ef0 ,"ASUS Strix G635LR_LW_LX" ,ALC287_FIXUP_TXNW2781_I2C ), +SND_PCI_QUIRK (0x1043 ,0x3f00 ,"ASUS Strix G815LH_LM_LP" ,ALC287_FIXUP_TXNW2781_I2C ), +SND_PCI_QUIRK (0x1043 ,0x3f10 ,"ASUS Strix G835LR_LW_LX" ,ALC287_FIXUP_TXNW2781_I2C ), +SND_PCI_QUIRK (0x1043 ,0x3f20 ,"ASUS Strix G615LR_LW" ,ALC287_FIXUP_TXNW2781_I2C ), +SND_PCI_QUIRK (0x1043 ,0x3f30 ,"ASUS Strix G815LR_LW" ,ALC287_FIXUP_TXNW2781_I2C ),SND_PCI_QUIRK (0x1043 ,0x3fd0 ,"ASUS B3605CVA" ,ALC245_FIXUP_CS35L41_SPI_2 ),SND_PCI_QUIRK (0x1043 ,0x3ff0 ,"ASUS B5405CVA" ,ALC245_FIXUP_CS35L41_SPI_2 ), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 309/377 drm/msm/snapshot: fix dumping of the unaligned regions
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit 76824d2467feb1828b745d6add2541918d7be3da ]
The snapshotting code internally aligns data segment to 16 bytes. This works fine for DPU code (where most of the regions are aligned), but fails for snapshotting of the DSI data (because DSI data region is shifted by 4 bytes). Fix the code by removing length alignment and by accurately printing last registers in the region. While reworking the code also fix the 16x memory overallocation in msm_disp_state_dump_regs().
Patchwork: https://patchwork.freedesktop.org/patch/725449/
Message-ID: <[email protected]>
--- .../gpu/drm/msm/disp/msm_disp_snapshot_util.c | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-)
drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c +18 -6
@@ -9,7 +9,7 @@#include "msm_disp_snapshot.h" -static void msm_disp_state_dump_regs (u32 **reg,u32 aligned_len,void __iomem *base_addr) +static void msm_disp_state_dump_regs (u32 **reg,u32 len,void __iomem *base_addr) {u32 len_padded;u32 num_rows;
@@ -19,11 +19,11 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *bvoid __iomem *end_addr;int i; - len_padded = aligned_len *REG_DUMP_ALIGN ; - num_rows = aligned_len /REG_DUMP_ALIGN ; + len_padded =round_up (len,REG_DUMP_ALIGN ); + num_rows =DIV_ROUND_UP (len,REG_DUMP_ALIGN ); addr = base_addr; - end_addr = base_addr + aligned_len; + end_addr = base_addr + len; *reg =kvzalloc (len_padded,GFP_KERNEL );if (!*reg)
@@ -48,8 +48,8 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *bstatic void msm_disp_state_print_regs (const u32 *dump_addr,u32 len,void __iomem *base_addr,struct drm_printer *p) { +void __iomem *addr, *end_addr;int i; -void __iomem *addr;u32 num_rows;if (!dump_addr) {
@@ -58,6 +58,7 @@ static void msm_disp_state_print_regs(const u32 *dump_addr, u32 len, } addr = base_addr; + end_addr = base_addr + len; num_rows = len /REG_DUMP_ALIGN ;for (i =0 ; i < num_rows; i++) {
@@ -67,6 +68,17 @@ static void msm_disp_state_print_regs(const u32 *dump_addr, u32 len, dump_addr[i * 4 + 2], dump_addr[i * 4 + 3]); addr +=REG_DUMP_ALIGN ; } + +if (addr != end_addr) { +drm_printf (p,"0x%lx : %08x" , + (unsigned long )(addr - base_addr), + dump_addr[i *4 ]); +if (addr +0x4 < end_addr) +drm_printf (p," %08x" , dump_addr[i *4 +1 ]); +if (addr +0x8 < end_addr) +drm_printf (p," %08x" , dump_addr[i *4 +2 ]); +drm_printf (p,"\n" ); + } }void msm_disp_state_print (struct msm_disp_state *state,struct drm_printer *p)
@@ -186,7 +198,7 @@ void msm_disp_snapshot_add_block(struct msm_disp_state *disp_state, u32 len,va_end (va);INIT_LIST_HEAD (&new_blk->node); - new_blk->size =ALIGN (len,REG_DUMP_ALIGN ); + new_blk->size = len; new_blk->base_addr = base_addr;msm_disp_state_dump_regs (&new_blk->state, new_blk->size, base_addr);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 310/377 hwmon: (lm90) Stop work before releasing hwmon device
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit b09a45601094c7f4ec4db8090b825fa61e169d93 ]
Sashiko reports:
In lm90_probe(), the devm action to cancel the alert_work and report_work (lm90_restore_conf) is registered in lm90_init_client() before devm_hwmon_device_register_with_info() is called.
Because devm executes cleanup actions in reverse order during module unbind or probe failure, the hwmon device is unregistered and freed first.
If lm90_alert_work() or lm90_report_alarms() runs in the window between the hwmon device being freed and the delayed works being cancelled, lm90_update_alarms() will dereference the freed data->hwmon_dev here.
Fix the problem by canceling the workers separately after registering the hwmon device and before registering the interrupt handler. This ensures that the workers are canceled after interrupts are disabled and before the hwmon device is released. Add "shutdown" flag to indicate that device shutdown is in progress to prevent workers from being re-armed.
--- drivers/hwmon/lm90.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)
drivers/hwmon/lm90.c +20 -4
@@ -738,6 +738,7 @@ struct lm90_data {struct mutex update_lock;struct delayed_work alert_work;struct work_struct report_work; +bool shutdown;/* true if shutting down */ bool valid;/* true if register values are valid */ bool alarms_valid;/* true if status register values are valid */ unsigned long last_updated;/* in jiffies */
@@ -1156,6 +1157,9 @@ static void lm90_report_alarms(struct work_struct *work)static int lm90_update_alarms_locked (struct lm90_data *data,bool force) { +if (data->shutdown) +return 0 ; +if (force || !data->alarms_valid ||time_after (jiffies, data->alarms_updated +msecs_to_jiffies (data->update_interval))) {struct i2c_client *client = data->client;
@@ -2600,15 +2604,23 @@ static void lm90_restore_conf(void *_data)struct lm90_data *data = _data;struct i2c_client *client = data->client; -cancel_delayed_work_sync (&data->alert_work); -cancel_work_sync (&data->report_work); -/* Restore initial configuration */ if (data->flags &LM90_HAVE_CONVRATE )lm90_write_convrate (data, data->convrate_orig);lm90_write_reg (client,LM90_REG_CONFIG1 , data->config_orig); } +static void lm90_stop_work (void *_data) +{ +struct lm90_data *data = _data; + +hwmon_lock (data->hwmon_dev); + data->shutdown = true; +hwmon_unlock (data->hwmon_dev); +cancel_delayed_work_sync (&data->alert_work); +cancel_work_sync (&data->report_work); +} +static int lm90_init_client (struct i2c_client *client,struct lm90_data *data) {struct device_node *np = client->dev.of_node;
@@ -2919,6 +2931,10 @@ static int lm90_probe(struct i2c_client *client) data->hwmon_dev = hwmon_dev; + err =devm_add_action_or_reset (&client->dev, lm90_stop_work, data); +if (err) +return err; +if (client->irq) {dev_dbg (dev,"IRQ: %d\n" , client->irq); err = devm_request_threaded_irq(dev, client->irq,
@@ -2947,7 +2963,7 @@ static void lm90_alert(struct i2c_client *client, enum i2c_alert_protocol type,*/ struct lm90_data *data =i2c_get_clientdata (client); -if ((data->flags &LM90_HAVE_BROKEN_ALERT ) && +if (!data->shutdown && (data->flags &LM90_HAVE_BROKEN_ALERT ) && (data->current_alarms & data->alert_alarms)) {if (!(data->config &0x80 )) {dev_dbg (&client->dev,"Disabling ALERT#\n" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 311/377 hwmon: (lm90) Add lock protection to lm90_alert
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit 873e919e3101063a7a75989510ccfc125a4391cf ]
Sashiko reports:
lm90_alert() executes in the smbus alert context and calls lm90_update_confreg() to disable the hardware alert line, without acquiring hwmon_lock.
Concurrently, sysfs write operations (such as lm90_write_convrate) hold the hwmon_lock, temporarily modify data->config, and then restore it.
If an alert interrupt occurs concurrently with a sysfs write, the sysfs path will overwrite the alert handler's modifications to data->config and the hardware register.
This unintentionally re-enables the hardware alert line while the alarm is still active, causing an interrupt storm.
Add the missing lock to lm90_alert() to solve the problem.
--- drivers/hwmon/lm90.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/hwmon/lm90.c +2 -0
@@ -2963,6 +2963,7 @@ static void lm90_alert(struct i2c_client *client, enum i2c_alert_protocol type,*/ struct lm90_data *data =i2c_get_clientdata (client); +hwmon_lock (data->hwmon_dev);if (!data->shutdown && (data->flags &LM90_HAVE_BROKEN_ALERT ) && (data->current_alarms & data->alert_alarms)) {if (!(data->config &0x80 )) {
@@ -2972,6 +2973,7 @@ static void lm90_alert(struct i2c_client *client, enum i2c_alert_protocol type,schedule_delayed_work (&data->alert_work,max_t (int,HZ ,msecs_to_jiffies (data->update_interval))); } +hwmon_unlock (data->hwmon_dev); }else {dev_dbg (&client->dev,"Everything OK\n" ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 312/377 wifi: iwlwifi: mld: fix TSO segmentation explosion when AMSDU is disabled
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cole Leavitt <[email protected]>
[ Upstream commit 92cee08dc4f00e77fd1317e4343c5d458b0abab7 ]
When the TLC notification disables AMSDU for a TID, the MLD driver sets max_tid_amsdu_len to the sentinel value 1. The TSO segmentation path in iwl_mld_tx_tso_segment() checks for zero but not for this sentinel, allowing it to reach the num_subframes calculation:
num_subframes = (max_tid_amsdu_len + pad) / (subf_len + pad)
= (1 + 2) / (1534 + 2) = 0
This zero propagates to iwl_tx_tso_segment() which sets:
gso_size = num_subframes * mss = 0
Calling skb_gso_segment() with gso_size=0 creates over 32000 tiny segments from a single GSO skb. This floods the TX ring with ~1024 micro-frames (the rest are purged), creating a massive burst of TX completion events that can lead to memory corruption and a subsequent use-after-free in TCP's retransmit queue (refcount underflow in tcp_shifted_skb, NULL deref in tcp_rack_detect_loss).
The MVM driver is immune because it checks mvmsta->amsdu_enabled before reaching the num_subframes calculation. The MLD driver has no equivalent bitmap check and relies solely on max_tid_amsdu_len, which does not catch the sentinel value.
Fix this by detecting the sentinel value (max_tid_amsdu_len == 1) at the existing check and falling back to non-AMSDU TSO segmentation. Also add a WARN_ON_ONCE guard after the num_subframes division as defense-in-depth to catch any future code paths that produce zero through a different mechanism.
--- drivers/net/wireless/intel/iwlwifi/mld/tx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/wireless/intel/iwlwifi/mld/tx.c +4 -1
@@ -828,7 +828,7 @@ static int iwl_mld_tx_tso_segment(struct iwl_mld *mld, struct sk_buff *skb,return -EINVAL ; max_tid_amsdu_len = sta->cur->max_tid_amsdu_len[tid]; -if (!max_tid_amsdu_len) +if (!max_tid_amsdu_len || max_tid_amsdu_len ==1 )return iwl_tx_tso_segment (skb,1 , netdev_flags, mpdus_skbs);/* Sub frame header + SNAP + IP header + TCP header + MSS */
@@ -840,6 +840,9 @@ static int iwl_mld_tx_tso_segment(struct iwl_mld *mld, struct sk_buff *skb,*/ num_subframes = (max_tid_amsdu_len + pad) / (subf_len + pad); +if (WARN_ON_ONCE (!num_subframes)) +return iwl_tx_tso_segment (skb,1 , netdev_flags, mpdus_skbs); +if (sta->max_amsdu_subframes && num_subframes > sta->max_amsdu_subframes) num_subframes = sta->max_amsdu_subframes;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 313/377 wifi: iwlwifi: mld: dont dereference a pointer before NULL checking it
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miri Korenblit <[email protected]>
[ Upstream commit d733ed481fd20a8e7bfe5119c4e77761ba3f87ee ]
In iwl_mld_remove_link, the link->fw_id is saved at the beginning of the function so we have it after we freed the link.
But the link pointer can be NULL, and is not checked when the fw_id is stored.
Fix it by simply freeing the link at the end of the function.
fFixes: 0e66a39f4f0e ("wifi: iwlwifi: fix potential use after free in iwl_mld_remove_link()")
--- drivers/net/wireless/intel/iwlwifi/mld/link.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
drivers/net/wireless/intel/iwlwifi/mld/link.c +6 -7
@@ -1,6 +1,6 @@// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* -* Copyright (C) 2024-2025 Intel Corporation +* Copyright (C) 2024-2026 Intel Corporation */ #include "constants.h"
@@ -501,7 +501,6 @@ void iwl_mld_remove_link(struct iwl_mld *mld,struct iwl_mld_vif *mld_vif =iwl_mld_vif_from_mac80211 (bss_conf->vif);struct iwl_mld_link *link =iwl_mld_link_from_mac80211 (bss_conf);bool is_deflink = link == &mld_vif->deflink; -u8 fw_id = link->fw_id;if (WARN_ON (!link || link->active))return ;
@@ -509,15 +508,15 @@ void iwl_mld_remove_link(struct iwl_mld *mld,iwl_mld_rm_link_from_fw (mld, bss_conf);/* Continue cleanup on failure */ -if (!is_deflink) -kfree_rcu (link, rcu_head); -RCU_INIT_POINTER (mld_vif->link[bss_conf->link_id],NULL ); -if (WARN_ON (fw_id >= mld->fw->ucode_capa.num_links)) +if (WARN_ON (link->fw_id >= mld->fw->ucode_capa.num_links))return ; -RCU_INIT_POINTER (mld->fw_id_to_bss_conf[fw_id],NULL ); +RCU_INIT_POINTER (mld->fw_id_to_bss_conf[link->fw_id],NULL ); + +if (!is_deflink) +kfree_rcu (link, rcu_head); } void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 314/377 dma-mapping: move dma_map_resource() sanity check into debug code
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jianpeng Chang <[email protected]>
[ Upstream commit af0c3f05866237f7592219bfe05387bc3bfc99b5 ]
dma_map_resource() uses pfn_valid() to ensure the range is not RAM. However, pfn_valid() only checks for availability of the memory map for a PFN but it does not ensure that the PFN is actually backed by RAM. On ARM64 with SPARSEMEM (128MB section granularity), MMIO addresses that share a section with RAM will falsely trigger the WARN_ON_ONCE and cause dma_map_resource() to return DMA_MAPPING_ERROR.
This causes a WARNING on Raspberry Pi 4 during spi_bcm2835 probe because the SPI FIFO register (0xfe204004) falls in the same sparsemem section as the end of RAM (0xf8000000-0xfbffffff), both in section 31 (0xf8000000-0xffffffff).
Move the sanity check from dma_map_resource() into debug_dma_map_phys() and replace the unreliable pfn_valid() with pfn_valid() && !PageReserved(), which correctly identifies actual usable RAM without false positives for MMIO regions that happen to have struct pages.
Since dma_map_resource() is dma_map_phys(DMA_ATTR_MMIO), the check applies equally to both APIs. Any non-reserved page represents kernel memory to a sufficient degree that using DMA_ATTR_MMIO on it is almost certainly wrong and risks breaking coherency on non-coherent platforms. ZONE_DEVICE pages used for PCI P2P DMA (MEMORY_DEVICE_PCI_P2PDMA) have PageReserved set, so they will not trigger a false positive.
The check no longer blocks the mapping and uses err_printk() to integrate with dma-debug filtering.
--- kernel/dma/debug.c | 9 ++++++++- kernel/dma/mapping.c | 4 ---- 2 files changed, 8 insertions(+), 5 deletions(-)
kernel/dma/debug.c +8 -1
@@ -1250,7 +1250,14 @@ void debug_dma_map_phys(struct device *dev, phys_addr_t phys, size_t size, entry->direction = direction; entry->map_err_type =MAP_ERR_NOT_CHECKED ; -if (!(attrs &DMA_ATTR_MMIO )) { +if (attrs &DMA_ATTR_MMIO ) { +unsigned long pfn =PHYS_PFN (phys); + +if (pfn_valid (pfn) && !PageReserved (pfn_to_page (pfn))) +err_printk (dev, entry, +"dma_map_resource called for RAM address %pa\n" , + &phys); + }else {check_for_stack (dev, phys);if (!PhysHighMem (phys))
kernel/dma/mapping.c +0 -4
@@ -366,10 +366,6 @@ EXPORT_SYMBOL(dma_unmap_sg_attrs);dma_addr_t dma_map_resource (struct device *dev,phys_addr_t phys_addr,size_t size,enum dma_data_direction dir,unsigned long attrs) { -if (IS_ENABLED (CONFIG_DMA_API_DEBUG ) && -WARN_ON_ONCE (pfn_valid (PHYS_PFN (phys_addr)))) -return DMA_MAPPING_ERROR ; -return dma_map_phys (dev, phys_addr, size, dir, attrs |DMA_ATTR_MMIO ); }EXPORT_SYMBOL (dma_map_resource);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 315/377 drm/xe/gsc: Fix double-free of managed BO in error path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuicheng Lin <[email protected]>
[ Upstream commit d3ded53fab90996e7d94a39049e11962dd066725 ]
The error path in xe_gsc_init_post_hwconfig() explicitly frees a BO allocated with xe_managed_bo_create_pin_map() via xe_bo_unpin_map_no_vm(). Since the managed BO already has a devm cleanup action registered, this causes a double-free when devm unwinds during probe failure.
Remove the explicit free and let devm handle it, consistent with all other xe_managed_bo_create_pin_map() callers.
--- drivers/gpu/drm/xe/xe_gsc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/gpu/drm/xe/xe_gsc.c +1 -4
@@ -487,8 +487,7 @@ int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc) EXEC_QUEUE_FLAG_PERMANENT, 0);if (IS_ERR (q)) {xe_gt_err (gt,"Failed to create queue for GSC submission\n" ); - err =PTR_ERR (q); - goto out_bo; +return PTR_ERR (q); } wq =alloc_ordered_workqueue ("gsc-ordered-wq" ,0 );
@@ -511,8 +510,6 @@ int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc) out_q:xe_exec_queue_put (q); -out_bo: -xe_bo_unpin_map_no_vm (bo);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 316/377 drm/xe/vf: Fix signature of print functions
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Wajdeczko <[email protected]>
[ Upstream commit 9bb2f1d7e6e58b8e434ddc2048c661bf87ccdf2a ]
We have plugged-in existing VF print functions into our GT debugfs show helper as-is, but we missed that the helper expects functions to return int, while they were defined as void. This can lead to errors being reported when CFI is enabled.
--- drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 24 ++++++++++++++++++------ drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 6 +++--- 2 files changed, 21 insertions(+), 9 deletions(-)
drivers/gpu/drm/xe/xe_gt_sriov_vf.c +18 -6
@@ -1030,13 +1030,15 @@ void xe_gt_sriov_vf_write32(struct xe_gt *gt, struct xe_reg reg, u32 val) }/** -* xe_gt_sriov_vf_print_config - Print VF self config. +* xe_gt_sriov_vf_print_config() - Print VF self config. * @gt: the &xe_gt * @p: the &drm_printer * * This function is for VF use only. +* +* Return: always 0. */ -void xe_gt_sriov_vf_print_config (struct xe_gt *gt,struct drm_printer *p) +int xe_gt_sriov_vf_print_config (struct xe_gt *gt,struct drm_printer *p) {struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config;struct xe_device *xe =gt_to_xe (gt);
@@ -1060,16 +1062,20 @@ void xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p)drm_printf (p,"GuC contexts:\t%u\n" , config->num_ctxs);drm_printf (p,"GuC doorbells:\t%u\n" , config->num_dbs); + +return 0 ; }/** -* xe_gt_sriov_vf_print_runtime - Print VF's runtime regs received from PF. +* xe_gt_sriov_vf_print_runtime() - Print VF's runtime regs received from PF. * @gt: the &xe_gt * @p: the &drm_printer * * This function is for VF use only. +* +* Return: always 0. */ -void xe_gt_sriov_vf_print_runtime (struct xe_gt *gt,struct drm_printer *p) +int xe_gt_sriov_vf_print_runtime (struct xe_gt *gt,struct drm_printer *p) {struct vf_runtime_reg *vf_regs = gt->sriov.vf.runtime.regs;unsigned int size = gt->sriov.vf.runtime.num_regs;
@@ -1078,16 +1084,20 @@ void xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p)for (; size--; vf_regs++)drm_printf (p,"%#x = %#x\n" , vf_regs->offset, vf_regs->value); + +return 0 ; }/** -* xe_gt_sriov_vf_print_version - Print VF ABI versions. +* xe_gt_sriov_vf_print_version() - Print VF ABI versions. * @gt: the &xe_gt * @p: the &drm_printer * * This function is for VF use only. +* +* Return: always 0. */ -void xe_gt_sriov_vf_print_version (struct xe_gt *gt,struct drm_printer *p) +int xe_gt_sriov_vf_print_version (struct xe_gt *gt,struct drm_printer *p) {struct xe_device *xe =gt_to_xe (gt);struct xe_uc_fw_version *guc_version = >->sriov.vf.guc_version;
@@ -1117,4 +1127,6 @@ void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p) GUC_RELAY_VERSION_LATEST_MAJOR, GUC_RELAY_VERSION_LATEST_MINOR);drm_printf (p,"\thandshake:\t%u.%u\n" , pf_version->major, pf_version->minor); + +return 0 ; }
drivers/gpu/drm/xe/xe_gt_sriov_vf.h +3 -3
@@ -35,8 +35,8 @@ s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt);u32 xe_gt_sriov_vf_read32 (struct xe_gt *gt,struct xe_reg reg);void xe_gt_sriov_vf_write32 (struct xe_gt *gt,struct xe_reg reg,u32 val); -void xe_gt_sriov_vf_print_config (struct xe_gt *gt,struct drm_printer *p); -void xe_gt_sriov_vf_print_runtime (struct xe_gt *gt,struct drm_printer *p); -void xe_gt_sriov_vf_print_version (struct xe_gt *gt,struct drm_printer *p); +int xe_gt_sriov_vf_print_config (struct xe_gt *gt,struct drm_printer *p); +int xe_gt_sriov_vf_print_runtime (struct xe_gt *gt,struct drm_printer *p); +int xe_gt_sriov_vf_print_version (struct xe_gt *gt,struct drm_printer *p);#endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 317/377 drm/xe/pf: Fix CFI failure in debugfs access
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mohanram Meenakshisundaram <[email protected]>
[ Upstream commit 96bf49b526e2d03a2b7f6e861925a08f46ed0d28 ]
Reading debugfs file (/sys/kernel/debug/dri/0/gt*/pf/adverse_events) with CFI (Control Flow Integrity) enabled, the kernel panics at xe_gt_debugfs_simple_show+0x82/0xc0.
xe_gt_debugfs_simple_show() declare a function pointer expecting int return type, but xe_gt_sriov_pf_monitor_print_events() is void return type, leading to CFI failure and kernel panic.
[507620.973657] CFI failure at xe_gt_debugfs_simple_show+0x82/0xc0 [xe]
(target: xe_gt_sriov_pf_monitor_print_events+0x0/0x130 [xe]; expected
type: 0xd72c7139)
Fix xe_gt_sriov_pf_monitor_print_events() function by updating to return an int type.
--- drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.c | 6 +++++- drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-)
drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.c +5 -1
@@ -114,8 +114,10 @@ int xe_gt_sriov_pf_monitor_process_guc2pf(struct xe_gt *gt, const u32 *msg, u32* VFs with no events are not printed. * * This function can only be called on PF. +* +* Return: always 0 */ -void xe_gt_sriov_pf_monitor_print_events (struct xe_gt *gt,struct drm_printer *p) +int xe_gt_sriov_pf_monitor_print_events (struct xe_gt *gt,struct drm_printer *p) {unsigned int n, total_vfs =xe_gt_sriov_pf_get_totalvfs (gt);const struct xe_gt_sriov_monitor *data;
@@ -144,4 +146,6 @@ void xe_gt_sriov_pf_monitor_print_events(struct xe_gt *gt, struct drm_printer *p#undef __format#undef __value } + +return 0 ; }
drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.h +1 -1
@@ -13,7 +13,7 @@ struct drm_printer;struct xe_gt ;void xe_gt_sriov_pf_monitor_flr (struct xe_gt *gt,u32 vfid); -void xe_gt_sriov_pf_monitor_print_events (struct xe_gt *gt,struct drm_printer *p); +int xe_gt_sriov_pf_monitor_print_events (struct xe_gt *gt,struct drm_printer *p);#ifdef CONFIG_PCI_IOV int xe_gt_sriov_pf_monitor_process_guc2pf (struct xe_gt *gt,const u32 *msg,u32 len);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 318/377 wifi: ath11k: fix peer resolution on rx path when peer_id=0
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Leach <[email protected]>
[ Upstream commit 2a2451a34afdf563b3102d36a4b6cf335cf813e2 ]
It has been observed that on certain chipsets a peer can be assigned peer_id=0. For reception of non-aggregated MPDUs this is fine as ath11k_dp_rx_h_find_peer() has a fallback case where it locates the peer based upon the source MAC address. On an aggregated link, the mpdu_start header is only populated by hardware on the first sub-MSDU. This causes the peer resolution to be skipped for the subsequent MSDUs and the encryption type of these frames to be set to an incorrect value, resulting in these MSDUs being dropped by ieee80211.
ath11k_pci 0000:03:00.0: data rx skb 000000002f4b704d len 1534 peer xx:xx:xx:xx:xx:xx 0 ucast sn 3063 he160 rate_idx 9 vht_nss 2 freq 5240 band 1 flag 0x40d1a fcs-err 0 mic-err 0 amsdu-more 0 peer_id 0 first_msdu 1 last_msdu 0 ath11k_pci 0000:03:00.0: data rx skb 0000000038acd580 len 1534 peer (null) 0 ucast sn 3063 he160 rate_idx 9 vht_nss 2 freq 5240 band 1 flag 0x40d00 fcs-err 0 mic-err 0 amsdu-more 0 peer_id 0 first_msdu 0 last_msdu 1
Remove the null peer_id checks in ath11k_dp_rx_h_find_peer() and ath11k_hal_rx_parse_mon_status_tlv(), allowing peers with an assigned ID of 0 to be resolved.
Tested-on: QCA2066 hw2.1 PCI WLAN.HSP.1.1-03926.13-QCAHSPSWPL_V2_SILICONZ_CE-2.52297.9
--- drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +-- drivers/net/wireless/ath/ath11k/hal_rx.c | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-)
drivers/net/wireless/ath/ath11k/dp_rx.c +1 -2
@@ -2214,8 +2214,7 @@ ath11k_dp_rx_h_find_peer(struct ath11k_base *ab, struct sk_buff *msdu)lockdep_assert_held (&ab->base_lock); -if (rxcb->peer_id) - peer =ath11k_peer_find_by_id (ab, rxcb->peer_id); + peer =ath11k_peer_find_by_id (ab, rxcb->peer_id);if (peer)return peer;
drivers/net/wireless/ath/ath11k/hal_rx.c +1 -4
@@ -1467,11 +1467,8 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,case HAL_RX_MPDU_START : {struct hal_rx_mpdu_info *mpdu_info = (struct hal_rx_mpdu_info *)tlv_data; -u16 peer_id; - peer_id =ath11k_hal_rx_mpduinfo_get_peerid (ab, mpdu_info); -if (peer_id) - ppdu_info->peer_id = peer_id; + ppdu_info->peer_id =ath11k_hal_rx_mpduinfo_get_peerid (ab, mpdu_info);break ; }case HAL_RXPCU_PPDU_END_INFO : {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 319/377 drm/mediatek: mtk_cec: Fix non-static global variable
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Louis-Alexis Eyraud <[email protected]>
[ Upstream commit 571f00a5fb725984049bd532ee8193cc34ff2994 ]
The struct 'mtk_cec_driver' is not used outside of the mtk_cec.c file, so make it static to silence sparse warning:
``` drivers/gpu/drm/mediatek/mtk_cec.c:243:24: sparse: warning: symbol 'mtk_cec_driver' was not declared. Should it be static? ```
--- drivers/gpu/drm/mediatek/mtk_cec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/mediatek/mtk_cec.c +1 -1
@@ -240,7 +240,7 @@ static const struct of_device_id mtk_cec_of_ids[] = { };MODULE_DEVICE_TABLE (of, mtk_cec_of_ids); -struct platform_driver mtk_cec_driver = { +static struct platform_driver mtk_cec_driver = { .probe = mtk_cec_probe, .remove = mtk_cec_remove, .driver = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 320/377 drm/mediatek: mtk_hdmi_ddc: Fix non-static global variable
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Louis-Alexis Eyraud <[email protected]>
[ Upstream commit 87ed4e845d5a90bba1a56c0a5c580a13982e8648 ]
The struct 'mtk_hdmi_ddc_driver' is not used outside of the mtk_hdmi_ddc.c file, so make it static to silence sparse warning:
``` drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c:331:24: sparse: warning: symbol 'mtk_hdmi_ddc_driver' was not declared. Should it be static? ```
--- drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c +1 -1
@@ -328,7 +328,7 @@ static const struct of_device_id mtk_hdmi_ddc_match[] = { };MODULE_DEVICE_TABLE (of, mtk_hdmi_ddc_match); -struct platform_driver mtk_hdmi_ddc_driver = { +static struct platform_driver mtk_hdmi_ddc_driver = { .probe = mtk_hdmi_ddc_probe, .remove = mtk_hdmi_ddc_remove, .driver = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 321/377 cgroup/rstat: validate cpu before css_rstat_cpu() access
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qing Ming <[email protected]>
[ Upstream commit 8817005efbdfdf5d4e4814cb5dc52b53d12917d7 ]
css_rstat_updated() is exposed as a BPF kfunc and accepts a caller-provided cpu argument. The function uses cpu for per-cpu rstat lookups without checking whether it refers to a valid possible CPU.
A BPF iter/cgroup program with CAP_BPF and CAP_PERFMON can pass an invalid cpu value. On an unfixed UBSCAN_BOUNDS test kernel, cpu == 0x7fffffff triggers:
UBSAN: array-index-out-of-bounds in kernel/cgroup/rstat.c:31:9
index 2147483647 is out of range for type 'long unsigned int [64]'
Call Trace:
css_rstat_updated
bpf_iter_run_prog
cgroup_iter_seq_show
bpf_seq_readAdd cpu validation to the BPF-facing css_rstat_updated() kfunc and move the common implementation to __css_rstat_updated() for in-kernel callers.
--- block/blk-cgroup.c | 2 +- include/linux/cgroup.h | 1 + kernel/cgroup/rstat.c | 30 ++++++++++++++++++++---------- mm/memcontrol.c | 6 +++--- 4 files changed, 25 insertions(+), 14 deletions(-)
block/blk-cgroup.c +1 -1
@@ -2241,7 +2241,7 @@ void blk_cgroup_bio_start(struct bio *bio) }u64_stats_update_end_irqrestore (&bis->sync, flags); -css_rstat_updated (&blkcg->css, cpu); +__css_rstat_updated (&blkcg->css, cpu);put_cpu (); }
include/linux/cgroup.h +1 -0
@@ -713,6 +713,7 @@ static inline void cgroup_path_from_kernfs_id(u64 id, char *buf, size_t buflen)/* * cgroup scalable recursive statistics. */ +void __css_rstat_updated (struct cgroup_subsys_state *css,int cpu);void css_rstat_updated (struct cgroup_subsys_state *css,int cpu);void css_rstat_flush (struct cgroup_subsys_state *css);
kernel/cgroup/rstat.c +20 -10
@@ -1,6 +1,7 @@// SPDX-License-Identifier: GPL-2.0-only #include "cgroup-internal.h" +#include <linux/cpumask.h> #include <linux/sched/cputime.h> #include <linux/bpf.h>
@@ -53,7 +54,7 @@ static inline struct llist_head *ss_lhead_cpu(struct cgroup_subsys *ss, int cpu) }/** -* css_rstat_updated - keep track of updated rstat_cpu +* __css_rstat_updated - keep track of updated rstat_cpu * @css: target cgroup subsystem state * @cpu: cpu on which rstat_cpu was updated *
@@ -63,20 +64,17 @@ static inline struct llist_head *ss_lhead_cpu(struct cgroup_subsys *ss, int cpu)* * NOTE: if the user needs the guarantee that the updater either add itself in * the lockless list or the concurrent flusher flushes its updated stats, a -* memory barrier is needed before the call to css_rstat_updated() i.e. a +* memory barrier is needed before the call to __css_rstat_updated() i.e. a * barrier after updating the per-cpu stats and before calling -* css_rstat_updated(). +* __css_rstat_updated(). */ -__bpf_kfunc void css_rstat_updated(struct cgroup_subsys_state *css, int cpu) +void __css_rstat_updated (struct cgroup_subsys_state *css,int cpu) {struct llist_head *lhead;struct css_rstat_cpu *rstatc;struct llist_node *self; -/* -* Since bpf programs can call this function, prevent access to -* uninitialized rstat pointers. -*/ +/* Prevent access to uninitialized rstat pointers. */ if (!css_uses_rstat (css))return ;
@@ -125,6 +123,18 @@ __bpf_kfunc void css_rstat_updated(struct cgroup_subsys_state *css, int cpu)llist_add (&rstatc->lnode, lhead); } +/* +* BPF-facing wrapper for __css_rstat_updated(). Validate the caller-provided +* CPU before passing it to the internal rstat updater. +*/ +__bpf_kfunc void css_rstat_updated(struct cgroup_subsys_state *css, int cpu) +{ +if (unlikely (cpu <0 || cpu >= nr_cpu_ids || !cpu_possible (cpu))) +return ; + +__css_rstat_updated (css, cpu); +} +static void __css_process_update_tree (struct cgroup_subsys_state *css,int cpu) {/* put @css and all ancestors on the corresponding updated lists */
@@ -170,7 +180,7 @@ static void css_process_update_tree(struct cgroup_subsys *ss, int cpu)* flusher flush the stats updated by the updater who have * observed that they are already on the list. The * corresponding barrier pair for this one should be before -* css_rstat_updated() by the user. +* __css_rstat_updated() by the user. * * For now, there aren't any such user, so not adding the * barrier here but if such a use-case arise, please add
@@ -614,7 +624,7 @@ static void cgroup_base_stat_cputime_account_end(struct cgroup *cgrp, unsigned long flags) {u64_stats_update_end_irqrestore (&rstatbc->bsync, flags); -css_rstat_updated (&cgrp->self,smp_processor_id ()); +__css_rstat_updated (&cgrp->self,smp_processor_id ());put_cpu_ptr (rstatbc); }
mm/memcontrol.c +3 -3
@@ -571,7 +571,7 @@ static inline void memcg_rstat_updated(struct mem_cgroup *memcg, int val,if (!val)return ; -css_rstat_updated (&memcg->css, cpu); +__css_rstat_updated (&memcg->css, cpu); statc_pcpu = memcg->vmstats_percpu;for (; statc_pcpu; statc_pcpu = statc->parent_pcpu) { statc =this_cpu_ptr (statc_pcpu);
@@ -2525,7 +2525,7 @@ static inline void account_slab_nmi_safe(struct mem_cgroup *memcg,struct mem_cgroup_per_node *pn = memcg->nodeinfo[pgdat->node_id];/* preemption is disabled in_nmi(). */ -css_rstat_updated (&memcg->css,smp_processor_id ()); +__css_rstat_updated (&memcg->css,smp_processor_id ());if (idx ==NR_SLAB_RECLAIMABLE_B )atomic_add (nr, &pn->slab_reclaimable);else
@@ -2749,7 +2749,7 @@ static inline void account_kmem_nmi_safe(struct mem_cgroup *memcg, int val)mod_memcg_state (memcg,MEMCG_KMEM , val); }else {/* preemption is disabled in_nmi(). */ -css_rstat_updated (&memcg->css,smp_processor_id ()); +__css_rstat_updated (&memcg->css,smp_processor_id ());atomic_add (val, &memcg->kmem_stat); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 322/377 ice: ptp: serialize E825 PHY timer start with PTP lock
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Grzegorz Nitka <[email protected]>
[ Upstream commit 781ff8f2d575a794a2a4f11605288ae06757f5eb ]
ice_start_phy_timer_eth56g() programs TIMETUS registers and issues INIT_INCVAL without holding the global PTP semaphore.
This allows concurrent PTP command paths to interleave with PHY timer start, which can make the sequence fail and leave timer initialization inconsistent.
Take the PTP lock around TIMETUS registers programming and INIT_INCVAL command execution, and make sure the lock is released on all error paths.
Keep the subsequent sync step outside of this critical section, since ice_sync_phy_timer_eth56g() takes the same semaphore internally.
--- drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/net/ethernet/intel/ice/ice_ptp_hw.c +13 -2
@@ -2141,16 +2141,23 @@ int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port) } incval = (u64 )hi <<32 | lo; +if (!ice_ptp_lock (hw)) { +dev_err (ice_hw_to_dev (hw),"Failed to acquire PTP semaphore\n" ); +return -EBUSY ; + } + err =ice_write_40b_ptp_reg_eth56g (hw, port,PHY_REG_TIMETUS_L , incval);if (err) -return err; + goto err_ptp_unlock; err =ice_ptp_one_port_cmd (hw, port,ICE_PTP_INIT_INCVAL );if (err) -return err; + goto err_ptp_unlock;ice_ptp_exec_tmr_cmd (hw); +ice_ptp_unlock (hw); + err =ice_sync_phy_timer_eth56g (hw, port);if (err)return err;
@@ -2166,6 +2173,10 @@ int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port)ice_debug (hw,ICE_DBG_PTP ,"Enabled clock on PHY port %u\n" , port);return 0 ; + +err_ptp_unlock: +ice_ptp_unlock (hw); +return err; }/**
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 323/377 ice: ptp: use primary NAC semaphore on E825
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Grzegorz Nitka <[email protected]>
[ Upstream commit 7b28523546c7e4adbb8436f2986efcfc8382985e ]
For E825 2xNAC configurations, PTP semaphore operations must hit the primary NAC register block so both sides coordinate on the same lock.
Commit e2193f9f9ec9 ("ice: enable timesync operation on 2xNAC E825 devices") updated other primary-only PTP register accesses to use the primary NAC on non-primary functions, but left ice_ptp_lock() and ice_ptp_unlock() operating on the local NAC. As a result, secondary NAC PTP paths can take a different semaphore than the primary side.
Select the primary hardware in ice_ptp_lock() and ice_ptp_unlock() when the current function is not primary, keeping semaphore operations symmetric and consistent with the rest of the 2xNAC PTP register access path.
--- drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/net/ethernet/intel/ice/ice_ptp_hw.c +9 -0
@@ -5264,9 +5264,13 @@ static void ice_ptp_init_phy_e830(struct ice_ptp_hw *ptp)*/ bool ice_ptp_lock (struct ice_hw *hw) { + struct ice_pf *pf = container_of(hw, struct ice_pf, hw);u32 hw_lock;int i; +if (!ice_is_primary (hw)) + hw =ice_get_primary_hw (pf); +#define MAX_TRIES 15for (i =0 ; i <MAX_TRIES ; i++) {
@@ -5293,6 +5297,11 @@ bool ice_ptp_lock(struct ice_hw *hw)*/ void ice_ptp_unlock (struct ice_hw *hw) { + struct ice_pf *pf = container_of(hw, struct ice_pf, hw); + +if (!ice_is_primary (hw)) + hw =ice_get_primary_hw (pf); +wr32 (hw,PFTSYN_SEM + (PFTSYN_SEM_BYTES * hw->pf_id),0 ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 324/377 igc: set tx buffer type for SMD frames
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kohei Enju <[email protected]>
[ Upstream commit 5acc641e590e008caaed480ed9ffae47cf7ecbdf ]
Sashiko pointed out that igc_fpe_init_smd_frame() initializes igc_tx_buffer fields for an SMD skb, but does not set the buffer type:
https://sashiko.dev/#/patchset/20260415025226.114115-1-kohei%40enjuk.jp
Since igc_tx_buffer entries are reused, a stale XDP or XSK type can remain and make TX completion use the wrong cleanup path.
Set the buffer type to IGC_TX_BUFFER_TYPE_SKB.
--- drivers/net/ethernet/intel/igc/igc_tsn.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/intel/igc/igc_tsn.c +1 -0
@@ -34,6 +34,7 @@ static int igc_fpe_init_smd_frame(struct igc_ring *ring,return -ENOMEM ; } + buffer->type =IGC_TX_BUFFER_TYPE_SKB ; buffer->skb = skb; buffer->protocol =0 ; buffer->bytecount = skb->len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 325/377 drm/i915/dp: Fix readback for target_rr in Adaptive Sync SDP
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ankit Nautiyal <[email protected]>
[ Upstream commit f87abd0c6604fb6cc31cc86fc7ccc6a576924352 ]
Correct the bit-shift logic to properly readback the 10 bit target_rr from DB3 and DB4.
v2: Align the style with readback for vtotal. (Ville)
--- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/i915/display/intel_dp.c +1 -1
@@ -4899,7 +4899,7 @@ int intel_dp_as_sdp_unpack(struct drm_dp_as_sdp *as_sdp, as_sdp->length = sdp->sdp_header.HB3 &DP_ADAPTIVE_SYNC_SDP_LENGTH ; as_sdp->mode = sdp->db[0 ] &DP_ADAPTIVE_SYNC_SDP_OPERATION_MODE ; as_sdp->vtotal = (sdp->db[2 ] <<8 ) | sdp->db[1 ]; - as_sdp->target_rr = (u64 )sdp->db[3 ] | ((u64 )sdp->db[4 ] &0x3 ); + as_sdp->target_rr = ((sdp->db[4 ] &0x3 ) <<8 ) | sdp->db[3 ]; as_sdp->target_rr_divider = sdp->db[4 ] &0x20 ? true : false;return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 326/377 kbuild: pacman-pkg: make "rc" releases adhere to pacman versioning scheme
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Viktor Jägersküpper <[email protected]>
[ Upstream commit 202550713128da20d9381d6d2dc0f6b73839f434 ]
The package versioning scheme does not enable smooth upgrades from "rc" releases to the corresponding stable releases (e.g. 7.0.0-rc7 -> 7.0.0) because pacman considers that a downgrade due to the underscore in pkgver (e.g. 7.0.0_rc7), see e.g. vercmp(8) for an explanation of the package version comparison used by pacman. Package versions which are derived from said releases (e.g. built from git revisions) are similarly affected. Fix this by modifying pkgver in order to remove the hyphen from kernel versions containing "-rcN", where N is a non-negative integer.
--- scripts/package/PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
scripts/package/PKGBUILD +1 -1
@@ -10,7 +10,7 @@ for pkg in $_extrapackages; do pkgname+=("${pkgbase}-${pkg}") done -pkgver="${KERNELRELEASE//-/_}" +pkgver="$(echo "${KERNELRELEASE}" | sed 's/-\(rc[0-9]\+\)/\1/;s/-/_/g')" # The PKGBUILD is evaluated multiple times. # Running scripts/build-version from here would introduce inconsistencies. pkgrel="${KBUILD_REVISION}"
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 327/377 net: dsa: mt7530: fix FDB entries not aging out with short timeout
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Golle <[email protected]>
[ Upstream commit e824e40d0e841fab66ab7897d6c7b14dc81c66a7 ]
The DSA forwarding selftests bridge_vlan_aware.sh and bridge_vlan_unaware.sh configure the bridge with ageing_time set to LOW_AGEING_TIME (1000 centiseconds, i.e. 10 seconds) and then run learning_test() in lib.sh, which expects a learned FDB entry to be removed after ageing_time + 10 seconds. On MT7530/MT7531 the entry persisted past the deadline and the "Found FDB record when should not" assertion failed.
With msecs=10000, the algorithm in mt7530_set_ageing_time() finds AGE_CNT=0 and AGE_UNIT=9 as the first exact match (starting the search from tmp_age_count=0). The per-entry aging counter is initialized to AGE_CNT when a MAC address is learned, so with AGE_CNT=0 new entries start with a counter value of 0, which the hardware treats as "already aged" and never removes, effectively disabling aging.
Fix this by starting the search from tmp_age_count=1 to ensure entries always have a non-zero initial aging counter. For a 10-second ageing time this yields AGE_CNT=1 and AGE_UNIT=4 instead:
the timer ticks every 5 seconds and entries are removed after 2 ticks.
Starting the search at AGE_CNT=1 raises the minimum representable ageing time from 1 to 2 seconds. Without bounds, a stale ageing_time of 1 second would now make the loop fall through without setting age_count and age_unit, leaving them uninitialized when written to the MT7530_AAC hardware register. Set ds->ageing_time_min and ds->ageing_time_max so the DSA core validates the range before the callback is invoked, and drop the now-redundant range check from mt7530_set_ageing_time().
--- drivers/net/dsa/mt7530.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
drivers/net/dsa/mt7530.c +14 -6
@@ -973,12 +973,16 @@ mt7530_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)unsigned int age_count;unsigned int age_unit; -/* Applied timer is (AGE_CNT + 1) * (AGE_UNIT + 1) seconds */ -if (secs <1 || secs > (AGE_CNT_MAX +1 ) * (AGE_UNIT_MAX +1 )) -return -ERANGE ; - -/* iterate through all possible age_count to find the closest pair */ -for (tmp_age_count =0 ; tmp_age_count <=AGE_CNT_MAX ; ++tmp_age_count) { +/* Applied timer is (AGE_CNT + 1) * (AGE_UNIT + 1) seconds. +* The DSA core has already validated the range using +* ds->ageing_time_min and ds->ageing_time_max. +* +* Iterate through all possible age_count values to find the closest +* pair. Start from 1 because the per-entry aging counter is +* initialized to AGE_CNT and a value of 0 means the entry will +* never be aged out. +*/ +for (tmp_age_count =1 ; tmp_age_count <=AGE_CNT_MAX ; ++tmp_age_count) {unsigned int tmp_age_unit = secs / (tmp_age_count +1 ) -1 ;if (tmp_age_unit <=AGE_UNIT_MAX ) {
@@ -2378,6 +2382,8 @@ mt7530_setup(struct dsa_switch *ds) ds->assisted_learning_on_cpu_port = true; ds->mtu_enforcement_ingress = true; + ds->ageing_time_min =2 *1000 ; + ds->ageing_time_max = (AGE_CNT_MAX +1 ) * (AGE_UNIT_MAX +1 ) *1000 ;if (priv->id ==ID_MT7530 ) {regulator_set_voltage (priv->core_pwr,1000000 ,1000000 );
@@ -2567,6 +2573,8 @@ mt7531_setup_common(struct dsa_switch *ds) ds->assisted_learning_on_cpu_port = true; ds->mtu_enforcement_ingress = true; + ds->ageing_time_min =2 *1000 ; + ds->ageing_time_max = (AGE_CNT_MAX +1 ) * (AGE_UNIT_MAX +1 ) *1000 ;mt753x_trap_frames (priv);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 328/377 net: dsa: mt7530: preserve VLAN tags on trapped link-local frames
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Golle <[email protected]>
[ Upstream commit 3ac85bcfd404b588298c95c6fba8aad4ad334f57 ]
The BPC, RGAC1 and RGAC2 registers control the handling of link-local frames with reserved MAC DAs (01:80:C2:00:00:0x). These frames are correctly trapped to the CPU port, but the egress VLAN tag attribute was set to MT7530_VLAN_EG_UNTAGGED which causes the switch to strip any VLAN tags from trapped frames before they reach the CPU.
This causes VLAN-tagged link-local frames (STP BPDUs, LLDP, PTP Peer Delay Requests) to arrive at the CPU without their VLAN tag, so they are delivered to the base network interface instead of the VLAN sub-interface. The DSA local_termination selftest confirms this: all link-local protocol tests on VLAN upper interfaces fail.
Set the EG_TAG attribute to MT7530_VLAN_EG_DISABLED (system default) so that the switch does not modify VLAN tags in trapped frames. This way VLAN-tagged frames retain their original tag and are delivered to the correct VLAN sub-interface, matching the behavior of non-trapped frames which pass through without VLAN tag modification.
--- drivers/net/dsa/mt7530.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-)
drivers/net/dsa/mt7530.c +15 -12
@@ -1250,37 +1250,40 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)static void mt753x_trap_frames (struct mt7530_priv *priv) { -/* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress them -* VLAN-untagged. +/* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress +* them with the EG_TAG attribute set to disabled (system default) +* so that any VLAN tags in the frame are not modified by the +* switch egress VLAN tag processing. This preserves VLAN tags +* for reception on VLAN sub-interfaces. */ mt7530_rmw (priv,MT753X_BPC ,PAE_BPDU_FR |PAE_EG_TAG_MASK |PAE_PORT_FW_MASK |BPDU_EG_TAG_MASK |BPDU_PORT_FW_MASK , -PAE_BPDU_FR |PAE_EG_TAG (MT7530_VLAN_EG_UNTAGGED ) | +PAE_BPDU_FR |PAE_EG_TAG (MT7530_VLAN_EG_DISABLED ) |PAE_PORT_FW (TO_CPU_FW_CPU_ONLY ) | -BPDU_EG_TAG (MT7530_VLAN_EG_UNTAGGED ) | +BPDU_EG_TAG (MT7530_VLAN_EG_DISABLED ) |TO_CPU_FW_CPU_ONLY ); -/* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and egress -* them VLAN-untagged. +/* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and +* egress them with EG_TAG disabled. */ mt7530_rmw (priv,MT753X_RGAC1 ,R02_BPDU_FR |R02_EG_TAG_MASK |R02_PORT_FW_MASK |R01_BPDU_FR |R01_EG_TAG_MASK |R01_PORT_FW_MASK , -R02_BPDU_FR |R02_EG_TAG (MT7530_VLAN_EG_UNTAGGED ) | +R02_BPDU_FR |R02_EG_TAG (MT7530_VLAN_EG_DISABLED ) |R02_PORT_FW (TO_CPU_FW_CPU_ONLY ) |R01_BPDU_FR | -R01_EG_TAG (MT7530_VLAN_EG_UNTAGGED ) | +R01_EG_TAG (MT7530_VLAN_EG_DISABLED ) |TO_CPU_FW_CPU_ONLY ); -/* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and egress -* them VLAN-untagged. +/* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and +* egress them with EG_TAG disabled. */ mt7530_rmw (priv,MT753X_RGAC2 ,R0E_BPDU_FR |R0E_EG_TAG_MASK |R0E_PORT_FW_MASK |R03_BPDU_FR |R03_EG_TAG_MASK |R03_PORT_FW_MASK , -R0E_BPDU_FR |R0E_EG_TAG (MT7530_VLAN_EG_UNTAGGED ) | +R0E_BPDU_FR |R0E_EG_TAG (MT7530_VLAN_EG_DISABLED ) |R0E_PORT_FW (TO_CPU_FW_CPU_ONLY ) |R03_BPDU_FR | -R03_EG_TAG (MT7530_VLAN_EG_UNTAGGED ) | +R03_EG_TAG (MT7530_VLAN_EG_DISABLED ) |TO_CPU_FW_CPU_ONLY ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 329/377 net: mana: Fix TOCTOU double-fetch of hwc_msg_id from DMA buffer
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Erni Sri Satya Vennela <[email protected]>
[ Upstream commit 35f0f0a2536a4d604b4dbad92c85c4a8fdebb870 ]
In mana_hwc_rx_event_handler(), resp->response.hwc_msg_id is read from DMA-coherent memory and bounds-checked, then mana_hwc_handle_resp() re-reads the same field from the same DMA buffer for test_bit() and pointer arithmetic.
DMA-coherent memory is mapped uncacheable on x86 and is shared, unencrypted, in Confidential VMs (SEV-SNP/TDX), so each load goes directly to host-visible memory. A H/W can modify the value between the check and the use, bypassing the bounds validation.
Fix this by reading hwc_msg_id exactly once using READ_ONCE() into a stack-local variable in mana_hwc_rx_event_handler(), and passing the validated value as a parameter to mana_hwc_handle_resp().
--- .../net/ethernet/microsoft/mana/hw_channel.c | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-)
drivers/net/ethernet/microsoft/mana/hw_channel.c +13 -10
@@ -77,21 +77,19 @@ static int mana_hwc_post_rx_wqe(const struct hwc_wq *hwc_rxq, }static void mana_hwc_handle_resp (struct hw_channel_context *hwc,u32 resp_len, -struct hwc_work_request *rx_req) +struct hwc_work_request *rx_req,u16 msg_id) {const struct gdma_resp_hdr *resp_msg = rx_req->buf_va;struct hwc_caller_ctx *ctx;int err; -if (!test_bit (resp_msg->response.hwc_msg_id, - hwc->inflight_msg_res.map)) { -dev_err (hwc->dev,"hwc_rx: invalid msg_id = %u\n" , - resp_msg->response.hwc_msg_id); +if (!test_bit (msg_id, hwc->inflight_msg_res.map)) { +dev_err (hwc->dev,"hwc_rx: invalid msg_id = %u\n" , msg_id);mana_hwc_post_rx_wqe (hwc->rxq, rx_req);return ; } - ctx = hwc->caller_ctx + resp_msg->response.hwc_msg_id; + ctx = hwc->caller_ctx + msg_id; err =mana_hwc_verify_resp_msg (ctx, resp_msg, resp_len);if (err) goto out;
@@ -251,6 +249,7 @@ static void mana_hwc_rx_event_handler(void *ctx, u32 gdma_rxq_id,struct gdma_sge *sge;u64 rq_base_addr;u64 rx_req_idx; +u16 msg_id;u8 *wqe;if (WARN_ON_ONCE (hwc_rxq->gdma_wq->id != gdma_rxq_id))
@@ -269,13 +268,17 @@ static void mana_hwc_rx_event_handler(void *ctx, u32 gdma_rxq_id, rx_req = &hwc_rxq->msg_buf->reqs[rx_req_idx]; resp = (struct gdma_resp_hdr *)rx_req->buf_va; -if (resp->response.hwc_msg_id >= hwc->num_inflight_msg) { -dev_err (hwc->dev,"HWC RX: wrong msg_id=%u\n" , - resp->response.hwc_msg_id); +/* Read msg_id once from DMA buffer to prevent TOCTOU: +* DMA memory is shared/unencrypted in CVMs - host can +* modify it between reads. +*/ + msg_id =READ_ONCE (resp->response.hwc_msg_id); +if (msg_id >= hwc->num_inflight_msg) { +dev_err (hwc->dev,"HWC RX: wrong msg_id=%u\n" , msg_id);return ; } -mana_hwc_handle_resp (hwc, rx_oob->tx_oob_data_size, rx_req); +mana_hwc_handle_resp (hwc, rx_oob->tx_oob_data_size, rx_req, msg_id);/* Can no longer use 'resp', because the buffer is posted to the HW * in mana_hwc_handle_resp() above.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 330/377 platform/surface: aggregator_registry: omit battery & AC nodes on Surface Laptop 7
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver White <[email protected]>
[ Upstream commit 0488073a6c84571dd3cffe581a4a73a5fceb099d ]
Surface Laptop 7 exposes battery and AC status via Qualcomm PMIC GLINK qcom_battmgr. Registering the standard SSAM battery and AC client devices on this platform causes duplicate power-supply devices to appear.
Drop the SSAM battery and AC nodes from the Surface Laptop 7 registry group so that only the qcom_battmgr power supplies are instantiated.
--- drivers/platform/surface/surface_aggregator_registry.c | 2 -- 1 file changed, 2 deletions(-)
drivers/platform/surface/surface_aggregator_registry.c +0 -2
@@ -295,8 +295,6 @@ static const struct software_node *ssam_node_group_sl6[] = {/* Devices for Surface Laptop 7. */ static const struct software_node *ssam_node_group_sl7[] = { &ssam_node_root, - &ssam_node_bat_ac, - &ssam_node_bat_main, &ssam_node_tmp_perf_profile_with_fan, &ssam_node_fan_speed, &ssam_node_hid_sam_keyboard,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 331/377 platform/x86: adv_swbutton: Check ACPI_HANDLE() against NULL
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit e7a9a6ea40e352cd7977f6a8c80bdeadf65ad838 ]
Every platform driver can be forced to match a device that doesn't match its list of device IDs because of device_match_driver_override(), so platform drivers that rely on the existence of a device's ACPI companion object need to verify its presence.
Accordingly, add a requisite ACPI_HANDLE() check against NULL to the platform/x86 adv_swbutton driver.
--- drivers/platform/x86/adv_swbutton.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/platform/x86/adv_swbutton.c +5 -1
@@ -48,10 +48,14 @@ static int adv_swbutton_probe(struct platform_device *device) {struct adv_swbutton *button;struct input_dev *input; -acpi_handle handle =ACPI_HANDLE (&device->dev); +acpi_handle handle;acpi_status status;int error; + handle =ACPI_HANDLE (&device->dev); +if (!handle) +return -ENODEV ; + button =devm_kzalloc (&device->dev,sizeof (*button),GFP_KERNEL );if (!button)return -ENOMEM ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 332/377 platform/x86: hp_accel: Check ACPI_COMPANION() against NULL
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit abfbe5ee8ae89f1f5449790423d5dd3e423545bd ]
Every platform driver can be forced to match a device that doesn't match its list of device IDs because of device_match_driver_override(), so platform drivers that rely on the existence of a device's ACPI companion object need to verify its presence.
Accordingly, add a requisite ACPI_COMPANION() check against NULL to the platform/x86 hp_accel driver.
--- drivers/platform/x86/hp/hp_accel.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/platform/x86/hp/hp_accel.c +3 -0
@@ -300,6 +300,9 @@ static int lis3lv02d_probe(struct platform_device *device)int ret; lis3_dev.bus_priv =ACPI_COMPANION (&device->dev); +if (!lis3_dev.bus_priv) +return -ENODEV ; + lis3_dev.init = lis3lv02d_acpi_init; lis3_dev.read = lis3lv02d_acpi_read; lis3_dev.write = lis3lv02d_acpi_write;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 333/377 platform/x86: intel-hid: Check ACPI_HANDLE() against NULL
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit 5c69e090ae5dd93d910f70db0796357080707d26 ]
Every platform driver can be forced to match a device that doesn't match its list of device IDs because of device_match_driver_override(), so platform drivers that rely on the existence of a device's ACPI companion object need to verify its presence.
Accordingly, add a requisite ACPI_HANDLE() check against NULL to the platform/x86 intel-hid driver.
--- drivers/platform/x86/intel/hid.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/platform/x86/intel/hid.c +5 -1
@@ -682,12 +682,16 @@ static bool button_array_present(struct platform_device *device)static int intel_hid_probe (struct platform_device *device) { -acpi_handle handle =ACPI_HANDLE (&device->dev);unsigned long long mode, dummy;struct intel_hid_priv *priv; +acpi_handle handle;acpi_status status;int err; + handle =ACPI_HANDLE (&device->dev); +if (!handle) +return -ENODEV ; +intel_hid_init_dsm (handle);if (!intel_hid_evaluate_method (handle,INTEL_HID_DSM_HDMM_FN , &mode)) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 334/377 platform/x86: intel-vbtn: Check ACPI_HANDLE() against NULL
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit a9f305c5a355efeb240d406d378491d9eec02d07 ]
Every platform driver can be forced to match a device that doesn't match its list of device IDs because of device_match_driver_override(), so platform drivers that rely on the existence of a device's ACPI companion object need to verify its presence.
Accordingly, add a requisite ACPI_HANDLE() check against NULL to the platform/x86 intel-vbtn driver.
--- drivers/platform/x86/intel/vbtn.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/platform/x86/intel/vbtn.c +5 -1
@@ -275,12 +275,16 @@ static bool intel_vbtn_has_switches(acpi_handle handle, bool dual_accel)static int intel_vbtn_probe (struct platform_device *device) { -acpi_handle handle =ACPI_HANDLE (&device->dev);bool dual_accel, has_buttons, has_switches;struct intel_vbtn_priv *priv; +acpi_handle handle;acpi_status status;int err; + handle =ACPI_HANDLE (&device->dev); +if (!handle) +return -ENODEV ; + dual_accel =dual_accel_detect (); has_buttons =acpi_has_method (handle,"VBDL" ); has_switches =intel_vbtn_has_switches (handle, dual_accel);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 335/377 ASoC: soc-utils: Add missing va_end in snd_soc_ret()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Robertus Diawan Chris <[email protected]>
[ Upstream commit 298a43b54432fbc3a32949a94c72544ee18c8c00 ]
The default case in snd_soc_ret() use va_start without va_end to cleanup "args" object which can cause undefined behavior. So, add missing va_end to cleanup "args" object.
This is reported by Coverity Scan as "Missing varargs init or cleanup".
--- sound/soc/soc-utils.c | 1 + 1 file changed, 1 insertion(+)
sound/soc/soc-utils.c +1 -0
@@ -36,6 +36,7 @@ int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...) vaf.va = &args;dev_err (dev,"ASoC error (%d): %pV" , ret, &vaf); +va_end (args); }return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 336/377 RDMA/mana_ib: Report max_msg_sz in mana_ib_query_port
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shiraz Saleem <[email protected]>
[ Upstream commit c9a40f6531b81baa9619bcc2697ff86896afcce7 ]
Report max_msg_sz for mana_ib, which is 16MB.
--- drivers/infiniband/hw/mana/main.c | 1 + 1 file changed, 1 insertion(+)
drivers/infiniband/hw/mana/main.c +1 -0
@@ -639,6 +639,7 @@ int mana_ib_query_port(struct ib_device *ibdev, u32 port,if (mana_ib_is_rnic (dev)) { props->gid_tbl_len =16 ; props->ip_gids = true; + props->max_msg_sz =SZ_16M ;if (port ==1 ) props->port_cap_flags =IB_PORT_CM_SUP ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 337/377 RDMA/rtrs: Fix use-after-free in path file creation cleanup
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit 5b74373390113fba798a76b483837029ab010fef ]
In the error path of rtrs_srv_create_path_files(), the sysfs root folders may already have been created and srv_path->kobj may already have been initialized. If a later step fails, the cleanup currently calls kobject_put(&srv_path->kobj) before rtrs_srv_destroy_once_sysfs_root_folders(srv_path).
kobject_put() may drop the last reference to srv_path->kobj and invoke the release callback, rtrs_srv_release(), which frees srv_path. The following call to rtrs_srv_destroy_once_sysfs_root_folders(srv_path) then dereferences srv_path internally to access srv_path->srv, resulting in a use-after-free.
This failure path is reached before rtrs_srv_create_path_files() returns success, so the successful-path lifetime handling is not involved.
Fix this by destroying the sysfs root folders before calling kobject_put(&srv_path->kobj), so srv_path is still valid while the helper accesses it.
This issue was found by a static analysis tool I am developing.
--- drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c +1 -1
@@ -295,8 +295,8 @@ int rtrs_srv_create_path_files(struct rtrs_srv_path *srv_path) put_kobj:kobject_del (&srv_path->kobj); destroy_root: -kobject_put (&srv_path->kobj);rtrs_srv_destroy_once_sysfs_root_folders (srv_path); +kobject_put (&srv_path->kobj);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 338/377 net: bridge: Flush multicast groups when snooping is disabled
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Petr Machata <[email protected]>
[ Upstream commit 68800bbf583f26f71491141e4b3c8582f9cfcbde ]
When forwarding multicast packets, the bridge takes MDB into account when IGMP / MLD snooping is enabled. Currently, when snooping is disabled, the MDB is retained, even though it is not used anymore.
At the same time, during the time that snooping is disabled, the IGMP / MLD control packets are obviously ignored, and after the snooping is reenabled, the administrator has to assume it is out of sync. In particular, missed join and leave messages would lead to traffic being forwarded to wrong interfaces.
Keeping the MDB entries around thus serves no purpose, and just takes memory. Note also that disabling per-VLAN snooping does actually flush the relevant MDB entries.
This patch flushes non-permanent MDB entries as global snooping is disabled.
Stable-dep-of: 4df78ff02629 ("bridge: mcast: Fix a possible use-after-free when removing a bridge port")
--- net/bridge/br_multicast.c | 9 +++++++++ 1 file changed, 9 insertions(+)
net/bridge/br_multicast.c +9 -0
@@ -4640,6 +4640,14 @@ static void br_multicast_start_querier(struct net_bridge_mcast *brmctx,rcu_read_unlock (); } +static void br_multicast_del_grps (struct net_bridge *br) +{ +struct net_bridge_port *port; + +list_for_each_entry (port, &br->port_list, list) +__br_multicast_disable_port_ctx (&port->multicast_ctx); +} +int br_multicast_toggle (struct net_bridge *br,unsigned long val,struct netlink_ext_ack *extack) {
@@ -4660,6 +4668,7 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val,br_opt_toggle (br,BROPT_MULTICAST_ENABLED , !!val);if (!br_opt_get (br,BROPT_MULTICAST_ENABLED )) { change_snoopers = true; +br_multicast_del_grps (br); goto unlock; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 339/377 bridge: mcast: Fix a possible use-after-free when removing a bridge port
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit 4df78ff02629c7729168f0696a7a2123c389818d ]
When per-VLAN multicast snooping is enabled, the bridge iterates over all the bridge ports, disables the per-port multicast context on each port and enables the per-{port, VLAN} multicast contexts instead. The reverse happens when per-VLAN multicast snooping is disabled.
When global multicast snooping is enabled, the bridge iterates over all the bridge ports and enables the per-port multicast context on each port. The reverse happens when multicast snooping is disabled.
The above scheme can result in a situation where both types of contexts (per-port and per-{port, VLAN}) are enabled on a single bridge port:
# ip link add name br1 up type bridge mcast_snooping 1 mcast_querier 1 vlan_filtering 1 # ip link add name dummy1 up master br1 type dummy # ip link set dev br1 type bridge mcast_vlan_snooping 1 # ip link set dev br1 type bridge mcast_snooping 0 # ip link set dev br1 type bridge mcast_snooping 1
This is not intended and it is a problem since the commit cited below. Prior to this commit, when removing a bridge port, br_multicast_disable_port() would disable the per-port multicast context and the per-{port, VLAN} multicast contexts would get disabled when flushing VLANs.
After this commit, br_multicast_disable_port() only disables the per-port multicast context if per-VLAN multicast snooping is disabled. If both types of contexts were enabled on the port when it was removed, the per-port multicast context would remain enabled when freeing the bridge port, leading to a use-after-free [1].
Fix by preventing the bridge from enabling / disabling the per-port multicast contexts when toggling global multicast snooping if per-VLAN multicast snooping is enabled.
[1]
ODEBUG: free active (active state 0) object: ffff88810f8bda78 object type: timer_list hint: br_ip6_multicast_port_query_expired (net/bridge/br_multicast.c:1927)
WARNING: lib/debugobjects.c:629 at debug_print_object+0x1b1/0x3e0, CPU#5: swapper/5/0 [...] Call Trace: <IRQ>
__debug_check_no_obj_freed (lib/debugobjects.c:1116)
kfree (mm/slub.c:2620 mm/slub.c:6250 mm/slub.c:6565) kobject_cleanup (lib/kobject.c:689)rcu_do_batch (kernel/rcu/tree.c:2617)rcu_core (kernel/rcu/tree.c:2869)handle_softirqs (kernel/softirq.c:622)__irq_exit_rcu (kernel/softirq.c:656 kernel/softirq.c:496 kernel/softirq.c:735) irq_exit_rcu (kernel/softirq.c:752)
sysvec_apic_timer_interrupt (arch/x86/kernel/apic/apic.c:1061 (discriminator 47) arch/x86/kernel/apic/apic.c:1061 (discriminator 47)) </IRQ>
--- net/bridge/br_multicast.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-)
net/bridge/br_multicast.c +17 -5
@@ -4640,10 +4640,24 @@ static void br_multicast_start_querier(struct net_bridge_mcast *brmctx,rcu_read_unlock (); } -static void br_multicast_del_grps (struct net_bridge *br) +static void br_multicast_enable_all_ports (struct net_bridge *br) {struct net_bridge_port *port; +if (br_opt_get (br,BROPT_MCAST_VLAN_SNOOPING_ENABLED )) +return ; + +list_for_each_entry (port, &br->port_list, list) +__br_multicast_enable_port_ctx (&port->multicast_ctx); +} + +static void br_multicast_disable_all_ports (struct net_bridge *br) +{ +struct net_bridge_port *port; + +if (br_opt_get (br,BROPT_MCAST_VLAN_SNOOPING_ENABLED )) +return ; +list_for_each_entry (port, &br->port_list, list)__br_multicast_disable_port_ctx (&port->multicast_ctx); }
@@ -4651,7 +4665,6 @@ static void br_multicast_del_grps(struct net_bridge *br)int br_multicast_toggle (struct net_bridge *br,unsigned long val,struct netlink_ext_ack *extack) { -struct net_bridge_port *port;bool change_snoopers = false;int err =0 ;
@@ -4668,7 +4681,7 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val,br_opt_toggle (br,BROPT_MULTICAST_ENABLED , !!val);if (!br_opt_get (br,BROPT_MULTICAST_ENABLED )) { change_snoopers = true; -br_multicast_del_grps (br); +br_multicast_disable_all_ports (br); goto unlock; }
@@ -4676,8 +4689,7 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val, goto unlock;br_multicast_open (br); -list_for_each_entry (port, &br->port_list, list) -__br_multicast_enable_port_ctx (&port->multicast_ctx); +br_multicast_enable_all_ports (br); change_snoopers = true;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 340/377 net: phy: honor eee_disabled_modes in phy_support_eee()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolai Buchwitz <[email protected]>
[ Upstream commit 3655063e083889ed4b79b7dda9cec65478dce09a ]
phy_support_eee() copies supported_eee into advertising_eee unconditionally, overwriting any filtering applied during phy_probe() based on DT eee-broken-* properties or driver-populated eee_disabled_modes. MAC drivers that call phy_support_eee() after probe (e.g. bcmgenet, fec, lan743x, lan78xx, r8169) then cause the PHY to advertise EEE for modes the user marked as broken.
The symptom is that ethtool --show-eee on the local interface reports "not supported" (supported & ~eee_disabled_modes is empty) while the link partner sees EEE negotiated and active.
phy_probe() already filters advertising_eee via eee_disabled_modes after calling of_set_phy_eee_broken(). Apply the same mask in phy_support_eee() so the filtering survives the copy.
--- drivers/net/phy/phy_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/phy/phy_device.c +2 -1
@@ -2818,7 +2818,8 @@ EXPORT_SYMBOL_GPL(phy_advertise_eee_all);*/ void phy_support_eee (struct phy_device *phydev) { -linkmode_copy (phydev->advertising_eee, phydev->supported_eee); +linkmode_andnot (phydev->advertising_eee, phydev->supported_eee, + phydev->eee_disabled_modes); phydev->eee_cfg.tx_lpi_enabled = true; phydev->eee_cfg.eee_enabled = true; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 341/377 net: phy: honor eee_disabled_modes in phy_advertise_eee_all()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolai Buchwitz <[email protected]>
[ Upstream commit 8baa7506d793f0636e3f6f01b01ef7be19674d06 ]
phy_advertise_eee_all() copies supported_eee into advertising_eee unconditionally, overwriting any filtering applied during phy_probe() based on DT eee-broken-* properties or driver-populated eee_disabled_modes. genphy_c45_ethtool_set_eee() calls this helper when user space passes an empty advertisement, undoing the filtering.
Apply the same eee_disabled_modes mask in phy_advertise_eee_all() so the filtering survives the copy, matching the pattern in phy_probe() and phy_support_eee().
--- drivers/net/phy/phy_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/phy/phy_device.c +2 -1
@@ -2792,7 +2792,8 @@ EXPORT_SYMBOL(phy_advertise_supported);*/ void phy_advertise_eee_all (struct phy_device *phydev) { -linkmode_copy (phydev->advertising_eee, phydev->supported_eee); +linkmode_andnot (phydev->advertising_eee, phydev->supported_eee, + phydev->eee_disabled_modes); }EXPORT_SYMBOL_GPL (phy_advertise_eee_all);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 342/377 net: airoha: Fix NPU RX DMA descriptor bits
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Marangi <[email protected]>
[ Upstream commit 0cb5a74faa3bdcfa3b18735d554e12c0f615e35d ]
In an internal review from Airoha, it was notice that the RX DMA descriptor bits and mask are wrong. These values probably refer to an old NPU firmware never published. The previous value works correctly but it was reported that in some specific condition in mixed scenario with both Ethernet and WiFi offload it's possible that RX DMA descriptor signal wrong value with the problem to the RX ring or packets getting dropped.
To handle these specific scenario, apply the new suggested bits mask from Airoha.
Correct functionality of both AN7581 NPU and MT7996 variant were verified and confirmed working.
--- include/linux/soc/airoha/airoha_offload.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
include/linux/soc/airoha/airoha_offload.h +3 -3
@@ -70,9 +70,9 @@ static inline void airoha_ppe_dev_check_skb(struct airoha_ppe_dev *dev,#define NPU_RX1_DESC_NUM 512/* CTRL */ -#define NPU_RX_DMA_DESC_LAST_MASK BIT(27) -#define NPU_RX_DMA_DESC_LEN_MASK GENMASK(26, 14) -#define NPU_RX_DMA_DESC_CUR_LEN_MASK GENMASK(13, 1) +#define NPU_RX_DMA_DESC_LAST_MASK BIT(29) +#define NPU_RX_DMA_DESC_LEN_MASK GENMASK(28, 15) +#define NPU_RX_DMA_DESC_CUR_LEN_MASK GENMASK(14, 1)#define NPU_RX_DMA_DESC_DONE_MASK BIT(0)/* INFO */ #define NPU_RX_DMA_PKT_COUNT_MASK GENMASK(31, 29)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 343/377 pds_core: fix error handling in pdsc_devcmd_wait
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <[email protected]>
[ Upstream commit 0e46b6635b03d29807f810c3b415c4755a3f958d ]
Fix two cases where pdsc_devcmd_wait() returns stale success from the completion register instead of an error:
1. FW crash: If firmware stops running, the wait loop breaks early with running=false. The condition "if ((!done || timeout) && running)" is false, so error handling is bypassed and stale status is returned. Check !running first and return -ENXIO.
2. Timeout: If a command times out, err is set to -ETIMEDOUT but then overwritten by pdsc_err_to_errno(status) which reads stale status. Return -ETIMEDOUT immediately after cleaning up.
Both errors now propagate to pdsc_devcmd_locked() which queues health_work for recovery.
--- drivers/net/ethernet/amd/pds_core/dev.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/net/ethernet/amd/pds_core/dev.c +9 -2
@@ -162,12 +162,19 @@ static int pdsc_devcmd_wait(struct pdsc *pdsc, u8 opcode, int max_seconds)dev_dbg (dev,"DEVCMD %d %s after %ld secs\n" , opcode,pdsc_devcmd_str (opcode), duration /HZ ); -if ((!done || timeout) && running) { +if (!running) { +dev_err (dev,"DEVCMD %d %s fw not running\n" , + opcode,pdsc_devcmd_str (opcode)); +pdsc_devcmd_clean (pdsc); +return -ENXIO ; + } + +if (!done || timeout) {dev_err (dev,"DEVCMD %d %s timeout, done %d timeout %d max_seconds=%d\n" , opcode,pdsc_devcmd_str (opcode), done, timeout, max_seconds); - err = -ETIMEDOUT ;pdsc_devcmd_clean (pdsc); +return -ETIMEDOUT ; } status =pdsc_devcmd_status (pdsc);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 344/377 pds_core: fix debugfs_lookup dentry leak and error handling
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <[email protected]>
[ Upstream commit dc416e32baaeb620b9809e9e25fc7b30889686e9 ]
debugfs_lookup() returns a dentry with an elevated reference count that must be released with dput(). The current code discards the returned dentry without calling dput(), causing a reference leak on every firmware reset recovery.
Additionally, when CONFIG_DEBUG_FS is disabled, debugfs_lookup() returns ERR_PTR(-ENODEV), not NULL. The current check passes for error pointers and would call dput() on an invalid pointer, causing a crash.
--- drivers/net/ethernet/amd/pds_core/debugfs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/net/ethernet/amd/pds_core/debugfs.c +6 -1
@@ -64,9 +64,14 @@ DEFINE_SHOW_ATTRIBUTE(identity);void pdsc_debugfs_add_ident (struct pdsc *pdsc) { +struct dentry *dentry; +/* This file will already exist in the reset flow */ -if (debugfs_lookup ("identity" , pdsc->dentry)) + dentry =debugfs_lookup ("identity" , pdsc->dentry); +if (!IS_ERR_OR_NULL (dentry)) { +dput (dentry);return ; + }debugfs_create_file ("identity" ,0400 , pdsc->dentry, pdsc, &identity_fops);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 345/377 erofs: fix managed cache race for unaligned extents
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gao Xiang <[email protected]>
[ Upstream commit 649932fc3815eda2f24eb4de4b3a5e94886ee0b9 ]
After unaligned compressed extents were introduced, the following race could occur:
[Thread 1] [Thread 2]
(z_erofs_fill_bio_vec)
<handle a Z_EROFS_PREALLOCATED_FOLIO folio>
...filemap_add_folio (1)
(z_erofs_bind_cache)
<the same folio is found..>
..
..folio_attach_private (2)
filemap_add_folio (3) again
Since (1) is executed but (2) hasn't been executed yet, it's possible that another thread finds the same managed folio in z_erofs_bind_cache() for a different pcluster and calls filemap_add_folio() again since folio->private is still Z_EROFS_PREALLOCATED_FOLIO.
Fix this by explicitly clearing folio->private before making the folio visible in the managed cache so that another pcluster can simply wait on the locked managed folio as what we did for other shared cases [1].
This only impacts unaligned data compression (-E48bit with zstd, for example).
[1] Commit 9e2f9d34dd12 ("erofs: handle overlapped pclusters out of crafted images properly") was originally introduced to handle crafted overlapped extents, but it addresses unaligned extents as well.
--- fs/erofs/zdata.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
fs/erofs/zdata.c +8 -7
@@ -1511,8 +1511,15 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec,DBG_BUGON (z_erofs_is_shortlived_page (bvec->bv_page)); folio =page_folio (zbv.page); -/* For preallocated managed folios, add them to page cache here */ +/* +* Preallocated folios are added to the managed cache here rather than +* in z_erofs_bind_cache() in order to keep these folios locked in +* increasing (physical) address order. +* Clear folio->private before these folios become visible to others in +* the managed cache to avoid duplicate additions for unaligned extents. +*/ if (folio->private ==Z_EROFS_PREALLOCATED_FOLIO ) { + folio->private =NULL ; tocache = true; goto out_tocache; }
@@ -1548,14 +1555,8 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec, }return ; } -/* -* Already linked with another pcluster, which only appears in -* crafted images by fuzzers for now. But handle this anyway. -*/ - tocache = false;/* use temporary short-lived pages */ }else {DBG_BUGON (1 );/* referenced managed folios can't be truncated */ - tocache = true; }folio_unlock (folio);folio_put (folio);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 346/377 wifi: mac80211: bounds-check link_id in ieee80211_ml_epcs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandru Hossu <[email protected]>
[ Upstream commit f718506edd2d9c6a308ded9d13c632bf7b7d5a2c ]
IEEE80211_MLE_STA_EPCS_CONTROL_LINK_ID is 0x000f, so link_id extracted from a PRIO_ACCESS ML element PER_STA_PROFILE subelement can be 0..15. sdata->link[] has IEEE80211_MLD_MAX_NUM_LINKS (15) entries (indices 0..14), making index 15 out-of-bounds.
A connected WiFi 7 AP can trigger this by sending an EPCS Enable Response action frame with a PER_STA_PROFILE subelement where link_id = 15. The unsolicited-notification path (dialog_token = 0) is reachable any time EPCS is already enabled, without any prior client request.
sdata->link[15] reads into the first word of sdata->activate_links_work (a wiphy_work whose embedded list_head is non-NULL after INIT_LIST_HEAD), so the NULL check on the result does not catch the invalid access. The garbage pointer is then passed to ieee80211_sta_wmm_params(), which dereferences link->sdata and crashes the kernel.
The same class of bug was fixed for ieee80211_ml_reconfiguration() by commit 162d331d833d ("wifi: mac80211: bounds-check link_id in ieee80211_ml_reconfiguration").
--- net/mac80211/mlme.c | 3 +++ 1 file changed, 3 insertions(+)
net/mac80211/mlme.c +3 -0
@@ -10997,6 +10997,9 @@ static void ieee80211_ml_epcs(struct ieee80211_sub_if_data *sdata, control =get_unaligned_le16 (pos); link_id = control &IEEE80211_MLE_STA_EPCS_CONTROL_LINK_ID ; +if (link_id >=IEEE80211_MLD_MAX_NUM_LINKS ) +continue ; + link =sdata_dereference (sdata->link[link_id], sdata);if (!link)continue ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 347/377 wifi: mac80211: fix MLE defragmentation
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit a74e893f30db64cdce0fc7a96d3baa417bcd55f5 ]
If either reconf or EPCS multi-link element (MLE) is contained in a non-transmitted profile, the defragmentation routine is called with a pointer to the defragmented copy, but the original elements.
This is incorrect for two reasons:
- if the original defragmentation was needed, it will not find the correct data
- if the original frame is at a higher address, the parsing will potentially overrun the heap data (though given the layout of the buffers, only into the new defragmentation buffer, and then it has to stop and fail once that's filled with copied data.
Fix it by tracking the container along with the pointer and in doing so also unify the two almost identical defragmentation routines.
--- net/mac80211/parse.c | 71 +++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 40 deletions(-)
net/mac80211/parse.c +31 -40
@@ -34,6 +34,13 @@#include "led.h" #include "wep.h" +struct ieee80211_elem_defrag { +const struct element *elem; +/* container start/len */ +const u8 *start; +size_t len; +}; +struct ieee80211_elems_parse {/* must be first for kfree to work */ struct ieee802_11_elems elems;
@@ -41,11 +48,7 @@ struct ieee80211_elems_parse {/* The basic Multi-Link element in the original elements */ const struct element *ml_basic_elem; -/* The reconfiguration Multi-Link element in the original elements */ -const struct element *ml_reconf_elem; - -/* The EPCS Multi-Link element in the original elements */ -const struct element *ml_epcs_elem; +struct ieee80211_elem_defrag ml_reconf, ml_epcs;bool multi_link_inner;bool skip_vendor;
@@ -162,10 +165,14 @@ ieee80211_parse_extension_element(u32 *crc, }break ;case IEEE80211_ML_CONTROL_TYPE_RECONF : - elems_parse->ml_reconf_elem = elem; + elems_parse->ml_reconf.elem = elem; + elems_parse->ml_reconf.start = params->start; + elems_parse->ml_reconf.len = params->len;break ;case IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS : - elems_parse->ml_epcs_elem = elem; + elems_parse->ml_epcs.elem = elem; + elems_parse->ml_epcs.start = params->start; + elems_parse->ml_epcs.len = params->len;break ;default :break ;
@@ -950,46 +957,27 @@ ieee80211_prep_mle_link_parse(struct ieee80211_elems_parse *elems_parse, sub->start, sub->len); } -static void -ieee80211_mle_defrag_reconf (struct ieee80211_elems_parse *elems_parse) -{ -struct ieee802_11_elems *elems = &elems_parse->elems; -ssize_t ml_len; - - ml_len =cfg80211_defragment_element (elems_parse->ml_reconf_elem, - elems->ie_start, - elems->total_len, - elems_parse->scratch_pos, - elems_parse->scratch + - elems_parse->scratch_len - - elems_parse->scratch_pos, -WLAN_EID_FRAGMENT ); -if (ml_len <0 ) -return ; - elems->ml_reconf = (void *)elems_parse->scratch_pos; - elems->ml_reconf_len = ml_len; - elems_parse->scratch_pos += ml_len; -} - -static void -ieee80211_mle_defrag_epcs (struct ieee80211_elems_parse *elems_parse) +static const void * +ieee80211_mle_defrag (struct ieee80211_elems_parse *elems_parse, +struct ieee80211_elem_defrag *defrag, +size_t *out_len) { -struct ieee802_11_elems *elems = &elems_parse->elems; +const void *ret;ssize_t ml_len; - ml_len =cfg80211_defragment_element (elems_parse->ml_epcs_elem, - elems->ie_start, - elems->total_len, + ml_len =cfg80211_defragment_element (defrag->elem, + defrag->start, defrag->len, elems_parse->scratch_pos, elems_parse->scratch + elems_parse->scratch_len - elems_parse->scratch_pos,WLAN_EID_FRAGMENT );if (ml_len <0 ) -return ; - elems->ml_epcs = (void *)elems_parse->scratch_pos; - elems->ml_epcs_len = ml_len; +return NULL ; + ret = elems_parse->scratch_pos; + *out_len = ml_len; elems_parse->scratch_pos += ml_len; +return ret; } struct ieee802_11_elems *
@@ -1069,9 +1057,12 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)_ieee802_11_parse_elems_full (&sub, elems_parse,NULL ); } -ieee80211_mle_defrag_reconf (elems_parse); - -ieee80211_mle_defrag_epcs (elems_parse); + elems->ml_reconf =ieee80211_mle_defrag (elems_parse, + &elems_parse->ml_reconf, + &elems->ml_reconf_len); + elems->ml_epcs =ieee80211_mle_defrag (elems_parse, + &elems_parse->ml_epcs, + &elems->ml_epcs_len);if (elems->tim && !elems->parse_error) {const struct ieee80211_tim_ie *tim_ie = elems->tim;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 348/377 wifi: wilc1000: fix dma_buffer leak on bus acquire failure
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shitalkumar Gandhi <[email protected]>
[ Upstream commit dd7b6a8671939708cc4b7a46786d8c11297e8f69 ]
wilc_wlan_firmware_download() allocates dma_buffer with kmalloc() at the top of the function and uses a 'fail:' label to free it via kfree(dma_buffer) on error.
All later error paths correctly use 'goto fail' to route through this cleanup. However, the early failure path after the first acquire_bus() call uses a bare 'return ret;', which leaks dma_buffer whenever the bus acquire fails.
Replace the early return with goto fail so the existing cleanup path runs.
Found via a custom Coccinelle semantic patch hunting for kmalloc'd locals leaked on early-return error paths in driver firmware-download code.
--- drivers/net/wireless/microchip/wilc1000/wlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/microchip/wilc1000/wlan.c +1 -1
@@ -1265,7 +1265,7 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, ret =acquire_bus (wilc,WILC_BUS_ACQUIRE_AND_WAKEUP );if (ret) -return ret; + goto fail; wilc->hif_func->hif_read_reg (wilc,WILC_GLB_RESET_0 , ®); reg &= ~BIT (10 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 349/377 ALSA: seq: Serialize UMP output teardown with event_input
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Cen <[email protected]>
[ Upstream commit 60a1969fae6209644698fca91c185d153674f631 ]
seq_ump_process_event() borrows client->out_rfile.output without synchronizing with the first-open and last-close transition in seq_ump_client_open() and seq_ump_client_close().
The last output unuse can therefore drop opened[STR_OUT] to zero and release the rawmidi file while an in-flight event_input callback is still inside snd_rawmidi_kernel_write(). That leaves the rawmidi substream runtime exposed to teardown before the write path has taken its own buffer reference.
Add a per-client rwlock for the event_input-visible output file. Publish a newly opened output file under the write side, and hold the read side from the output lookup through snd_rawmidi_kernel_write(). The last output close copies and clears the visible output file under the write side, then drops the lock and releases the saved rawmidi file. Use IRQ-safe rwlock guards because event_input can also be reached from atomic sequencer delivery.
The buggy scenario involves two paths, with each column showing the order within that path:
path A label: event_input path path B label: last unuse path
1. seq_ump_process_event() reads 1. seq_ump_client_close()
client->out_rfile.output. drops opened[STR_OUT] to zero.
2. snd_rawmidi_kernel_write1() 2. snd_rawmidi_kernel_release()
has not yet pinned runtime. closes the output file.
3. The writer continues using 3. close_substream() frees
the borrowed substream. substream->runtime.
This keeps the output substream and runtime alive for the full event_input write while keeping rawmidi release outside the rwlock.
KASAN reproduced this as a slab-use-after-free in snd_rawmidi_kernel_write1(), with allocation through seq_ump_use()/snd_seq_port_connect() and free through seq_ump_unuse()/snd_seq_port_disconnect().
Validation reproduced this kernel report:
KASAN slab-use-after-free in snd_rawmidi_kernel_write1+0x9d/0x400
RIP: 0033:0x7f5528af837f Read of size 8 Call trace: dump_stack_lvl+0x73/0xb0 (?:?) print_report+0xd1/0x650 (?:?) srso_alias_return_thunk+0x5/0xfbef5 (?:?) __virt_addr_valid+0x1a7/0x340 (?:?) kasan_complete_mode_report_info+0x64/0x200 (?:?) kasan_report+0xf7/0x130 (?:?) snd_rawmidi_kernel_write1+0x9d/0x400 (?:?) __asan_load8+0x82/0xb0 (?:?) update_stack_state+0x1ef/0x2d0 (?:?) snd_rawmidi_kernel_write+0x1a/0x20 (?:?) seq_ump_process_event+0xd4/0x120 (sound/core/seq/seq_ump_client.c:82) __snd_seq_deliver_single_event+0x8a/0xe0 (?:?) snd_seq_deliver_from_ump+0x2b2/0xd60 (?:?) lock_acquire+0x14e/0x2e0 (?:?) find_held_lock+0x31/0x90 (?:?) snd_seq_port_use_ptr+0xa6/0xe0 (?:?) __kasan_check_write+0x18/0x20 (?:?) do_raw_read_unlock+0x32/0xa0 (?:?) _raw_read_unlock+0x26/0x50 (?:?) snd_seq_deliver_single_event+0x45c/0x4b0 (?:?) snd_seq_deliver_event+0x10d/0x1b0 (?:?) snd_seq_client_enqueue_event+0x192/0x240 (?:?) snd_seq_write+0x2cd/0x450 (?:?) apparmor_file_permission+0x20/0x30 (?:?) security_file_permission+0x51/0x60 (?:?) vfs_write+0x1ce/0x850 (?:?) __fget_files+0x12b/0x220 (?:?) lock_release+0xc8/0x2a0 (?:?) __rcu_read_unlock+0x74/0x2d0 (?:?) __fget_files+0x135/0x220 (?:?) ksys_write+0x15a/0x180 (?:?) rcu_is_watching+0x24/0x60 (?:?) __x64_sys_write+0x46/0x60 (?:?) x64_sys_call+0x7d/0x20d0 (?:?) do_syscall_64+0xc1/0x360 (arch/x86/entry/syscall_64.c:87) entry_SYSCALL_64_after_hwframe+0x77/0x7f (?:?)
--- sound/core/seq/seq_ump_client.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
sound/core/seq/seq_ump_client.c +18 -4
@@ -37,6 +37,7 @@ struct seq_ump_client {struct snd_ump_endpoint *ump;/* assigned endpoint */ int seq_client;/* sequencer client id */ int opened[2 ];/* current opens for each direction */ +rwlock_t output_lock;/* protects out_rfile output access */ struct snd_rawmidi_file out_rfile;/* rawmidi for output */ struct seq_ump_input_buffer input;/* input parser context */ void *ump_info[SNDRV_UMP_MAX_BLOCKS +1 ];/* shadow of seq client ump_info */
@@ -88,6 +89,7 @@ static int seq_ump_process_event(struct snd_seq_event *ev, int direct,unsigned char type;int len; +guard (read_lock_irqsave)(&client->output_lock); substream = client->out_rfile.output;if (!substream)return -ENODEV ;
@@ -106,6 +108,7 @@ static int seq_ump_process_event(struct snd_seq_event *ev, int direct,static int seq_ump_client_open (struct seq_ump_client *client,int dir) {struct snd_ump_endpoint *ump = client->ump; +struct snd_rawmidi_file rfile = {};int err;guard (mutex)(&ump->open_mutex);
@@ -113,9 +116,11 @@ static int seq_ump_client_open(struct seq_ump_client *client, int dir) err =snd_rawmidi_kernel_open (&ump->core,0 ,SNDRV_RAWMIDI_LFLG_OUTPUT |SNDRV_RAWMIDI_LFLG_APPEND , - &client->out_rfile); + &rfile);if (err <0 )return err; +scoped_guard (write_lock_irqsave, &client->output_lock) + client->out_rfile = rfile; } client->opened[dir]++;return 0 ;
@@ -125,11 +130,19 @@ static int seq_ump_client_open(struct seq_ump_client *client, int dir)static int seq_ump_client_close (struct seq_ump_client *client,int dir) {struct snd_ump_endpoint *ump = client->ump; +struct snd_rawmidi_file rfile = {};guard (mutex)(&ump->open_mutex); -if (!--client->opened[dir]) -if (dir ==STR_OUT ) -snd_rawmidi_kernel_release (&client->out_rfile); +if (!--client->opened[dir]) { +if (dir ==STR_OUT ) { + scoped_guard(write_lock_irqsave, &client->output_lock) { + rfile = client->out_rfile; + client->out_rfile = (struct snd_rawmidi_file ){}; + } +if (rfile.rmidi) +snd_rawmidi_kernel_release (&rfile); + } + }return 0 ; }
@@ -468,6 +481,7 @@ static int snd_seq_ump_probe(struct device *_dev)INIT_WORK (&client->group_notify_work, handle_group_notify); client->ump = ump; +rwlock_init (&client->output_lock); client->seq_client = snd_seq_create_kernel_client(card, ump->core.device,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 350/377 cgroup: rstat: relax NMI guard after switch to try_cmpxchg
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cunlong Li <[email protected]>
[ Upstream commit 22572dbcd3486e6c4dced877125bbf50e4e24edf ]
Commit 36df6e3dbd7e ("cgroup: make css_rstat_updated nmi safe") used this_cpu_cmpxchg() for the lockless insertion, and therefore required both ARCH_HAVE_NMI_SAFE_CMPXCHG and ARCH_HAS_NMI_SAFE_THIS_CPU_OPS in the NMI guard: on archs without the latter, this_cpu_cmpxchg() falls back to "local_irq_save() + plain cmpxchg", and local_irq_save() cannot mask NMIs.
Commit 3309b63a2281 ("cgroup: rstat: use LOCK CMPXCHG in css_rstat_updated") later replaced this_cpu_cmpxchg() with plain try_cmpxchg() to fix cross-CPU lockless-list corruption, but left the NMI guard untouched. After that switch, css_rstat_updated() no longer performs any this_cpu_*() RMW operations and only relies on the arch having NMI-safe cmpxchg, so ARCH_HAS_NMI_SAFE_THIS_CPU_OPS is no longer required in the guard.
Relax the guard accordingly so that archs which have HAVE_NMI and ARCH_HAVE_NMI_SAFE_CMPXCHG but not ARCH_HAS_NMI_SAFE_THIS_CPU_OPS (e.g. sparc, powerpc on PPC64/BOOK3S) can benefit from the existing CONFIG_MEMCG_NMI_SAFETY_REQUIRES_ATOMIC path. Without this, the css is never queued in NMI on those archs, and the atomics staged by account_{slab,kmem}_nmi_safe() are not drained by flush_nmi_stats().
--- kernel/cgroup/rstat.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
kernel/cgroup/rstat.c +3 -4
@@ -81,11 +81,10 @@ void __css_rstat_updated(struct cgroup_subsys_state *css, int cpu)lockdep_assert_preemption_disabled ();/* -* For archs withnot nmi safe cmpxchg or percpu ops support, ignore -* the requests from nmi context. +* The lockless insertion below relies on NMI-safe cmpxchg; +* bail out in NMI on archs that don't provide it. */ -if ((!IS_ENABLED (CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG ) || - !IS_ENABLED (CONFIG_ARCH_HAS_NMI_SAFE_THIS_CPU_OPS )) &&in_nmi ()) +if (!IS_ENABLED (CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG ) &&in_nmi ())return ; rstatc =css_rstat_cpu (css, cpu);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 351/377 tracing: Avoid NULL return from hist_field_name() on truncation
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <[email protected]>
[ Upstream commit 576ec047d20b368b43c4d5db98c4f2e0f3c101ec ]
hist_field_name() returns "" everywhere except the fully-qualified VAR_REF/EXPR case, where snprintf() truncation returns NULL early and bypasses the bottom NULL->"" guard. Callers don't expect NULL:strcat(expr, hist_field_name(field, 0)) at trace_events_hist.c:1758 and the strcmp() in the sort-key match loop at :4804 both deref it.
system and event_name are bounded by MAX_EVENT_NAME_LEN, but the field name on a VAR_REF is kstrdup'd from a histogram variable name parsed out of the trigger string and has no length cap, so a long enough var name in a fully qualified reference can reach the truncation path.
Keep the length check but leave field_name as "" on overflow.
--- kernel/trace/trace_events_hist.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
kernel/trace/trace_events_hist.c +2 -4
@@ -1360,10 +1360,8 @@ static const char *hist_field_name(struct hist_field *field, len =snprintf (full_name,sizeof (full_name),"%s.%s.%s" , field->system, field->event_name, field->name); -if (len >=sizeof (full_name)) -return NULL ; - - field_name = full_name; +if (len <sizeof (full_name)) + field_name = full_name; }else field_name = field->name; }else if (field->flags &HIST_FIELD_FL_TIMESTAMP )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 352/377 Bluetooth: btintel_pcie: Fix incorrect MAC access programming
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kiran K <[email protected]>
[ Upstream commit 88365d04fdc821dc4e9eb0cc00fdf6905430d172 ]
btintel_pcie_get_mac_access() and btintel_pcie_release_mac_access() were programming STOP_MAC_ACCESS_DIS and XTAL_CLK_REQ in addition to the MAC_ACCESS_REQ handshake. These bits are not part of the host MAC-access handshake on the supported parts; the driver was programming them incorrectly. Drop the writes so the register update contains only the bits the controller actually consumes.
--- drivers/bluetooth/btintel_pcie.c | 20 ++++++-------------- drivers/bluetooth/btintel_pcie.h | 3 --- 2 files changed, 6 insertions(+), 17 deletions(-)
drivers/bluetooth/btintel_pcie.c +6 -14
@@ -567,12 +567,10 @@ static int btintel_pcie_get_mac_access(struct btintel_pcie_data *data) reg =btintel_pcie_rd_reg32 (data,BTINTEL_PCIE_CSR_FUNC_CTRL_REG ); - reg |=BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS ; - reg |=BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ ; -if ((reg &BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS ) ==0 ) +if (!(reg &BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ )) { reg |=BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ ; - -btintel_pcie_wr_reg32 (data,BTINTEL_PCIE_CSR_FUNC_CTRL_REG , reg); +btintel_pcie_wr_reg32 (data,BTINTEL_PCIE_CSR_FUNC_CTRL_REG , reg); + } do { reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
@@ -592,16 +590,10 @@ static void btintel_pcie_release_mac_access(struct btintel_pcie_data *data) reg =btintel_pcie_rd_reg32 (data,BTINTEL_PCIE_CSR_FUNC_CTRL_REG ); -if (reg &BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ ) +if (reg &BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ ) { reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ ; - -if (reg &BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS ) - reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS ; - -if (reg &BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ ) - reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ ; - -btintel_pcie_wr_reg32 (data,BTINTEL_PCIE_CSR_FUNC_CTRL_REG , reg); +btintel_pcie_wr_reg32 (data,BTINTEL_PCIE_CSR_FUNC_CTRL_REG , reg); + } } static void *btintel_pcie_copy_tlv(void *dest, enum btintel_pcie_tlv_type type,
drivers/bluetooth/btintel_pcie.h +0 -3
@@ -34,9 +34,6 @@#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS (BIT(20))#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ (BIT(21)) -/* Stop MAC Access disconnection request */ -#define BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS (BIT(22)) -#define BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ (BIT(23))#define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_STS (BIT(28))#define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_DISCON (BIT(29))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 353/377 Bluetooth: btmtk: fix urb->setup_packet leak in error paths
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiajia Liu <[email protected]>
[ Upstream commit dd1dda6b8d6e1f4376a5b3055a04f0ecbdb4d6bd ]
The setup_packet of control urb is not freed if usb_submit_urb fails or the submitted urb is killed. Add free in these two paths.
--- drivers/bluetooth/btmtk.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/bluetooth/btmtk.c +2 -0
@@ -496,6 +496,7 @@ static void btmtk_usb_wmt_recv(struct urb *urb)return ; }else if (urb->status == -ENOENT ) {/* Avoid suspend failed when usb_kill_urb */ +kfree (urb->setup_packet);return ; }
@@ -569,6 +570,7 @@ static int btmtk_usb_submit_wmt_recv_urb(struct hci_dev *hdev)if (err != -EPERM && err != -ENODEV )bt_dev_err (hdev,"urb %p submission failed (%d)" , urb, -err); +kfree (dr);usb_unanchor_urb (urb); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 354/377 net/mlx5e: Fix eswitch mode block underflow on IPsec acquire SA
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Prathamesh Deshpande <[email protected]>
[ Upstream commit abe003b33223ff33552f291644bf35d9c2f992fb ]
mlx5e_xfrm_add_state() handles acquire-flow temporary SAs by allocating software state and skipping hardware offload setup.
That path jumps to the common success label before taking the eswitch mode block. After tunnel-mode validation was moved earlier, the common success label unconditionally calls mlx5_eswitch_unblock_mode(). For acquire SAs, this decrements esw->offloads.num_block_mode without a matching increment.
Return directly after installing the acquire SA offload handle, so only the paths that successfully called mlx5_eswitch_block_mode() call the matching unblock.
--- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +4 -3
@@ -794,8 +794,10 @@ static int mlx5e_xfrm_add_state(struct net_device *dev, sa_entry->dev = dev; sa_entry->ipsec = ipsec;/* Check if this SA is originated from acquire flow temporary SA */ -if (x->xso.flags &XFRM_DEV_OFFLOAD_FLAG_ACQ ) - goto out; +if (x->xso.flags &XFRM_DEV_OFFLOAD_FLAG_ACQ ) { + x->xso.offload_handle = (unsigned long )sa_entry; +return 0 ; + } err =mlx5e_xfrm_validate_state (priv->mdev, x, extack);if (err)
@@ -872,7 +874,6 @@ static int mlx5e_xfrm_add_state(struct net_device *dev,xa_unlock_bh (&ipsec->sadb); } -out: x->xso.offload_handle = (unsigned long )sa_entry;if (allow_tunnel_mode)mlx5_eswitch_unblock_encap (priv->mdev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 355/377 net: shaper: annotate the data races
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit a3442936dd0523277e20aaf86207c574e755c634 ]
As previously discussed we don't care about making the shaper state fully RCU-compliant because the hierarchy itself can't be dumped in one go over Netlink. Let's annotate the reads and writes to make that clear.
The field-by-field assignments will also be useful for the next commit which adds explicit "valid" field (which we don't want to override with the current full struct assignment).
Stable-dep-of: b8d7519352ba ("net: shaper: rework the VALID marking (again)")
--- net/shaper/shaper.c | 53 ++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 15 deletions(-)
net/shaper/shaper.c +38 -15
@@ -138,35 +138,58 @@ static int net_shaper_fill_handle(struct sk_buff *msg,return -EMSGSIZE ; } +static void net_shaper_copy (struct net_shaper *dst, +const struct net_shaper *src) +{ +WRITE_ONCE (dst->parent.scope,READ_ONCE (src->parent.scope)); +WRITE_ONCE (dst->parent.id,READ_ONCE (src->parent.id)); +WRITE_ONCE (dst->handle.scope,READ_ONCE (src->handle.scope)); +WRITE_ONCE (dst->handle.id,READ_ONCE (src->handle.id)); + +WRITE_ONCE (dst->metric,READ_ONCE (src->metric)); +WRITE_ONCE (dst->bw_min,READ_ONCE (src->bw_min)); +WRITE_ONCE (dst->bw_max,READ_ONCE (src->bw_max)); +WRITE_ONCE (dst->burst,READ_ONCE (src->burst)); +WRITE_ONCE (dst->priority,READ_ONCE (src->priority)); +WRITE_ONCE (dst->weight,READ_ONCE (src->weight)); + +/* private fields are only used on the write path under the lock */ +data_race (dst->leaves = src->leaves); +} +static int net_shaper_fill_one (struct sk_buff *msg,const struct net_shaper_binding *binding,const struct net_shaper *shaper,const struct genl_info *info) { +struct net_shaper cur;void *hdr; hdr =genlmsg_iput (msg, info);if (!hdr)return -EMSGSIZE ; +/* Make a copy to avoid data races */ +net_shaper_copy (&cur, shaper); +if (net_shaper_fill_binding (msg, binding,NET_SHAPER_A_IFINDEX ) || -net_shaper_fill_handle (msg, &shaper->parent, +net_shaper_fill_handle (msg, &cur.parent,NET_SHAPER_A_PARENT ) || -net_shaper_fill_handle (msg, &shaper->handle, +net_shaper_fill_handle (msg, &cur.handle,NET_SHAPER_A_HANDLE ) || - ((shaper->bw_min || shaper->bw_max || shaper->burst) && -nla_put_u32 (msg,NET_SHAPER_A_METRIC , shaper->metric)) || - (shaper->bw_min && -nla_put_uint (msg,NET_SHAPER_A_BW_MIN , shaper->bw_min)) || - (shaper->bw_max && -nla_put_uint (msg,NET_SHAPER_A_BW_MAX , shaper->bw_max)) || - (shaper->burst && -nla_put_uint (msg,NET_SHAPER_A_BURST , shaper->burst)) || - (shaper->priority && -nla_put_u32 (msg,NET_SHAPER_A_PRIORITY , shaper->priority)) || - (shaper->weight && -nla_put_u32 (msg,NET_SHAPER_A_WEIGHT , shaper->weight))) + ((cur.bw_min || cur.bw_max || cur.burst) && +nla_put_u32 (msg,NET_SHAPER_A_METRIC , cur.metric)) || + (cur.bw_min && +nla_put_uint (msg,NET_SHAPER_A_BW_MIN , cur.bw_min)) || + (cur.bw_max && +nla_put_uint (msg,NET_SHAPER_A_BW_MAX , cur.bw_max)) || + (cur.burst && +nla_put_uint (msg,NET_SHAPER_A_BURST , cur.burst)) || + (cur.priority && +nla_put_u32 (msg,NET_SHAPER_A_PRIORITY , cur.priority)) || + (cur.weight && +nla_put_u32 (msg,NET_SHAPER_A_WEIGHT , cur.weight))) goto nla_put_failure;genlmsg_end (msg, hdr);
@@ -424,7 +447,7 @@ static void net_shaper_commit(struct net_shaper_binding *binding,/* Successful update: drop the tentative mark * and update the hierarchy container. */ - *cur = shapers[i]; +net_shaper_copy (cur, &shapers[i]);smp_wmb ();__xa_set_mark (&hierarchy->shapers, index,NET_SHAPER_VALID ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 356/377 net: shaper: rework the VALID marking (again)
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit b8d7519352ba8c6df83259295d4a3bad093cae90 ]
Recent commit changed the semantics from NOT_VALID to VALID. I didn't realize that the flags are not stored atomically with the entry in XArray. There's still a race of reader observing a VALID mark for a slot, getting interrupted, writer replacing the entry with a different one, reader continuing, fetching the entry which is now a different pointer than the pointer for which VALID was meant.
The biggest consequence of this is that we may see a UAF since net_shaper_rollback() assumed that entries without VALID can be freed without observing RCU.
Looks like the XArray marks are buying us nothing at this point. Let's convert the code to an explicit valid field. The smp_load_acquire() / smp_store_release() barriers are marginally cleaner.
--- include/net/net_shaper.h | 1 + net/shaper/shaper.c | 45 ++++++++++++++++------------------------ 2 files changed, 19 insertions(+), 27 deletions(-)
include/net/net_shaper.h +1 -0
@@ -53,6 +53,7 @@ struct net_shaper {/* private: */ u32 leaves;/* accounted only for NODE scope */ +bool valid;struct rcu_head rcu; };
net/shaper/shaper.c +18 -27
83 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 357/377 crypto/krb5, rxrpc: Fix lack of pre-decrypt/pre-verify length checks
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <[email protected]>
[ Upstream commit 2b50aceafe6606ea52ed42aadd1b4d44a188aade ]
Change the krb5 crypto library to provide facilities to precheck the length of the message about to be decrypted or verified.
Fix AF_RXRPC to make use of this to validate DATA packets secured with RxGK.
--- Documentation/crypto/krb5.rst | 17 ++++++++--- crypto/krb5/krb5_api.c | 54 +++++++++++++++++++++++++++++++---- include/crypto/krb5.h | 9 ++++-- include/trace/events/rxrpc.h | 1 + net/rxrpc/rxgk.c | 15 ++++++++-- 5 files changed, 81 insertions(+), 15 deletions(-)
Documentation/crypto/krb5.rst +13 -4
@@ -158,13 +158,22 @@ returned. When a message has been received, the location and size of the data with the message can be determined by calling:: - void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, - enum krb5_crypto_mode mode, - size_t *_offset, size_t *_len); + int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, + enum krb5_crypto_mode mode, + size_t *_offset, size_t *_len); The caller provides the offset and length of the message to the function, which then alters those values to indicate the region containing the data (plus any -padding). It is up to the caller to determine how much padding there is. +padding). It is up to the caller to determine how much padding there is. The +function returns an error if the length is too small or if the mode is +unsupported. An additional function:: + + int crypto_krb5_check_data_len(const struct krb5_enctype *krb5, + enum krb5_crypto_mode mode, + size_t len, size_t min_content); + +is provided to just do a basic check that the decrypted/verified message would +have a sufficient minimum payload. Preparation Functions ---------------------
crypto/krb5/krb5_api.c +48 -6
75 lines not on this page · raw message
include/crypto/krb5.h +6 -3
@@ -121,9 +121,12 @@ size_t crypto_krb5_how_much_buffer(const struct krb5_enctype *krb5,size_t crypto_krb5_how_much_data (const struct krb5_enctype *krb5,enum krb5_crypto_mode mode,size_t *_buffer_size,size_t *_offset); -void crypto_krb5_where_is_the_data (const struct krb5_enctype *krb5, -enum krb5_crypto_mode mode, -size_t *_offset,size_t *_len); +int crypto_krb5_where_is_the_data (const struct krb5_enctype *krb5, +enum krb5_crypto_mode mode, +size_t *_offset,size_t *_len); +int crypto_krb5_check_data_len (const struct krb5_enctype *krb5, +enum krb5_crypto_mode mode, +size_t len,size_t min_content);struct crypto_aead *crypto_krb5_prepare_encryption (const struct krb5_enctype *krb5,const struct krb5_buffer *TK ,u32 usage,gfp_t gfp);
include/trace/events/rxrpc.h +1 -0
@@ -71,6 +71,7 @@ EM(rxkad_abort_resp_unknown_tkt, "rxkad-resp-unknown-tkt") \EM (rxkad_abort_resp_version,"rxkad-resp-version" ) \ /* RxGK security errors */ \ + EM(rxgk_abort_1_short_header, "rxgk1-short-hdr") \ EM(rxgk_abort_1_verify_mic_eproto, "rxgk1-vfy-mic-eproto") \ EM(rxgk_abort_2_decrypt_eproto, "rxgk2-dec-eproto") \EM (rxgk_abort_2_short_data,"rxgk2-short-data" ) \
net/rxrpc/rxgk.c +13 -2
@@ -480,8 +480,12 @@ static int rxgk_verify_packet_integrity(struct rxrpc_call *call,_enter ("" ); -crypto_krb5_where_is_the_data (gk->krb5,KRB5_CHECKSUM_MODE , - &data_offset, &data_len); +if (crypto_krb5_where_is_the_data (gk->krb5,KRB5_CHECKSUM_MODE , + &data_offset, &data_len) <0 ) { + ret =rxrpc_abort_eproto (call, skb,RXGK_PACKETSHORT , + rxgk_abort_1_short_header); + goto put_gk; + } hdr =kzalloc (sizeof (*hdr),GFP_NOFS );if (!hdr)
@@ -529,6 +533,13 @@ static int rxgk_verify_packet_encrypted(struct rxrpc_call *call,_enter ("" ); +if (crypto_krb5_check_data_len (gk->krb5,KRB5_ENCRYPT_MODE , + len,sizeof (hdr)) <0 ) { + ret =rxrpc_abort_eproto (call, skb,RXGK_PACKETSHORT , + rxgk_abort_2_short_header); + goto error; + } + ret =rxgk_decrypt_skb (gk->krb5, gk->rx_enc, skb, &offset, &len, &ac);if (ret <0 ) {if (ret != -ENOMEM )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 358/377 net: ag71xx: check error for platform_get_irq
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <[email protected]>
[ Upstream commit e7c70bf97e90d974cd575e4c90f8f9b07d056da3 ]
Complete error handling for a failed platform_get_irq() call
--- drivers/net/ethernet/atheros/ag71xx.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/atheros/ag71xx.c +3 -0
@@ -1856,6 +1856,9 @@ static int ag71xx_probe(struct platform_device *pdev)ag71xx_int_disable (ag,AG71XX_INT_POLL ); ndev->irq =platform_get_irq (pdev,0 ); +if (ndev->irq <0 ) +return ndev->irq; + err =devm_request_irq (&pdev->dev, ndev->irq, ag71xx_interrupt,0x0 ,dev_name (&pdev->dev), ndev);if (err) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 359/377 bpf, skmsg: fix verdict sk_data_ready racing with ktls rx
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xingwang Xiang <[email protected]>
[ Upstream commit ddf8029623a1af20e984c040e89ff918158397ab ]
sk_psock_strp_data_ready() already checks tls_sw_has_ctx_rx() and defers to psock->saved_data_ready when a TLS RX context is present, avoiding a conflict with the TLS strparser's ownership of the receive queue (commit e91de6afa81c, "bpf: Fix running sk_skb program types with ktls").
sk_psock_verdict_data_ready() has no equivalent guard. When a socket is inserted into a sockmap (BPF_SK_SKB_VERDICT) before TLS RX is configured, tls_sw_strparser_arm() saves sk_psock_verdict_data_ready as rx_ctx->saved_data_ready. On data arrival:
tls_data_ready -> tls_strp_data_ready -> tls_rx_msg_ready
-> saved_data_ready() = sk_psock_verdict_data_ready()
-> tcp_read_skb() drains sk_receive_queue via __skb_unlink()
without calling tcp_eat_skb(), so copied_seq is not advanced.tls_strp_msg_load() then finds tcp_inq() >= full_len (stale), calls tcp_recv_skb() on the now-empty queue, hits WARN_ON_ONCE(!first), and returns with rx_ctx->strp.anchor.frag_list pointing at a psock-owned (potentially freed) skb. tls_decrypt_sg() subsequently walks thatfrag_list: use-after-free.
Apply the same fix as sk_psock_strp_data_ready(): if a TLS RX context is present, call psock->saved_data_ready (sock_def_readable) to wake recv() waiters and return immediately, leaving the receive queue untouched. TLS retains sole ownership of the queue and decrypts the record normally through tls_sw_recvmsg().
--- net/core/skmsg.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
net/core/skmsg.c +7 -2
@@ -1268,12 +1268,19 @@ static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb)static void sk_psock_verdict_data_ready (struct sock *sk) {const struct proto_ops *ops =NULL ; +struct sk_psock *psock;struct socket *sock;int copied;trace_sk_data_ready (sk);rcu_read_lock (); + psock =sk_psock (sk); +if (psock &&tls_sw_has_ctx_rx (sk)) { + psock->saved_data_ready (sk); +rcu_read_unlock (); +return ; + } sock =READ_ONCE (sk->sk_socket);if (likely (sock)) ops =READ_ONCE (sock->ops);
@@ -1283,8 +1290,6 @@ static void sk_psock_verdict_data_ready(struct sock *sk) copied = ops->read_skb (sk, sk_psock_verdict_recv);if (copied >=0 ) { -struct sk_psock *psock; -rcu_read_lock (); psock =sk_psock (sk);if (psock)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 360/377 tcp: fix stale per-CPU tcp_tw_isn leak enabling ISN prediction
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 1bbf0ced1d9db73ac7893c2187f3459288603e0d ]
Blamed commit moved the TIME_WAIT-derived ISN from the skb control block to a per-CPU variable, assuming the value would always be consumed by tcp_conn_request() for the same packet that wrote it. That assumption is violated by multiple drop paths between the producer (__this_cpu_write(tcp_tw_isn, isn) in tcp_v{4,6}_rcv()) and the consumer (tcp_conn_request()):
- min_ttl / min_hopcount check
- xfrm policy check
- tcp_inbound_hash() MD5/AO mismatch
- tcp_filter() eBPF/SO_ATTACH_FILTER drop
- th->syn && th->fin discard in tcp_rcv_state_process() TCP_LISTEN
- psp_sk_rx_policy_check() in tcp_v{4,6}_do_rcv()
- tcp_checksum_complete() in tcp_v{4,6}_do_rcv()
- tcp_v{4,6}_cookie_check() returning NULL
When a packet is dropped on any of these paths, tcp_tw_isn is left set.
The next SYN processed on the same CPU then consumes the non zero value in tcp_conn_request(), receiving a potentially predictable ISN.
This patch moves back tcp_tw_isn to skb->cb[], getting rid of the per-cpu variable.
Note that tcp_v{4,6}_fill_cb() do not set it.
Very litle impact on overall code size/complexity:
$ scripts/bloat-o-meter -t vmlinux.old vmlinux.new add/remove: 0/0 grow/shrink: 2/1 up/down: 8/-15 (-7) Function old new delta tcp_v6_rcv 3038 3042 +4 tcp_v4_rcv 3035 3039 +4 tcp_conn_request 2938 2923 -15 Total: Before=24436060, After=24436053, chg -0.00%
--- include/net/tcp.h | 7 ++++--- net/ipv4/tcp.c | 3 --- net/ipv4/tcp_input.c | 15 ++++++--------- net/ipv4/tcp_ipv4.c | 3 ++- net/ipv6/tcp_ipv6.c | 3 ++- 5 files changed, 14 insertions(+), 17 deletions(-)
include/net/tcp.h +4 -3
@@ -65,8 +65,6 @@ static inline void tcp_orphan_count_dec(void)this_cpu_dec (tcp_orphan_count); } -DECLARE_PER_CPU (u32, tcp_tw_isn); -void tcp_time_wait (struct sock *sk,int state,int timeo);#define MAX_TCP_HEADER L1_CACHE_ALIGN(128 + MAX_HEADER)
@@ -1028,10 +1026,13 @@ struct tcp_skb_cb {__u32 seq;/* Starting sequence number */ __u32 end_seq;/* SEQ + FIN + SYN + datalen */ union { -/* Note : +/* Notes : +* tcp_tw_isn is used in input path only +* (isn chosen by tcp_timewait_state_process()) * tcp_gso_segs/size are used in write queue only, * cf tcp_skb_pcount()/tcp_skb_mss() */ +u32 tcp_tw_isn;struct {u16 tcp_gso_segs;u16 tcp_gso_size;
net/ipv4/tcp.c +0 -3
@@ -300,9 +300,6 @@ enum { DEFINE_PER_CPU(unsigned int, tcp_orphan_count);EXPORT_PER_CPU_SYMBOL_GPL (tcp_orphan_count); -DEFINE_PER_CPU (u32, tcp_tw_isn); -EXPORT_PER_CPU_SYMBOL_GPL (tcp_tw_isn); -long sysctl_tcp_mem[3 ]__read_mostly ;EXPORT_IPV6_MOD (sysctl_tcp_mem);
net/ipv4/tcp_input.c +6 -9
@@ -7387,6 +7387,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, struct sock *sk, struct sk_buff *skb) { struct tcp_fastopen_cookie foc = { .len = -1 }; +u32 isn =TCP_SKB_CB (skb)->tcp_tw_isn;struct tcp_options_received tmp_opt;const struct tcp_sock *tp =tcp_sk (sk);struct net *net =sock_net (sk);
@@ -7397,20 +7398,16 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,struct dst_entry *dst;struct flowi fl;u8 syncookies; -u32 isn;#ifdef CONFIG_TCP_AO const struct tcp_ao_hdr *aoh;#endif - isn =__this_cpu_read (tcp_tw_isn); -if (isn) { -/* TW buckets are converted to open requests without -* limitations, they conserve resources and peer is -* evidently real one. -*/ -__this_cpu_write (tcp_tw_isn,0 ); - }else { +/* If isn is non-zero, this SYN originally matched a TIME_WAIT socket. +* TW sockets are converted to open requests without limitations, +* we skip the queue limits and syncookie checks in the block below. +*/ +if (!isn) { syncookies =READ_ONCE (net->ipv4.sysctl_tcp_syncookies);if (syncookies ==2 ||inet_csk_reqsk_queue_is_full (sk)) {
net/ipv4/tcp_ipv4.c +2 -1
@@ -2333,6 +2333,7 @@ int tcp_v4_rcv(struct sk_buff *skb) } } + isn =0 ; process:if (static_branch_unlikely (&ip4_min_ttl)) {/* min_ttl can be changed concurrently from do_ip_setsockopt() */
@@ -2361,6 +2362,7 @@ int tcp_v4_rcv(struct sk_buff *skb) th = (const struct tcphdr *)skb->data; iph =ip_hdr (skb);tcp_v4_fill_cb (skb, iph, th); +TCP_SKB_CB (skb)->tcp_tw_isn = isn; skb->dev =NULL ;
@@ -2446,7 +2448,6 @@ int tcp_v4_rcv(struct sk_buff *skb) sk = sk2;tcp_v4_restore_cb (skb); refcounted = false; -__this_cpu_write (tcp_tw_isn, isn); goto process; }
net/ipv6/tcp_ipv6.c +2 -1
@@ -1863,6 +1863,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) } } + isn =0 ; process:if (static_branch_unlikely (&ip6_min_hopcount)) {/* min_hopcount can be changed concurrently from do_ipv6_setsockopt() */
@@ -1891,6 +1892,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) th = (const struct tcphdr *)skb->data; hdr =ipv6_hdr (skb);tcp_v6_fill_cb (skb, hdr, th); +TCP_SKB_CB (skb)->tcp_tw_isn = isn; skb->dev =NULL ;
@@ -1978,7 +1980,6 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) sk = sk2;tcp_v6_restore_cb (skb); refcounted = false; -__this_cpu_write (tcp_tw_isn, isn); goto process; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 361/377 gpio: cdev: check if uAPI v2 config attributes are correctly zeroed
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
[ Upstream commit 3e6ccd790ed69bedd3d9626d01dd35cf9821c121 ]
We check the padding of other uAPI v2 structures but not that of line config attributes. For used attributes: check if their padding is zeroed, for unused: check if the entire structure is zeroed.
--- drivers/gpio/gpiolib-cdev.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/gpio/gpiolib-cdev.c +13 -0
@@ -1208,6 +1208,7 @@ static int gpio_v2_line_flags_validate(u64 flags)static int gpio_v2_line_config_validate (struct gpio_v2_line_config *lc,unsigned int num_lines) { +size_t unused_attrs;unsigned int i;u64 flags;int ret;
@@ -1215,9 +1216,21 @@ static int gpio_v2_line_config_validate(struct gpio_v2_line_config *lc,if (lc->num_attrs >GPIO_V2_LINE_NUM_ATTRS_MAX )return -EINVAL ; + unused_attrs =GPIO_V2_LINE_NUM_ATTRS_MAX - lc->num_attrs; +if (!mem_is_zero (lc->padding,sizeof (lc->padding)))return -EINVAL ; +for (i =0 ; i < lc->num_attrs; i++) { +if (lc->attrs[i].attr.padding !=0 ) +return -EINVAL ; + } + +if (unused_attrs) { +if (!mem_is_zero (&lc->attrs[lc->num_attrs], unused_attrs *sizeof (*lc->attrs))) +return -EINVAL ; + } +for (i =0 ; i < num_lines; i++) { flags =gpio_v2_line_config_flags (lc, i); ret =gpio_v2_line_flags_validate (flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 362/377 gpio: aggregator: fix a potential use-after-free
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
[ Upstream commit 30c073cab97afb31901f94de9605177b6b84367e ]
On error we free aggr->lookups->dev_id before removing the entry from the lookup table. If a concurrent thread calls gpiod_find() before we remove the entry, it could iterate over the list and call gpiod_match_lookup_table() which unconditionally dereferences dev_id when calling strcmp(). Reverse the order of cleanup.
--- drivers/gpio/gpio-aggregator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/gpio-aggregator.c +1 -1
@@ -970,8 +970,8 @@ static int gpio_aggregator_activate(struct gpio_aggregator *aggr)return 0 ; err_remove_lookup_table: -kfree (aggr->lookups->dev_id);gpiod_remove_lookup_table (aggr->lookups); +kfree (aggr->lookups->dev_id); err_remove_swnode:fwnode_remove_software_node (swnode); err_remove_lookups:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 363/377 gpio: aggregator: stop using dev-sync-probe
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
[ Upstream commit 3a27f40b457053e6112a63d14590e4a3ff553b44 ]
dev-err-probe is an overengineered solution to a simple problem. Use a combination of wait_for_probe() and device_is_bound() to synchronously wait for the platform device to probe.
Stable-dep-of: 61fef83f239e ("gpio: aggregator: remove the software node when deactivating the aggregator")
--- drivers/gpio/Kconfig | 1 - drivers/gpio/gpio-aggregator.c | 38 +++++++++++++++++++--------------- 2 files changed, 21 insertions(+), 18 deletions(-)
drivers/gpio/Kconfig +0 -1
@@ -1968,7 +1968,6 @@ menu "Virtual GPIO drivers" config GPIO_AGGREGATOR tristate "GPIO Aggregator" select CONFIGFS_FS - select DEV_SYNC_PROBE help Say yes here to enable the GPIO Aggregator, which provides a way to aggregate existing GPIO lines into a new virtual GPIO chip.
drivers/gpio/gpio-aggregator.c +21 -17
@@ -32,8 +32,6 @@#include <linux/gpio/forwarder.h> #include <linux/gpio/machine.h> -#include "dev-sync-probe.h" -#define AGGREGATOR_MAX_GPIOS 512#define AGGREGATOR_LEGACY_PREFIX "_sysfs"
@@ -42,7 +40,7 @@*/ struct gpio_aggregator { -struct dev_sync_probe_data probe_data; +struct platform_device *pdev;struct config_group group;struct gpiod_lookup_table *lookups;struct mutex lock;
@@ -135,7 +133,7 @@ static bool gpio_aggregator_is_active(struct gpio_aggregator *aggr) {lockdep_assert_held (&aggr->lock); -return aggr->probe_data.pdev &&platform_get_drvdata (aggr->probe_data.pdev); +return aggr->pdev &&platform_get_drvdata (aggr->pdev); }/* Only aggregators created via legacy sysfs can be "activating". */
@@ -143,7 +141,7 @@ static bool gpio_aggregator_is_activating(struct gpio_aggregator *aggr) {lockdep_assert_held (&aggr->lock); -return aggr->probe_data.pdev && !platform_get_drvdata (aggr->probe_data.pdev); +return aggr->pdev && !platform_get_drvdata (aggr->pdev); }static size_t gpio_aggregator_count_lines (struct gpio_aggregator *aggr)
@@ -909,6 +907,7 @@ static int gpio_aggregator_activate(struct gpio_aggregator *aggr) {struct platform_device_info pdevinfo;struct gpio_aggregator_line *line; +struct platform_device *pdev;struct fwnode_handle *swnode;unsigned int n =0 ;int ret =0 ;
@@ -963,12 +962,23 @@ static int gpio_aggregator_activate(struct gpio_aggregator *aggr)gpiod_add_lookup_table (aggr->lookups); - ret =dev_sync_probe_register (&aggr->probe_data, &pdevinfo); -if (ret) + pdev =platform_device_register_full (&pdevinfo); +if (IS_ERR (pdev)) { + ret =PTR_ERR (pdev); goto err_remove_lookup_table; + } +wait_for_device_probe (); +if (!device_is_bound (&pdev->dev)) { + ret = -ENXIO ; + goto err_unregister_pdev; + } + + aggr->pdev = pdev;return 0 ; +err_unregister_pdev: +platform_device_unregister (pdev); err_remove_lookup_table:gpiod_remove_lookup_table (aggr->lookups);kfree (aggr->lookups->dev_id);
@@ -982,7 +992,8 @@ static int gpio_aggregator_activate(struct gpio_aggregator *aggr)static void gpio_aggregator_deactivate (struct gpio_aggregator *aggr) { -dev_sync_probe_unregister (&aggr->probe_data); +platform_device_unregister (aggr->pdev); + aggr->pdev =NULL ;gpiod_remove_lookup_table (aggr->lookups);kfree (aggr->lookups->dev_id);kfree (aggr->lookups);
@@ -1146,7 +1157,7 @@ gpio_aggregator_device_dev_name_show(struct config_item *item, char *page)guard (mutex)(&aggr->lock); - pdev = aggr->probe_data.pdev; + pdev = aggr->pdev;if (pdev)return sysfs_emit (page,"%s\n" ,dev_name (&pdev->dev));
@@ -1323,7 +1334,6 @@ gpio_aggregator_make_group(struct config_group *group, const char *name)return ERR_PTR (ret);config_group_init_type_name (&aggr->group, name, &gpio_aggregator_device_type); -dev_sync_probe_init (&aggr->probe_data);return &aggr->group; }
@@ -1473,12 +1483,6 @@ static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver,scnprintf (name,sizeof (name),"%s.%d" ,AGGREGATOR_LEGACY_PREFIX , aggr->id);config_group_init_type_name (&aggr->group, name, &gpio_aggregator_device_type); -/* -* Since the device created by sysfs might be toggled via configfs -* 'live' attribute later, this initialization is needed. -*/ -dev_sync_probe_init (&aggr->probe_data); -/* Expose to configfs */ res =configfs_register_group (&gpio_aggregator_subsys.su_group, &aggr->group);
@@ -1497,7 +1501,7 @@ static ssize_t gpio_aggregator_new_device_store(struct device_driver *driver, goto remove_table; } - aggr->probe_data.pdev = pdev; + aggr->pdev = pdev;module_put (THIS_MODULE );return count;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 364/377 gpio: aggregator: remove the software node when deactivating the aggregator
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
[ Upstream commit 61fef83f239ecace1cce716135762a2d9b7b1fc6 ]
The dynamic software node we create for the aggregator platform device when using configfs is leaked when the device is deactivated. Destroy it as the last step in the tear-down path.
--- drivers/gpio/gpio-aggregator.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/gpio/gpio-aggregator.c +4 -0
@@ -992,11 +992,15 @@ static int gpio_aggregator_activate(struct gpio_aggregator *aggr)static void gpio_aggregator_deactivate (struct gpio_aggregator *aggr) { +struct fwnode_handle *swnode; + + swnode =dev_fwnode (&aggr->pdev->dev);platform_device_unregister (aggr->pdev); aggr->pdev =NULL ;gpiod_remove_lookup_table (aggr->lookups);kfree (aggr->lookups->dev_id);kfree (aggr->lookups); +fwnode_remove_software_node (swnode); } static void gpio_aggregator_lockup_configfs(struct gpio_aggregator *aggr,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 365/377 gpio: aggregator: lock device when calling device_is_bound()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
[ Upstream commit 598a2b3e2e0e6aa2e9f7843c96c45b5ea11e0411 ]
The kerneldoc for device_is_bound() says it must be called with the device lock taken. Add missing synchronization to this driver.
--- drivers/gpio/gpio-aggregator.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/gpio/gpio-aggregator.c +6 -3
@@ -969,9 +969,12 @@ static int gpio_aggregator_activate(struct gpio_aggregator *aggr) }wait_for_device_probe (); -if (!device_is_bound (&pdev->dev)) { - ret = -ENXIO ; - goto err_unregister_pdev; + + scoped_guard(device, &pdev->dev) { +if (!device_is_bound (&pdev->dev)) { + ret = -ENXIO ; + goto err_unregister_pdev; + } } aggr->pdev = pdev;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 366/377 ASoC: cs35l56: Fix flushing of IRQ work in cs35l56_sdw_remove()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Fitzgerald <[email protected]>
[ Upstream commit 18e7bd9f2446664053f8c34b72abd4606d22d858 ]
Use flush_work() instead of cancel_work_sync() to terminate pending IRQ work in cs35l56_sdw_remove(). And flush_work() again after masking the interrupts to flush any queueing that was racing with the masking. This is the same sequence as cs35l56_sdw_system_suspend().
cs35l56_sdw_interrupt() takes the pm_runtime to prevent the bus powering- down before the interrupt status can be read and handled. The work releases this pm_runtime. So cancelling it, instead of flushing, could leave an unbalanced pm_runtime.
--- sound/soc/codecs/cs35l56-sdw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
sound/soc/codecs/cs35l56-sdw.c +2 -1
@@ -560,10 +560,11 @@ static int cs35l56_sdw_remove(struct sdw_slave *peripheral)/* Disable SoundWire interrupts */ cs35l56->sdw_irq_no_unmask = true; -cancel_work_sync (&cs35l56->sdw_irq_work); +flush_work (&cs35l56->sdw_irq_work);sdw_write_no_pm (peripheral,CS35L56_SDW_GEN_INT_MASK_1 ,0 );sdw_read_no_pm (peripheral,CS35L56_SDW_GEN_INT_STAT_1 );sdw_write_no_pm (peripheral,CS35L56_SDW_GEN_INT_STAT_1 ,0xFF ); +flush_work (&cs35l56->sdw_irq_work);cs35l56_remove (cs35l56);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 367/377 drm/xe/oa: Fix exec_queue leak on width check in stream open
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuicheng Lin <[email protected]>
[ Upstream commit 4d25342543c01310fc4e0cba7cb17c775e2421e2 ]
In xe_oa_stream_open_ioctl(), when param.exec_q->width > 1 the function returns -EOPNOTSUPP directly, skipping the existing err_exec_q cleanup path. The exec_queue reference obtained by xe_exec_queue_lookup() is leaked.
The exec queue holds a reference on the xe_file, which is only dropped during queue teardown. The leaked lookup ref is not on the file's exec_queue xarray, so file close cannot release it. This keeps both the exec queue and the file private state pinned indefinitely.
Jump to err_exec_q instead of returning directly so the reference is released.
--- drivers/gpu/drm/xe/xe_oa.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/xe/xe_oa.c +4 -2
@@ -2043,8 +2043,10 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *fif (XE_IOCTL_DBG (oa->xe, !param.exec_q))return -ENOENT ; -if (XE_IOCTL_DBG (oa->xe, param.exec_q->width >1 )) -return -EOPNOTSUPP ; +if (XE_IOCTL_DBG (oa->xe, param.exec_q->width >1 )) { + ret = -EOPNOTSUPP ; + goto err_exec_q; + } }/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 368/377 selftests: net: Fix checksums in xdp_native
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nimrod Oren <[email protected]>
[ Upstream commit dfc077043351a81887d1e4c9ac244e9243f3cbf2 ]
Data adjustment cases failed with "Data exchange failed" when using IPv4 because the program did not update the IP and UDP checksums in the IPv4 branch. The issue was masked when both IPv4 and IPv6 were configured, since the test harness prefers IPv6.
While here, generalize csum_fold_helper() to fold twice so it works for any 32-bit input.
--- .../selftests/net/lib/xdp_native.bpf.c | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-)
tools/testing/selftests/net/lib/xdp_native.bpf.c +30 -25
@@ -268,6 +268,17 @@ static int xdp_mode_tx_handler(struct xdp_md *ctx, __u16 port)return XDP_PASS ; } +static __always_inline __u16 csum_fold_helper(__u32 csum) +{ + csum = (csum &0xffff ) + (csum >>16 ); +return ~((csum &0xffff ) + (csum >>16 )); +} + +static __always_inline __u16 csum_fold_udp_helper(__u32 csum) +{ +return csum_fold_helper (csum) ? :0xffff ; +} +static void *update_pkt (struct xdp_md *ctx,__s16 offset,__u32 *udp_csum) {void *data_end = (void *)(long )ctx->data_end;
@@ -281,21 +292,22 @@ static void *update_pkt(struct xdp_md *ctx, __s16 offset, __u32 *udp_csum)if (eth->h_proto ==bpf_htons (ETH_P_IP )) {struct iphdr *iph = data +sizeof (*eth); -__u16 total_len;if (iph +1 > (struct iphdr *)data_end)return NULL ; - iph->tot_len =bpf_htons (bpf_ntohs (iph->tot_len) + offset); - udph = (void *)eth +sizeof (*iph) +sizeof (*eth);if (!udph || udph +1 > (struct udphdr *)data_end)return NULL ; - len_new =bpf_htons (bpf_ntohs (udph->len) + offset); + len = iph->tot_len; + len_new =bpf_htons (bpf_ntohs (len) + offset); + iph->tot_len = len_new; + iph->check =csum_fold_helper ( +bpf_csum_diff (&len,sizeof (len), &len_new, +sizeof (len_new), ~((__u32 )iph->check))); }else if (eth->h_proto ==bpf_htons (ETH_P_IPV6 )) {struct ipv6hdr *ipv6h = data +sizeof (*eth); -__u16 payload_len;if (ipv6h +1 > (struct ipv6hdr *)data_end)return NULL ;
@@ -304,33 +316,27 @@ static void *update_pkt(struct xdp_md *ctx, __s16 offset, __u32 *udp_csum)if (!udph || udph +1 > (struct udphdr *)data_end)return NULL ; - *udp_csum = ~((__u32 )udph->check); - len = ipv6h->payload_len; len_new =bpf_htons (bpf_ntohs (len) + offset); ipv6h->payload_len = len_new; - - *udp_csum =bpf_csum_diff (&len,sizeof (len), &len_new, -sizeof (len_new), *udp_csum); - - len = udph->len; - len_new =bpf_htons (bpf_ntohs (udph->len) + offset); - *udp_csum =bpf_csum_diff (&len,sizeof (len), &len_new, -sizeof (len_new), *udp_csum); }else {return NULL ; } + len = udph->len; + len_new =bpf_htons (bpf_ntohs (len) + offset); + + *udp_csum = ~((__u32 )udph->check); + *udp_csum =bpf_csum_diff (&len,sizeof (len), &len_new, +sizeof (len_new), *udp_csum); + *udp_csum =bpf_csum_diff (&len,sizeof (len), &len_new, +sizeof (len_new), *udp_csum); + udph->len = len_new;return udph; } -static __u16 csum_fold_helper (__u32 csum) -{ -return ~((csum &0xffff ) + (csum >>16 )) ? :0xffff ; -} -static int xdp_adjst_tail_shrnk_data (struct xdp_md *ctx,__u16 offset,__u32 hdr_len) {
@@ -359,7 +365,7 @@ static int xdp_adjst_tail_shrnk_data(struct xdp_md *ctx, __u16 offset,return -1 ; udp_csum =bpf_csum_diff ((__be32 *)tmp_buff, offset,0 ,0 , udp_csum); - udph->check = (__u16 )csum_fold_helper (udp_csum); + udph->check = (__u16 )csum_fold_udp_helper (udp_csum);if (bpf_xdp_adjust_tail (ctx,0 - offset) <0 )return -1 ;
@@ -403,7 +409,7 @@ static int xdp_adjst_tail_grow_data(struct xdp_md *ctx, __u16 offset)return -1 ; udp_csum =bpf_csum_diff (0 ,0 , (__be32 *)tmp_buff, offset, udp_csum); - udph->check = (__u16 )csum_fold_helper (udp_csum); + udph->check = (__u16 )csum_fold_udp_helper (udp_csum); buff_len =bpf_xdp_get_buff_len (ctx);
@@ -483,8 +489,7 @@ static int xdp_adjst_head_shrnk_data(struct xdp_md *ctx, __u64 hdr_len,return -1 ; udp_csum =bpf_csum_diff ((__be32 *)tmp_buff, offset,0 ,0 , udp_csum); - - udph->check = (__u16 )csum_fold_helper (udp_csum); + udph->check = (__u16 )csum_fold_udp_helper (udp_csum);if (bpf_xdp_load_bytes (ctx,0 , tmp_buff,MAX_ADJST_OFFSET ) <0 )return -1 ;
@@ -541,7 +546,7 @@ static int xdp_adjst_head_grow_data(struct xdp_md *ctx, __u64 hdr_len,return -1 ; udp_csum =bpf_csum_diff (0 ,0 , (__be32 *)data_buff, offset, udp_csum); - udph->check = (__u16 )csum_fold_helper (udp_csum); + udph->check = (__u16 )csum_fold_udp_helper (udp_csum);if (hdr_len >MAX_ADJST_OFFSET || hdr_len ==0 )return -1 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 369/377 octeontx2-af: npc: Fix allmulticast skip logic for LBK and SDP VFs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ratheesh Kannoth <[email protected]>
[ Upstream commit 9eddc819f00b5b74bb4ac91396f80bd35f5f3561 ]
When installing the allmulticast NPC rule, rvu_npc_install_allmulti_entry() should skip LBK and SDP VFs (only CGX PF/VF may add the entry). The code combined is_lbk_vf() and is_sdp_vf() with logical AND, which is never true for a single pcifunc, so the intended early return never ran.
Use logical OR instead.
--- drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +1 -1
@@ -837,7 +837,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,u16 vf_func;/* Only CGX PF/VF can add allmulticast entry */ -if (is_lbk_vf (rvu, pcifunc) &&is_sdp_vf (rvu, pcifunc)) +if (is_lbk_vf (rvu, pcifunc) ||is_sdp_vf (rvu, pcifunc))return ; blkaddr =rvu_get_blkaddr (rvu,BLKTYPE_NPC ,0 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 370/377 net: mana: validate rx_req_idx to prevent out-of-bounds array access
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aditya Garg <[email protected]>
[ Upstream commit b809d0409991b75a6cff846a5ac27c3062953f84 ]
In mana_hwc_rx_event_handler(), rx_req_idx is derived from sge->address in DMA-coherent memory. In Confidential VMs (SEV-SNP/TDX), this memory is shared unencrypted and HW can modify WQE contents at any time. No bounds check exists on rx_req_idx, which can lead to an out-of-bounds access into reqs[].
Add bounds check on rx_req_idx in mana_hwc_rx_event_handler() before using it to index the reqs[] array.
--- drivers/net/ethernet/microsoft/mana/hw_channel.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/net/ethernet/microsoft/mana/hw_channel.c +6 -0
@@ -265,6 +265,12 @@ static void mana_hwc_rx_event_handler(void *ctx, u32 gdma_rxq_id, rq_base_addr = hwc_rxq->msg_buf->mem_info.dma_handle; rx_req_idx = (sge->address - rq_base_addr) / hwc->max_req_msg_size; +if (rx_req_idx >= hwc_rxq->msg_buf->num_reqs) { +dev_err (hwc->dev,"HWC RX: wrong rx_req_idx=%llu, num_reqs=%u\n" , + rx_req_idx, hwc_rxq->msg_buf->num_reqs); +return ; + } + rx_req = &hwc_rxq->msg_buf->reqs[rx_req_idx]; resp = (struct gdma_resp_hdr *)rx_req->buf_va;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 371/377 tap: fix stack info leak in tap_ioctl() SIOCGIFHWADDR
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit bddc09212c24934643bd44fc794748d2bbb3b6cd ]
In the SIOCGIFHWADDR path, tap_ioctl() copies 16 bytes of an uninitialised on-stack struct sockaddr_storage to userspace via ifr_hwaddr, but netif_get_mac_address() only writes sa_family and dev->addr_len (6 for Ethernet) bytes, leaving sa_data[6..13] uninitialised.
Those 8 trailing bytes leak kernel stack contents; SIOCGIFHWADDR on a macvtap chardev returns kernel .text and direct-map pointers, defeating KASLR.
Initialise ss at declaration.
--- drivers/net/tap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/tap.c +1 -1
@@ -919,11 +919,11 @@ static long tap_ioctl(struct file *file, unsigned int cmd,struct tap_queue *q = file->private_data;struct tap_dev *tap;void __user *argp = (void __user *)arg; +struct sockaddr_storage ss = {};struct ifreq __user *ifr = argp;unsigned int __user *up = argp;unsigned short u;int __user *sp = argp; -struct sockaddr_storage ss;int s;int ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 372/377 net: airoha: Disable GDM2 forwarding before configuring GDM2 loopback
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 985d4a55e64e43bd86eeb896b81ceba453301989 ]
Hw design requires to disable GDM2 forwarding before configuring GDM2 loopback in airoha_set_gdm2_loopback routine.
--- drivers/net/ethernet/airoha/airoha_eth.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +6 -4
@@ -1800,11 +1800,8 @@ static int airhoha_set_gdm2_loopback(struct airoha_gdm_port *port)u32 val, pse_port, chan;int src_port; -/* Forward the traffic to the proper GDM port */ - pse_port = port->id ==AIROHA_GDM3_IDX ?FE_PSE_PORT_GDM3 - :FE_PSE_PORT_GDM4 ;airoha_set_gdm_port_fwd_cfg (eth,REG_GDM_FWD_CFG (AIROHA_GDM2_IDX ), - pse_port); +FE_PSE_PORT_DROP );airoha_fe_clear (eth,REG_GDM_FWD_CFG (AIROHA_GDM2_IDX ),GDM_STRIP_CRC_MASK );
@@ -1822,6 +1819,11 @@ static int airhoha_set_gdm2_loopback(struct airoha_gdm_port *port)GDM_SHORT_LEN_MASK |GDM_LONG_LEN_MASK ,FIELD_PREP (GDM_SHORT_LEN_MASK ,60 ) | FIELD_PREP(GDM_LONG_LEN_MASK, AIROHA_MAX_MTU)); +/* Forward the traffic to the proper GDM port */ + pse_port = port->id ==AIROHA_GDM3_IDX ?FE_PSE_PORT_GDM3 + :FE_PSE_PORT_GDM4 ; +airoha_set_gdm_port_fwd_cfg (eth,REG_GDM_FWD_CFG (AIROHA_GDM2_IDX ), + pse_port);/* Disable VIP and IFC for GDM2 */ airoha_fe_clear (eth,REG_FE_VIP_PORT_EN ,BIT (AIROHA_GDM2_IDX ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 373/377 pds_core: ensure null-termination for firmware version strings
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <[email protected]>
[ Upstream commit 3d4432d34c1992701289cbe12df9fd024f315998 ]
The driver passes fw_version directly to devlink_info_version_stored_put() without ensuring null-termination. While current firmware null-terminates these strings, the driver should not rely on this behavior. Add explicit null-termination to prevent potential issues if firmware behavior changes.
--- drivers/net/ethernet/amd/pds_core/devlink.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/ethernet/amd/pds_core/devlink.c +4 -2
@@ -121,12 +121,14 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req, listlen =min (fw_list.num_fw_slots,ARRAY_SIZE (fw_list.fw_names));for (i =0 ; i < listlen; i++) { +char *fw_ver = fw_list.fw_names[i].fw_version; +if (i <ARRAY_SIZE (fw_slotnames))strscpy (buf, fw_slotnames[i],sizeof (buf));else snprintf (buf,sizeof (buf),"fw.slot_%d" , i); - err =devlink_info_version_stored_put (req, buf, - fw_list.fw_names[i].fw_version); + fw_ver[sizeof (fw_list.fw_names[i].fw_version) -1 ] ='\0' ; + err =devlink_info_version_stored_put (req, buf, fw_ver);if (err)return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 374/377 net: gro: dont merge zcopy skbs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
[ Upstream commit 4db79a322db8c97f7b73b8a347395ef4d685eb40 ]
skb_gro_receive() can currently copy frags between the source and GRO skb, without checking the zerocopy status, and in particular the SKBFL_MANAGED_FRAG_REFS flag.
When SKBFL_MANAGED_FRAG_REFS is set, the skb doesn't hold a reference on the pages in shinfo->frags. Appending those frags to another skb's frags without fixing up the page refcount can lead to UAF.
When either the last skb in the GRO chain (the one we would append frags to) or the source skb is zerocopy, don't merge the skbs.
--- net/core/gro.c | 3 +++ 1 file changed, 3 insertions(+)
net/core/gro.c +3 -0
@@ -109,6 +109,9 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb)if (p->pp_recycle != skb->pp_recycle)return -ETOOMANYREFS ; +if (skb_zcopy (p) ||skb_zcopy (skb)) +return -ETOOMANYREFS ; +if (unlikely (p->len + len >=netif_get_gro_max_size (p->dev, p) ||NAPI_GRO_CB (skb)->flush))return -E2BIG ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 375/377 io_uring/nop: pass all errors to userspace
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander A. Klimov <[email protected]>
[ Upstream commit e97ff8b62d4690c69297f0f6de874f0564cc01a4 ]
This fixes an inconsistency where io_nop() called req_set_fail() based on ret, but passed just nop->result to userspace. Originally, ret is a even copy of nop->result, but is set to an error when such happens subsequently. Now that's also passed to userspace.
--- io_uring/nop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
io_uring/nop.c +2 -2
@@ -79,9 +79,9 @@ int io_nop(struct io_kiocb *req, unsigned int issue_flags)if (ret <0 )req_set_fail (req);if (nop->flags &IORING_NOP_CQE32 ) -io_req_set_res32 (req, nop->result,0 , nop->extra1, nop->extra2); +io_req_set_res32 (req, ret,0 , nop->extra1, nop->extra2);else -io_req_set_res (req, nop->result,0 ); +io_req_set_res (req, ret,0 );if (nop->flags &IORING_NOP_TW ) { req->io_task_work.func = io_req_task_complete;io_req_task_work_add (req);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 376/377 ksmbd: fix durable reconnect error path file lifetime
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junyi Liu <[email protected]>
[ Upstream commit 3515503322f4819277091839eed46b695096aca5 ]
After a durable reconnect succeeds, ksmbd_reopen_durable_fd() republishes the same ksmbd_file into the session volatile-id table. If smb2_open() then takes a later error path, cleanup first calls ksmbd_fd_put(work, fp) and then unconditionally calls ksmbd_put_durable_fd(dh_info.fp).
In this case fp and dh_info.fp are the same object. The first put drops the reconnect lookup reference, but the final durable put can run __ksmbd_close_fd(NULL, fp). Because the final close is not session-aware, it can free the file object without removing the volatile-id entry that was just published into the session table.
Use the session-aware put for the final reconnect drop when the reconnect had already succeeded and the error path is cleaning up the republished file. Earlier reconnect failures, before fp is assigned to dh_info.fp, keep using the durable-only put path.
--- fs/smb/server/smb2pdu.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
fs/smb/server/smb2pdu.c +13 -2
@@ -3812,8 +3812,19 @@ int smb2_open(struct ksmbd_work *work)ksmbd_debug (SMB ,"Error response: %x\n" , rsp->hdr.Status); } -if (dh_info.reconnected) -ksmbd_put_durable_fd (dh_info.fp); +if (dh_info.reconnected) { +/* +* If reconnect succeeded, fp was republished in the +* session file table. On a later error, ksmbd_fd_put() +* above drops the session reference; drop the durable +* lookup reference through the same session-aware path so +* final close removes the volatile id before freeing fp. +*/ +if (rc && fp == dh_info.fp) +ksmbd_fd_put (work, dh_info.fp); +else +ksmbd_put_durable_fd (dh_info.fp); + }kfree (name);kfree (lc);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 377/377 LoongArch: kprobes: Fix handling of fatal unrecoverable recursions
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiezhu Yang <[email protected]>
[ Upstream commit 1c856e158fd34ef2c4475a81c1dc386329989938 ]
KPROBE_HIT_SS and KPROBE_REENTER are two types of fatal recursions that can not be safely recovered in kprobes.
KPROBE_HIT_SS means that a kprobe is hit during single-stepping. At this point, the architecture-specific single-step context is already active. Nested single-stepping would corrupt the state, as the kprobe control block (kcb) and hardware registers cannot safely store multiple levels of stepping state.
KPROBE_REENTER means that a third-level recursion occurs when a probe is hit while the system is already handling a nested probe (second- level). The kcb only provides a single slot (prev_kprobe) to backup the state. When a third probe is hit, there is no more space to save the state without corrupting the first-level backup.
Kprobes work by replacing instructions with breakpoints. In order to execute the original instruction and continue, it must be moved to a temporary "single-step" slot. Since there is no backup space left to set up this slot safely, the CPU would be forced to return to the same original breakpoint address, triggering an endless loop.
Currently, the code only prints a warning and returns. This leads to an infinite re-entry loop as the CPU repeatedly hits the same trap and a "stuck" CPU core because preemption was disabled at the start of the handler and never re-enabled in this early return path.
Fix the logic by:
1. Merging KPROBE_HIT_SS and KPROBE_REENTER cases, as both represent fatal recursions that cannot be safely recovered.
2. Replacing WARN_ON_ONCE() with BUG() to terminate the system. This aligns LoongArch with other architectures (x86, arm64, riscv) and prevents stack overflow while providing diagnostic information.
--- arch/loongarch/kernel/kprobes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/loongarch/kernel/kprobes.c +2 -2
@@ -186,16 +186,16 @@ static bool reenter_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) {switch (kcb->kprobe_status) { -case KPROBE_HIT_SS :case KPROBE_HIT_SSDONE :case KPROBE_HIT_ACTIVE :kprobes_inc_nmissed_count (p);setup_singlestep (p, regs, kcb,1 );break ; +case KPROBE_HIT_SS :case KPROBE_REENTER :pr_warn ("Failed to recover from reentered kprobes.\n" );dump_kprobe (p); -WARN_ON_ONCE (1 ); +BUG ();break ;default :WARN_ON (1 );
Signature · 1 line
2.53.0
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.34 release. There are 377 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 30 May 2026 19:45:50 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.18.34-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.18.y
and the diffstat can be found below.thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
Quoted 8 lines · On Thu, 28 May 2026 21:43:58 +0200 Greg Kroah-Hartman…
This is the start of the stable review cycle for the 6.18.34 release. There are 377 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 30 May 2026 19:45:50 +0000. Anything received after that time might be too late.
Boot-tested under QEMU for Rust x86_64, arm64 and riscv64; built-tested for loongarch64:
Like for 7.0.y, for arm64 and arm, I am seeing:
https://lore.kernel.org/stable/[email protected]/
Thanks!
Cheers,
Miguel
# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 6.18.34-rc1-g89dbc07155c2 #1 SMP PREEMPT_DYNAMIC Fri May 29 06:09:37 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.18.34 release. There are 377 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.
CIP testing did not find any problems here:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6.18.y
Best regards,
Pavel
Am 28.05.2026 um 21:43 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.18.34 release. There are 377 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.
Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697 v2 server. No dmesg oddities or regressions found.
Beste Grüße,
Peter Schneider
Signature · 8 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr. OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244 Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc https://keys.mailvelope.com/pks/lookup?op=get&[email protected] https://keys.mailvelope.com/pks/lookup?op=get&[email protected]
Build tested in our x86,arm64,loongarch,riscv config successfully without error.
BRs
Wentao Guan
defconfigs:
https://gist.github.com/opsiff/a840ae9e3d6857f5b7bacb9cdc49f8e9
Log:
strings vmlinux-*6.18.34-rc1* | grep "Linux version 6.18.34"
Linux version 6.18.34-rc1-g89dbc07155c2 (guanwentao@uos-PC) (aarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT_DYNAMIC Linux version 6.18.34-rc1-g89dbc07155c2 (guanwentao@uos-PC) (aarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #2 SMP PREEMPT_DYNAMIC Fri May 29 22:01:37 CST 2026 Linux version 6.18.34-rc1-g89dbc07155c2 (guanwentao@uos-PC) (loongarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT_DYNAMIC Linux version 6.18.34-rc1-g89dbc07155c2 (guanwentao@uos-PC) (loongarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #3 SMP PREEMPT_DYNAMIC Fri May 29 22:19:13 CST 2026 Linux version 6.18.34-rc1+ (guanwentao@uos-PC) (riscv64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT
Linux version 6.18.34-rc1+ (guanwentao@uos-PC) (riscv64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #4 SMP PREEMPT Fri May 29 22:38:58 CST 2026 Linux version 6.18.34-rc1-g89dbc07155c2 (guanwentao@uos-PC) (gcc (Deepin 12.3.0-17deepin15) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT_DYNAMIC
Linux version 6.18.34-rc1-g89dbc07155c2 (guanwentao@uos-PC) (gcc (Deepin 12.3.0-17deepin15) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #1 SMP PREEMPT_DYNAMIC Fri May 29 21:40:40 CST 2026
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.34 release. There are 377 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 30 May 2026 19:45:50 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.18.34-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.18.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
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.34 release. There are 377 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.