6.18.32-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 860/957 Revert "pseries/papr-hvpipe: Fix race with interrupt handler"
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit 6542e180fa6e1c701aba446a555c65556e6fd1a5.
--- arch/powerpc/platforms/pseries/papr-hvpipe.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
arch/powerpc/platforms/pseries/papr-hvpipe.c +9 -11
@@ -449,14 +449,13 @@ static int papr_hvpipe_handle_release(struct inode *inode, struct file *file) {struct hvpipe_source_info *src_info; -unsigned long flags;/* * Hold the lock, remove source from src_list, reset the * hvpipe status and release the lock to prevent any race * with message event IRQ. */ -spin_lock_irqsave (&hvpipe_src_list_lock, flags); +spin_lock (&hvpipe_src_list_lock); src_info = file->private_data;list_del (&src_info->list); file->private_data =NULL ;
@@ -467,10 +466,10 @@ static int papr_hvpipe_handle_release(struct inode *inode,*/ if (src_info->hvpipe_status &HVPIPE_MSG_AVAILABLE ) { src_info->hvpipe_status =0 ; -spin_unlock_irqrestore (&hvpipe_src_list_lock, flags); +spin_unlock (&hvpipe_src_list_lock);hvpipe_rtas_recv_msg (NULL ,0 ); }else -spin_unlock_irqrestore (&hvpipe_src_list_lock, flags); +spin_unlock (&hvpipe_src_list_lock);kfree (src_info);return 0 ;
@@ -486,21 +485,20 @@ static const struct file_operations papr_hvpipe_handle_ops = {static int papr_hvpipe_dev_create_handle (u32 srcID) { struct hvpipe_source_info *src_info __free(kfree) = NULL; -unsigned long flags; -spin_lock_irqsave (&hvpipe_src_list_lock, flags); +spin_lock (&hvpipe_src_list_lock);/* * Do not allow more than one process communicates with * each source. */ src_info =hvpipe_find_source (srcID);if (src_info) { -spin_unlock_irqrestore (&hvpipe_src_list_lock, flags); +spin_unlock (&hvpipe_src_list_lock);pr_err ("pid(%d) is already using the source(%d)\n" , src_info->tsk->pid, srcID);return -EALREADY ; } -spin_unlock_irqrestore (&hvpipe_src_list_lock, flags); +spin_unlock (&hvpipe_src_list_lock); src_info =kzalloc (sizeof (*src_info),GFP_KERNEL_ACCOUNT );if (!src_info)
@@ -517,18 +515,18 @@ static int papr_hvpipe_dev_create_handle(u32 srcID)return fdf.err;retain_and_null_ptr (src_info); -spin_lock_irqsave (&hvpipe_src_list_lock, flags); +spin_lock (&hvpipe_src_list_lock);/* * If two processes are executing ioctl() for the same * source ID concurrently, prevent the second process to * acquire FD. */ if (hvpipe_find_source (srcID)) { -spin_unlock_irqrestore (&hvpipe_src_list_lock, flags); +spin_unlock (&hvpipe_src_list_lock);return -EALREADY ; }list_add (&src_info->list, &hvpipe_src_list); -spin_unlock_irqrestore (&hvpipe_src_list_lock, flags); +spin_unlock (&hvpipe_src_list_lock);return fd_publish (fdf); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 861/957 Revert "papr-hvpipe: convert papr_hvpipe_dev_create_handle() to FD_PREPARE()"
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit 09c15bbbed533903e600660ea09098b3b0524f48.
--- arch/powerpc/platforms/pseries/papr-hvpipe.c | 39 +++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-)
arch/powerpc/platforms/pseries/papr-hvpipe.c +30 -9
@@ -484,7 +484,10 @@ static const struct file_operations papr_hvpipe_handle_ops = {static int papr_hvpipe_dev_create_handle (u32 srcID) { - struct hvpipe_source_info *src_info __free(kfree) = NULL; +struct hvpipe_source_info *src_info; +struct file *file; +long err; +int fd;spin_lock (&hvpipe_src_list_lock);/*
@@ -508,13 +511,20 @@ static int papr_hvpipe_dev_create_handle(u32 srcID) src_info->tsk = current;init_waitqueue_head (&src_info->recv_wqh); -FD_PREPARE (fdf,O_RDONLY |O_CLOEXEC , -anon_inode_getfile ("[papr-hvpipe]" , &papr_hvpipe_handle_ops, - (void *)src_info,O_RDWR )); -if (fdf.err) -return fdf.err; + fd =get_unused_fd_flags (O_RDONLY |O_CLOEXEC ); +if (fd <0 ) { + err = fd; + goto free_buf; + } + + file =anon_inode_getfile ("[papr-hvpipe]" , + &papr_hvpipe_handle_ops, (void *)src_info, +O_RDWR ); +if (IS_ERR (file)) { + err =PTR_ERR (file); + goto free_fd; + } -retain_and_null_ptr (src_info);spin_lock (&hvpipe_src_list_lock);/* * If two processes are executing ioctl() for the same
@@ -523,11 +533,22 @@ static int papr_hvpipe_dev_create_handle(u32 srcID)*/ if (hvpipe_find_source (srcID)) {spin_unlock (&hvpipe_src_list_lock); -return -EALREADY ; + err = -EALREADY ; + goto free_file; }list_add (&src_info->list, &hvpipe_src_list);spin_unlock (&hvpipe_src_list_lock); -return fd_publish (fdf); + +fd_install (fd, file); +return fd; + +free_file: +fput (file); +free_fd: +put_unused_fd (fd); +free_buf: +kfree (src_info); +return err; }/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 862/957 PCI: Initialize temporary device in new_id_store()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samiullah Khawaja <[email protected]>
[ Upstream commit f45a49a2380a47332817b7248c61a0ebbc6f0d00 ]
When setting new_id of a PCI device driver using sysfs a lockdep splat occurs. This is because new_id_store() builds a temporary pci_dev for pci_match_device(), which calls device_match_driver_override(). That depends on the driver_override.lock added by cb3d1049f4ea ("driver core:
generalize driver_override in struct device").
The new driver_override.lock was not initialized in the temporary pci_dev, resulting in this lockdep splat.
Initialize the temporary pci_dev to fix this.
Repro:
Build with CONFIG_LOCKDEP=y, boot with QEMU, and add a new ID:
# echo "8086 10f5" > /sys/bus/pci/drivers/e1000e/new_id
INFO: trying to register non-static key.
The code is fine but needs lockdep annotation, or maybe you didn't initialize this object before use? turning off the locking correctness validator.
CPU: 2 UID: 0 PID: 177 Comm: liveupdate-iomm Not tainted 7.0.0+ #9 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x5d/0x80 register_lock_class+0x77e/0x790 lock_acquire+0xbf/0x2e0 pci_match_device+0x24/0x180 new_id_store+0x189/0x1d0 kernfs_fop_write_iter+0x14f/0x210 vfs_write+0x263/0x5e0 ksys_write+0x79/0xf0 do_syscall_64+0x117/0xf80
--- drivers/pci/pci-driver.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/pci/pci-driver.c +8 -1
@@ -179,6 +179,11 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,return NULL ; } +static void _pci_free_device (struct device *dev) +{ +kfree (to_pci_dev (dev)); +} +/** * new_id_store - sysfs frontend to pci_add_dynid() * @driver: target device driver
@@ -214,11 +219,13 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf, pdev->subsystem_vendor = subvendor; pdev->subsystem_device = subdevice; pdev->class = class; + pdev->dev.release = _pci_free_device; +device_initialize (&pdev->dev);if (pci_match_device (pdrv, pdev)) retval = -EEXIST ; -kfree (pdev); +put_device (&pdev->dev);if (retval)return retval;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 863/957 erofs: fix offset truncation when shifting pgoff on 32-bit platforms
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 c99493ce409c3b98fec1616dbcf24c102e006deb ]
On 32-bit platforms, pgoff_t is 32 bits wide, so left-shifting large arbitrary pgoff_t values by PAGE_SHIFT performs 32-bit arithmetic and silently truncates the result for pages beyond the 4 GiB boundary.
Cast the page index to loff_t before shifting to produce a correct 64-bit byte offset.
--- fs/erofs/data.c | 2 +- fs/erofs/zdata.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
fs/erofs/data.c +1 -1
@@ -38,7 +38,7 @@ void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, bool need_kmap)* However, the data access range must be verified here in advance. */ if (buf->file) { - fpos = index <<PAGE_SHIFT ; + fpos = (loff_t )index <<PAGE_SHIFT ; err =rw_verify_area (READ , buf->file, &fpos,PAGE_SIZE );if (err <0 )return ERR_PTR (err);
fs/erofs/zdata.c +1 -1
@@ -1869,7 +1869,7 @@ static void z_erofs_pcluster_readmore(struct z_erofs_frontend *f,if (cur <PAGE_SIZE )break ; - cur = (index <<PAGE_SHIFT ) -1 ; + cur = ((loff_t )index <<PAGE_SHIFT ) -1 ; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 864/957 bpf: Fix sync_linked_regs regarding BPF_ADD_CONST32 zext propagation
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit bc308be380c136800e1e94c6ce49cb53141d6506 ]
Jenny reported that in sync_linked_regs() the BPF_ADD_CONST32 flag is checked on known_reg (the register narrowed by a conditional branch) instead of reg (the linked target register created by an alu32 operation).
Example case with reg:
1. r6 = bpf_get_prandom_u32()
2. r7 = r6 (linked, same id)
3. w7 += 5 (alu32 -- r7 gets BPF_ADD_CONST32, zero-extended by CPU)
4. if w6 < 0xFFFFFFFC goto safe (narrows r6 to [0xFFFFFFFC, 0xFFFFFFFF])
5. sync_linked_regs() propagates to r7 but does NOT call zext_32_to_64()
6. Verifier thinks r7 is [0x100000001, 0x100000004] instead of [1, 4]
Since known_reg above does not have BPF_ADD_CONST32 set above, zext_32_to_64() is never called on alu32-derived linked registers. This causes the verifier to track incorrect 64-bit bounds, while the CPU correctly zero-extends the 32-bit result.
The code checking known_reg->id was correct however (see scalars_alu32_wrap selftest case), but the real fix needs to handle both directions - zext propagation should be done when either register has BPF_ADD_CONST32, since the linked relationship involves a 32-bit operation regardless of which side has the flag.
Example case with known_reg (exercised also by scalars_alu32_wrap):
1. r1 = r0; w1 += 0x100 (alu32 -- r1 gets BPF_ADD_CONST32)
2. if r1 > 0x80 - known_reg = r1 (has BPF_ADD_CONST32), reg = r0 (doesn't)
Hence, fix it by checking for (reg->id | known_reg->id) & BPF_ADD_CONST32.
Moreover, sync_linked_regs() also has a soundness issue when two linked registers used different ALU widths: one with BPF_ADD_CONST32 and the other with BPF_ADD_CONST64. The delta relationship between linked registers assumes the same arithmetic width though. When one register went through alu32 (CPU zero-extends the 32-bit result) and the other went through alu64 (no zero-extension), the propagation produces incorrect bounds.
Example:
r6 = bpf_get_prandom_u32() // fully unknown
if r6 >= 0x100000000 goto out // constrain r6 to [0, U32_MAX] r7 = r6
w7 += 1 // alu32: r7.id = N | BPF_ADD_CONST32
r8 = r6
r8 += 2 // alu64: r8.id = N | BPF_ADD_CONST64
if r7 < 0xFFFFFFFF goto out // narrows r7 to [0xFFFFFFFF, 0xFFFFFFFF]
At the branch on r7, sync_linked_regs() runs with known_reg=r7 (BPF_ADD_CONST32) and reg=r8 (BPF_ADD_CONST64). The delta path computes:
r8 = r7 + (delta_r8 - delta_r7) = 0xFFFFFFFF + (2 - 1) = 0x100000000
Then, because known_reg->id has BPF_ADD_CONST32, zext_32_to_64(r8) is called, truncating r8 to [0, 0]. But r8 used a 64-bit ALU op -- the CPU does NOT zero-extend it. The actual CPU value of r8 is 0xFFFFFFFE + 2 = 0x100000000, not 0. The verifier now underestimates r8's 64-bit bounds, which is a soundness violation.
Fix sync_linked_regs() by skipping propagation when the two registers have mixed ALU widths (one BPF_ADD_CONST32, the other BPF_ADD_CONST64).
Lastly, fix regsafe() used for path pruning: the existing checks used "& BPF_ADD_CONST" to test for offset linkage, which treated BPF_ADD_CONST32 and BPF_ADD_CONST64 as equivalent.
--- kernel/bpf/verifier.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-)
kernel/bpf/verifier.c +15 -6
@@ -16913,6 +16913,12 @@ static void sync_linked_regs(struct bpf_verifier_state *vstate, struct bpf_reg_scontinue ;if ((reg->id & ~BPF_ADD_CONST ) != (known_reg->id & ~BPF_ADD_CONST ))continue ; +/* +* Skip mixed 32/64-bit links: the delta relationship doesn't +* hold across different ALU widths. +*/ +if (((reg->id ^ known_reg->id) &BPF_ADD_CONST ) ==BPF_ADD_CONST ) +continue ;if ((!(reg->id &BPF_ADD_CONST ) && !(known_reg->id &BPF_ADD_CONST )) || reg->off == known_reg->off) {s32 saved_subreg_def = reg->subreg_def;
@@ -16940,7 +16946,7 @@ static void sync_linked_regs(struct bpf_verifier_state *vstate, struct bpf_reg_sscalar32_min_max_add (reg, &fake_reg);scalar_min_max_add (reg, &fake_reg); reg->var_off =tnum_add (reg->var_off, fake_reg.var_off); -if (known_reg->id &BPF_ADD_CONST32 ) +if ((reg->id | known_reg->id) &BPF_ADD_CONST32 )zext_32_to_64 (reg);reg_bounds_sync (reg); }
@@ -19056,11 +19062,14 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,* Also verify that new value satisfies old value range knowledge. */ -/* ADD_CONST mismatch: different linking semantics */ -if ((rold->id &BPF_ADD_CONST ) && !(rcur->id &BPF_ADD_CONST )) -return false; - -if (rold->id && !(rold->id &BPF_ADD_CONST ) && (rcur->id &BPF_ADD_CONST )) +/* +* ADD_CONST flags must match exactly: BPF_ADD_CONST32 and +* BPF_ADD_CONST64 have different linking semantics in +* sync_linked_regs() (alu32 zero-extends, alu64 does not), +* so pruning across different flag types is unsafe. +*/ +if (rold->id && + (rold->id &BPF_ADD_CONST ) != (rcur->id &BPF_ADD_CONST ))return false;/* Both have offset linkage: offsets must match */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 865/957 net: airoha: Fix a copy and paste bug in probe()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 05e090620bacf317020f9591cfff8926093380bd ]
This code has a copy and paste bug where it accidentally checks "if (err)" instead of checking if "xsi_rsts" is NULL. Also, as a free bonus, I changed the allocation from kzalloc() to kcalloc() which is a kernel hardening measure to protect against integer overflows.
--- drivers/net/ethernet/airoha/airoha_eth.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +4 -4
@@ -3097,11 +3097,11 @@ static int airoha_probe(struct platform_device *pdev)return err; } - xsi_rsts =devm_kzalloc (eth->dev, - eth->soc->num_xsi_rsts *sizeof (*xsi_rsts), + xsi_rsts =devm_kcalloc (eth->dev, + eth->soc->num_xsi_rsts,sizeof (*xsi_rsts),GFP_KERNEL ); -if (err) -return err; +if (!xsi_rsts) +return -ENOMEM ; eth->xsi_rsts = xsi_rsts;for (i =0 ; i < eth->soc->num_xsi_rsts; i++)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 866/957 fuse: fix race when disposing stale dentries
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miklos Szeredi <[email protected]>
[ Upstream commit cb8d2bdcb8241b66ca4ac4868f20e12cd6881ebc ]
In fuse_dentry_tree_work() just before d_dispose_if_unused() the dentry could get evicted, resulting in UAF.
Move unlocking dentry_hash[i].lock to after the dispose. To do this, fuse_dentry_tree_del_node() needs to be moved from fuse_dentry_prune() to fuse_dentry_release() to prevent an ABBA deadlock.
The lock ordering becomes:
-> dentry_bucket.lock
-> dentry.d_lock
Stable-dep-of: 1e2c1af1beb3 ("fuse: make sure dentry is evicted if stale")
--- fs/fuse/dir.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-)
fs/fuse/dir.c +2 -9
@@ -172,8 +172,8 @@ static void fuse_dentry_tree_work(struct work_struct *work)if (time_after64 (get_jiffies_64 (), fd->time)) {rb_erase (&fd->node, &dentry_hash[i].tree);RB_CLEAR_NODE (&fd->node); -spin_unlock (&dentry_hash[i].lock);d_dispose_if_unused (fd->dentry, &dispose); +spin_unlock (&dentry_hash[i].lock);cond_resched ();spin_lock (&dentry_hash[i].lock); }else
@@ -464,18 +464,12 @@ static int fuse_dentry_init(struct dentry *dentry)return 0 ; } -static void fuse_dentry_prune (struct dentry *dentry) +static void fuse_dentry_release (struct dentry *dentry) {struct fuse_dentry *fd = dentry->d_fsdata;if (!RB_EMPTY_NODE (&fd->node))fuse_dentry_tree_del_node (dentry); -} - -static void fuse_dentry_release (struct dentry *dentry) -{ -struct fuse_dentry *fd = dentry->d_fsdata; -kfree_rcu (fd, rcu); }
@@ -512,7 +506,6 @@ const struct dentry_operations fuse_dentry_operations = { .d_revalidate = fuse_dentry_revalidate, .d_delete = fuse_dentry_delete, .d_init = fuse_dentry_init, - .d_prune = fuse_dentry_prune, .d_release = fuse_dentry_release, .d_automount = fuse_dentry_automount, };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 867/957 fuse: make sure dentry is evicted if stale
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miklos Szeredi <[email protected]>
[ Upstream commit 1e2c1af1beb395841743e240a59ab37edc9a7d33 ]
d_dispose_if_unused() may find the dentry with a positive refcount, in which case it won't be put on the dispose list even though it has already timed out.
"Reinstall" the d_delete() callback, which was optimized out in fuse_dentry_settime(). This will result in the dentry being evicted as soon as the refcount hits zero.
--- fs/fuse/dir.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/fuse/dir.c +4 -0
@@ -172,6 +172,10 @@ static void fuse_dentry_tree_work(struct work_struct *work)if (time_after64 (get_jiffies_64 (), fd->time)) {rb_erase (&fd->node, &dentry_hash[i].tree);RB_CLEAR_NODE (&fd->node); +spin_lock (&fd->dentry->d_lock); +/* If dentry is still referenced, let next dput release it */ + fd->dentry->d_flags |=DCACHE_OP_DELETE ; +spin_unlock (&fd->dentry->d_lock);d_dispose_if_unused (fd->dentry, &dispose);spin_unlock (&dentry_hash[i].lock);cond_resched ();
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 868/957 rtla: Fix parse_cpu_set() bug introduced by strtoi()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Costa Shulyupin <[email protected]>
[ Upstream commit 6ea8a206108fe8b5940c2797afc54ae9f5a7bbdd ]
The patch 'Replace atoi() with a robust strtoi()' introduced a bug in parse_cpu_set(), which relies on partial parsing of the input string.
The function parses CPU specifications like '0-3,5' by incrementing a pointer through the string. strtoi() rejects strings with trailing characters, causing parse_cpu_set() to fail on any CPU list with multiple entries.
Restore the original use of atoi() in parse_cpu_set().
--- tools/tracing/rtla/src/utils.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
tools/tracing/rtla/src/utils.c +4 -6
@@ -113,18 +113,16 @@ int parse_cpu_set(char *cpu_list, cpu_set_t *set) nr_cpus =sysconf (_SC_NPROCESSORS_CONF);for (p = cpu_list; *p; ) { -if (strtoi (p, &cpu)) - goto err; -if (cpu <0 || cpu >= nr_cpus) + cpu =atoi (p); +if (cpu <0 || (!cpu && *p !='0' ) || cpu >= nr_cpus) goto err;while (isdigit (*p)) p++;if (*p =='-' ) { p++; -if (strtoi (p, &end_cpu)) - goto err; -if (end_cpu < cpu || end_cpu >= nr_cpus) + end_cpu =atoi (p); +if (end_cpu < cpu || (!end_cpu && *p !='0' ) || end_cpu >= nr_cpus) goto err;while (isdigit (*p)) p++;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 869/957 net: airoha: Move entries to queue head in case of DMA mapping failure in airoha_dev_xmit()
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 75df490c9e8457990c8b227650f6491218ce018b ]
In order to respect the original descriptor order and avoid any potential IOMMU fault or memory corruption, move pending queue entries to the head of hw queue tx_list if the DMA mapping of current inflight packet fails in airoha_dev_xmit routine.
--- drivers/net/ethernet/airoha/airoha_eth.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +2 -4
@@ -2136,14 +2136,12 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,return NETDEV_TX_OK ; error_unmap: -while (!list_empty (&tx_list)) { - e = list_first_entry(&tx_list, struct airoha_queue_entry, - list); +list_for_each_entry (e, &tx_list, list) {dma_unmap_single (dev->dev.parent, e->dma_addr, e->dma_len,DMA_TO_DEVICE ); e->dma_addr =0 ; -list_move_tail (&e->list, &q->tx_list); } +list_splice (&tx_list, &q->tx_list);spin_unlock_bh (&q->lock); error:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 870/957 net: airoha: Move ndesc initialization at end of airoha_qdma_init_tx()
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 f329924bb49458c65297f1361f545816a5b90998 ]
If queue entry list allocation fails in airoha_qdma_init_tx_queue routine, airoha_qdma_cleanup_tx_queue() will trigger a NULL pointer dereference accessing the queue entry array. The issue is due to the early ndesc initialization in airoha_qdma_init_tx_queue(). Fix the issue moving ndesc initialization at end of airoha_qdma_init_tx routine.
--- drivers/net/ethernet/airoha/airoha_eth.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +4 -4
@@ -1019,27 +1019,27 @@ static int airoha_qdma_init_tx_queue(struct airoha_queue *q,dma_addr_t dma_addr;spin_lock_init (&q->lock); - q->ndesc = size; q->qdma = qdma; q->free_thr =1 +MAX_SKB_FRAGS ;INIT_LIST_HEAD (&q->tx_list); - q->entry =devm_kzalloc (eth->dev, q->ndesc *sizeof (*q->entry), + q->entry =devm_kzalloc (eth->dev, size *sizeof (*q->entry),GFP_KERNEL );if (!q->entry)return -ENOMEM ; - q->desc =dmam_alloc_coherent (eth->dev, q->ndesc *sizeof (*q->desc), + q->desc =dmam_alloc_coherent (eth->dev, size *sizeof (*q->desc), &dma_addr,GFP_KERNEL );if (!q->desc)return -ENOMEM ; -for (i =0 ; i < q->ndesc; i++) { +for (i =0 ; i < size; i++) {u32 val =FIELD_PREP (QDMA_DESC_DONE_MASK ,1 );list_add_tail (&q->entry[i].list, &q->tx_list);WRITE_ONCE (q->desc[i].ctrl,cpu_to_le32 (val)); } + q->ndesc = size;/* xmit ring drop default setting */ airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(qid),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 871/957 net/sched: sch_pie: annotate more data-races in pie_dump_stats()
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 6d4106e8df94c0c52cf3ca6a6a0d01567fb3844e ]
My prior patch missed few READ_ONCE()/WRITE_ONCE() annotations.
--- net/sched/sch_pie.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
net/sched/sch_pie.c +6 -8
@@ -219,16 +219,14 @@ void pie_process_dequeue(struct sk_buff *skb, struct pie_params *params,* packet timestamp. */ if (!params->dq_rate_estimator) { - vars->qdelay = now -pie_get_enqueue_time (skb); +WRITE_ONCE (vars->qdelay, + backlog ? now -pie_get_enqueue_time (skb) :0 );if (vars->dq_tstamp !=DTIME_INVALID ) dtime = now - vars->dq_tstamp; vars->dq_tstamp = now; -if (backlog ==0 ) - vars->qdelay =0 ; -if (dtime ==0 )return ;
@@ -376,7 +374,7 @@ void pie_calculate_probability(struct pie_params *params, struct pie_vars *vars,if (qdelay > (PSCHED_NS2TICKS (250 *NSEC_PER_MSEC ))) delta +=MAX_PROB / (100 /2 ); - vars->prob += delta; +WRITE_ONCE (vars->prob, vars->prob + delta);if (delta >0 ) {/* prevent overflow */
@@ -401,7 +399,7 @@ void pie_calculate_probability(struct pie_params *params, struct pie_vars *vars,if (qdelay ==0 && qdelay_old ==0 && update_prob)/* Reduce drop probability to 98.4% */ - vars->prob -= vars->prob /64 ; +WRITE_ONCE (vars->prob, vars->prob - vars->prob /64 );WRITE_ONCE (vars->qdelay, qdelay); vars->backlog_old = backlog;
@@ -501,7 +499,7 @@ static int pie_dump_stats(struct Qdisc *sch, struct gnet_dump *d) {struct pie_sched_data *q =qdisc_priv (sch);struct tc_pie_xstats st = { - .prob = q->vars.prob <<BITS_PER_BYTE , + .prob =READ_ONCE (q->vars.prob) <<BITS_PER_BYTE , .delay = ((u32 )PSCHED_TICKS2NS (READ_ONCE (q->vars.qdelay))) /NSEC_PER_USEC , .packets_in =READ_ONCE (q->stats.packets_in),
@@ -512,7 +510,7 @@ static int pie_dump_stats(struct Qdisc *sch, struct gnet_dump *d) };/* avg_dq_rate is only valid if dq_rate_estimator is enabled */ - st.dq_rate_estimating = q->params.dq_rate_estimator; + st.dq_rate_estimating =READ_ONCE (q->params.dq_rate_estimator);/* unscale and return dq_rate in bytes per sec */ if (st.dq_rate_estimating)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 872/957 net: airoha: Remove code duplication in airoha_regs.h
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 99ad2b6815f41acbec15ab051ccc79b11b05710a ]
This patch does not introduce any logical change, it just removes duplicated code in airoha_regs.h.
Fix naming conventions in airoha_regs.h.
Stable-dep-of: 1acdfbdb516b ("net: airoha: Fix VIP configuration for AN7583 SoC")
--- drivers/net/ethernet/airoha/airoha_eth.c | 102 ++++++++++---------- drivers/net/ethernet/airoha/airoha_regs.h | 109 ++++++++++------------ 2 files changed, 100 insertions(+), 111 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +51 -51
@@ -137,11 +137,11 @@ static void airoha_fe_maccr_init(struct airoha_eth *eth)for (p =1 ; p <=ARRAY_SIZE (eth->ports); p++)airoha_fe_set (eth,REG_GDM_FWD_CFG (p), -GDM_TCP_CKSUM |GDM_UDP_CKSUM |GDM_IP4_CKSUM | -GDM_DROP_CRC_ERR ); +GDM_TCP_CKSUM_MASK |GDM_UDP_CKSUM_MASK | +GDM_IP4_CKSUM_MASK |GDM_DROP_CRC_ERR_MASK ); -airoha_fe_rmw (eth,REG_CDM1_VLAN_CTRL ,CDM1_VLAN_MASK , -FIELD_PREP (CDM1_VLAN_MASK ,0x8100 )); +airoha_fe_rmw (eth,REG_CDM_VLAN_CTRL (1 ),CDM_VLAN_MASK , +FIELD_PREP (CDM_VLAN_MASK ,0x8100 ));airoha_fe_set (eth,REG_FE_CPORT_CFG ,FE_CPORT_PAD ); }
@@ -405,46 +405,46 @@ static int airoha_fe_mc_vlan_clear(struct airoha_eth *eth)static void airoha_fe_crsn_qsel_init (struct airoha_eth *eth) {/* CDM1_CRSN_QSEL */ -airoha_fe_rmw (eth,REG_CDM1_CRSN_QSEL (CRSN_22 >>2 ), -CDM1_CRSN_QSEL_REASON_MASK (CRSN_22 ), -FIELD_PREP (CDM1_CRSN_QSEL_REASON_MASK (CRSN_22 ), +airoha_fe_rmw (eth,REG_CDM_CRSN_QSEL (1 ,CRSN_22 >>2 ), +CDM_CRSN_QSEL_REASON_MASK (CRSN_22 ), +FIELD_PREP (CDM_CRSN_QSEL_REASON_MASK (CRSN_22 ),CDM_CRSN_QSEL_Q1 )); -airoha_fe_rmw (eth,REG_CDM1_CRSN_QSEL (CRSN_08 >>2 ), -CDM1_CRSN_QSEL_REASON_MASK (CRSN_08 ), -FIELD_PREP (CDM1_CRSN_QSEL_REASON_MASK (CRSN_08 ), +airoha_fe_rmw (eth,REG_CDM_CRSN_QSEL (1 ,CRSN_08 >>2 ), +CDM_CRSN_QSEL_REASON_MASK (CRSN_08 ), +FIELD_PREP (CDM_CRSN_QSEL_REASON_MASK (CRSN_08 ),CDM_CRSN_QSEL_Q1 )); -airoha_fe_rmw (eth,REG_CDM1_CRSN_QSEL (CRSN_21 >>2 ), -CDM1_CRSN_QSEL_REASON_MASK (CRSN_21 ), -FIELD_PREP (CDM1_CRSN_QSEL_REASON_MASK (CRSN_21 ), +airoha_fe_rmw (eth,REG_CDM_CRSN_QSEL (1 ,CRSN_21 >>2 ), +CDM_CRSN_QSEL_REASON_MASK (CRSN_21 ), +FIELD_PREP (CDM_CRSN_QSEL_REASON_MASK (CRSN_21 ),CDM_CRSN_QSEL_Q1 )); -airoha_fe_rmw (eth,REG_CDM1_CRSN_QSEL (CRSN_24 >>2 ), -CDM1_CRSN_QSEL_REASON_MASK (CRSN_24 ), -FIELD_PREP (CDM1_CRSN_QSEL_REASON_MASK (CRSN_24 ), +airoha_fe_rmw (eth,REG_CDM_CRSN_QSEL (1 ,CRSN_24 >>2 ), +CDM_CRSN_QSEL_REASON_MASK (CRSN_24 ), +FIELD_PREP (CDM_CRSN_QSEL_REASON_MASK (CRSN_24 ),CDM_CRSN_QSEL_Q6 )); -airoha_fe_rmw (eth,REG_CDM1_CRSN_QSEL (CRSN_25 >>2 ), -CDM1_CRSN_QSEL_REASON_MASK (CRSN_25 ), -FIELD_PREP (CDM1_CRSN_QSEL_REASON_MASK (CRSN_25 ), +airoha_fe_rmw (eth,REG_CDM_CRSN_QSEL (1 ,CRSN_25 >>2 ), +CDM_CRSN_QSEL_REASON_MASK (CRSN_25 ), +FIELD_PREP (CDM_CRSN_QSEL_REASON_MASK (CRSN_25 ),CDM_CRSN_QSEL_Q1 ));/* CDM2_CRSN_QSEL */ -airoha_fe_rmw (eth,REG_CDM2_CRSN_QSEL (CRSN_08 >>2 ), -CDM2_CRSN_QSEL_REASON_MASK (CRSN_08 ), -FIELD_PREP (CDM2_CRSN_QSEL_REASON_MASK (CRSN_08 ), +airoha_fe_rmw (eth,REG_CDM_CRSN_QSEL (2 ,CRSN_08 >>2 ), +CDM_CRSN_QSEL_REASON_MASK (CRSN_08 ), +FIELD_PREP (CDM_CRSN_QSEL_REASON_MASK (CRSN_08 ),CDM_CRSN_QSEL_Q1 )); -airoha_fe_rmw (eth,REG_CDM2_CRSN_QSEL (CRSN_21 >>2 ), -CDM2_CRSN_QSEL_REASON_MASK (CRSN_21 ), -FIELD_PREP (CDM2_CRSN_QSEL_REASON_MASK (CRSN_21 ), +airoha_fe_rmw (eth,REG_CDM_CRSN_QSEL (2 ,CRSN_21 >>2 ), +CDM_CRSN_QSEL_REASON_MASK (CRSN_21 ), +FIELD_PREP (CDM_CRSN_QSEL_REASON_MASK (CRSN_21 ),CDM_CRSN_QSEL_Q1 )); -airoha_fe_rmw (eth,REG_CDM2_CRSN_QSEL (CRSN_22 >>2 ), -CDM2_CRSN_QSEL_REASON_MASK (CRSN_22 ), -FIELD_PREP (CDM2_CRSN_QSEL_REASON_MASK (CRSN_22 ), +airoha_fe_rmw (eth,REG_CDM_CRSN_QSEL (2 ,CRSN_22 >>2 ), +CDM_CRSN_QSEL_REASON_MASK (CRSN_22 ), +FIELD_PREP (CDM_CRSN_QSEL_REASON_MASK (CRSN_22 ),CDM_CRSN_QSEL_Q1 )); -airoha_fe_rmw (eth,REG_CDM2_CRSN_QSEL (CRSN_24 >>2 ), -CDM2_CRSN_QSEL_REASON_MASK (CRSN_24 ), -FIELD_PREP (CDM2_CRSN_QSEL_REASON_MASK (CRSN_24 ), +airoha_fe_rmw (eth,REG_CDM_CRSN_QSEL (2 ,CRSN_24 >>2 ), +CDM_CRSN_QSEL_REASON_MASK (CRSN_24 ), +FIELD_PREP (CDM_CRSN_QSEL_REASON_MASK (CRSN_24 ),CDM_CRSN_QSEL_Q6 )); -airoha_fe_rmw (eth,REG_CDM2_CRSN_QSEL (CRSN_25 >>2 ), -CDM2_CRSN_QSEL_REASON_MASK (CRSN_25 ), -FIELD_PREP (CDM2_CRSN_QSEL_REASON_MASK (CRSN_25 ), +airoha_fe_rmw (eth,REG_CDM_CRSN_QSEL (2 ,CRSN_25 >>2 ), +CDM_CRSN_QSEL_REASON_MASK (CRSN_25 ), +FIELD_PREP (CDM_CRSN_QSEL_REASON_MASK (CRSN_25 ),CDM_CRSN_QSEL_Q1 )); }
@@ -464,18 +464,18 @@ static int airoha_fe_init(struct airoha_eth *eth)airoha_fe_wr (eth,REG_FE_PCE_CFG ,PCE_DPI_EN_MASK |PCE_KA_EN_MASK |PCE_MC_EN_MASK );/* set vip queue selection to ring 1 */ -airoha_fe_rmw (eth,REG_CDM1_FWD_CFG ,CDM1_VIP_QSEL_MASK , -FIELD_PREP (CDM1_VIP_QSEL_MASK ,0x4 )); -airoha_fe_rmw (eth,REG_CDM2_FWD_CFG ,CDM2_VIP_QSEL_MASK , -FIELD_PREP (CDM2_VIP_QSEL_MASK ,0x4 )); +airoha_fe_rmw (eth,REG_CDM_FWD_CFG (1 ),CDM_VIP_QSEL_MASK , +FIELD_PREP (CDM_VIP_QSEL_MASK ,0x4 )); +airoha_fe_rmw (eth,REG_CDM_FWD_CFG (2 ),CDM_VIP_QSEL_MASK , +FIELD_PREP (CDM_VIP_QSEL_MASK ,0x4 ));/* set GDM4 source interface offset to 8 */ -airoha_fe_rmw (eth,REG_GDM4_SRC_PORT_SET , -GDM4_SPORT_OFF2_MASK | -GDM4_SPORT_OFF1_MASK | -GDM4_SPORT_OFF0_MASK , -FIELD_PREP (GDM4_SPORT_OFF2_MASK ,8 ) | -FIELD_PREP (GDM4_SPORT_OFF1_MASK ,8 ) | -FIELD_PREP (GDM4_SPORT_OFF0_MASK ,8 )); +airoha_fe_rmw (eth,REG_GDM_SRC_PORT_SET (4 ), +GDM_SPORT_OFF2_MASK | +GDM_SPORT_OFF1_MASK | +GDM_SPORT_OFF0_MASK , +FIELD_PREP (GDM_SPORT_OFF2_MASK ,8 ) | +FIELD_PREP (GDM_SPORT_OFF1_MASK ,8 ) | +FIELD_PREP (GDM_SPORT_OFF0_MASK ,8 ));/* set PSE Page as 128B */ airoha_fe_rmw(eth, REG_FE_DMA_GLO_CFG,
@@ -501,8 +501,8 @@ static int airoha_fe_init(struct airoha_eth *eth)airoha_fe_set (eth,REG_GDM_MISC_CFG ,GDM2_RDM_ACK_WAIT_PREF_MASK |GDM2_CHN_VLD_MODE_MASK ); -airoha_fe_rmw (eth,REG_CDM2_FWD_CFG ,CDM2_OAM_QSEL_MASK , -FIELD_PREP (CDM2_OAM_QSEL_MASK ,15 )); +airoha_fe_rmw (eth,REG_CDM_FWD_CFG (2 ),CDM_OAM_QSEL_MASK , +FIELD_PREP (CDM_OAM_QSEL_MASK ,15 ));/* init fragment and assemble Force Port */ /* NPU Core-3, NPU Bridge Channel-3 */
@@ -516,8 +516,8 @@ static int airoha_fe_init(struct airoha_eth *eth)FIELD_PREP (IP_ASSEMBLE_PORT_MASK ,0 ) | FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22)); -airoha_fe_set (eth,REG_GDM3_FWD_CFG ,GDM3_PAD_EN_MASK ); -airoha_fe_set (eth,REG_GDM4_FWD_CFG ,GDM4_PAD_EN_MASK ); +airoha_fe_set (eth,REG_GDM_FWD_CFG (3 ),GDM_PAD_EN_MASK ); +airoha_fe_set (eth,REG_GDM_FWD_CFG (4 ),GDM_PAD_EN_MASK );airoha_fe_crsn_qsel_init (eth);
@@ -525,7 +525,7 @@ static int airoha_fe_init(struct airoha_eth *eth)airoha_fe_set (eth,REG_FE_CPORT_CFG ,FE_CPORT_PORT_XFC_MASK );/* default aging mode for mbi unlock issue */ -airoha_fe_rmw (eth,REG_GDM2_CHN_RLS , +airoha_fe_rmw (eth,REG_GDM_CHN_RLS (2 ),MBI_RX_AGE_SEL_MASK |MBI_TX_AGE_SEL_MASK ,FIELD_PREP (MBI_RX_AGE_SEL_MASK ,3 ) |FIELD_PREP (MBI_TX_AGE_SEL_MASK ,3 ));
@@ -1816,7 +1816,7 @@ static int airhoha_set_gdm2_loopback(struct airoha_gdm_port *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 (2 ), pse_port); -airoha_fe_clear (eth,REG_GDM_FWD_CFG (2 ),GDM_STRIP_CRC ); +airoha_fe_clear (eth,REG_GDM_FWD_CFG (2 ),GDM_STRIP_CRC_MASK );/* Enable GDM2 loopback */ airoha_fe_wr (eth,REG_GDM_TXCHN_EN (2 ),0xffffffff );
drivers/net/ethernet/airoha/airoha_regs.h +49 -60
151 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 873/957 net: airoha: Use gdm port enum value whenever possible
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 4d513329b87c1bd0546d9f0288794e244322daa6 ]
Use AIROHA_GDMx_IDX enum value whenever possible.
This patch is just cosmetic changes and does not introduce any logic one.
Stable-dep-of: 1acdfbdb516b ("net: airoha: Fix VIP configuration for AN7583 SoC")
--- drivers/net/ethernet/airoha/airoha_eth.c | 40 +++++++++++++----------- 1 file changed, 21 insertions(+), 19 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +21 -19
@@ -108,11 +108,11 @@ static int airoha_set_vip_for_gdm_port(struct airoha_gdm_port *port,u32 vip_port;switch (port->id) { -case 3 : +case AIROHA_GDM3_IDX :/* FIXME: handle XSI_PCIE1_PORT */ vip_port =XSI_PCIE0_VIP_PORT_MASK ;break ; -case 4 : +case AIROHA_GDM4_IDX :/* FIXME: handle XSI_USB_PORT */ vip_port =XSI_ETH_VIP_PORT_MASK ;break ;
@@ -516,8 +516,8 @@ static int airoha_fe_init(struct airoha_eth *eth)FIELD_PREP (IP_ASSEMBLE_PORT_MASK ,0 ) | FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22)); -airoha_fe_set (eth,REG_GDM_FWD_CFG (3 ),GDM_PAD_EN_MASK ); -airoha_fe_set (eth,REG_GDM_FWD_CFG (4 ),GDM_PAD_EN_MASK ); +airoha_fe_set (eth,REG_GDM_FWD_CFG (AIROHA_GDM3_IDX ),GDM_PAD_EN_MASK ); +airoha_fe_set (eth,REG_GDM_FWD_CFG (AIROHA_GDM4_IDX ),GDM_PAD_EN_MASK );airoha_fe_crsn_qsel_init (eth);
@@ -1815,27 +1815,29 @@ static int airhoha_set_gdm2_loopback(struct airoha_gdm_port *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 (2 ), pse_port); -airoha_fe_clear (eth,REG_GDM_FWD_CFG (2 ),GDM_STRIP_CRC_MASK ); +airoha_set_gdm_port_fwd_cfg (eth,REG_GDM_FWD_CFG (AIROHA_GDM2_IDX ), + pse_port); +airoha_fe_clear (eth,REG_GDM_FWD_CFG (AIROHA_GDM2_IDX ), +GDM_STRIP_CRC_MASK );/* Enable GDM2 loopback */ -airoha_fe_wr (eth,REG_GDM_TXCHN_EN (2 ),0xffffffff ); -airoha_fe_wr (eth,REG_GDM_RXCHN_EN (2 ),0xffff ); +airoha_fe_wr (eth,REG_GDM_TXCHN_EN (AIROHA_GDM2_IDX ),0xffffffff ); +airoha_fe_wr (eth,REG_GDM_RXCHN_EN (AIROHA_GDM2_IDX ),0xffff ); chan = port->id ==AIROHA_GDM3_IDX ?airoha_is_7581 (eth) ?4 :3 :0 ; -airoha_fe_rmw (eth,REG_GDM_LPBK_CFG (2 ), +airoha_fe_rmw (eth,REG_GDM_LPBK_CFG (AIROHA_GDM2_IDX ),LPBK_CHAN_MASK |LPBK_MODE_MASK |LPBK_EN_MASK ,FIELD_PREP (LPBK_CHAN_MASK , chan) |LBK_GAP_MODE_MASK |LBK_LEN_MODE_MASK |LBK_CHAN_MODE_MASK |LPBK_EN_MASK ); -airoha_fe_rmw (eth,REG_GDM_LEN_CFG (2 ), +airoha_fe_rmw (eth,REG_GDM_LEN_CFG (AIROHA_GDM2_IDX ),GDM_SHORT_LEN_MASK |GDM_LONG_LEN_MASK ,FIELD_PREP (GDM_SHORT_LEN_MASK ,60 ) |FIELD_PREP (GDM_LONG_LEN_MASK ,AIROHA_MAX_MTU ));/* Disable VIP and IFC for GDM2 */ -airoha_fe_clear (eth,REG_FE_VIP_PORT_EN ,BIT (2 )); -airoha_fe_clear (eth,REG_FE_IFC_PORT_EN ,BIT (2 )); +airoha_fe_clear (eth,REG_FE_VIP_PORT_EN ,BIT (AIROHA_GDM2_IDX )); +airoha_fe_clear (eth,REG_FE_IFC_PORT_EN ,BIT (AIROHA_GDM2_IDX ));/* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */ nbq = port->id ==AIROHA_GDM3_IDX &&airoha_is_7581 (eth) ?4 :0 ;
@@ -1869,8 +1871,8 @@ static int airoha_dev_init(struct net_device *dev)airoha_set_macaddr (port, dev->dev_addr);switch (port->id) { -case 3 : -case 4 : +case AIROHA_GDM3_IDX : +case AIROHA_GDM4_IDX :/* If GDM2 is active we can't enable loopback */ if (!eth->ports[1 ]) {int err;
@@ -1880,7 +1882,7 @@ static int airoha_dev_init(struct net_device *dev)return err; } fallthrough; -case 2 : +case AIROHA_GDM2_IDX :if (airoha_ppe_is_enabled (eth,1 )) { pse_port =FE_PSE_PORT_PPE2 ;break ;
@@ -3206,14 +3208,14 @@ static const char * const en7581_xsi_rsts_names[] = {static int airoha_en7581_get_src_port_id (struct airoha_gdm_port *port,int nbq) {switch (port->id) { -case 3 : +case AIROHA_GDM3_IDX :/* 7581 SoC supports PCIe serdes on GDM3 port */ if (nbq ==4 )return HSGMII_LAN_7581_PCIE0_SRCPORT ;if (nbq ==5 )return HSGMII_LAN_7581_PCIE1_SRCPORT ;break ; -case 4 : +case AIROHA_GDM4_IDX :/* 7581 SoC supports eth and usb serdes on GDM4 port */ if (!nbq)return HSGMII_LAN_7581_ETH_SRCPORT ;
@@ -3237,12 +3239,12 @@ static const char * const an7583_xsi_rsts_names[] = {static int airoha_an7583_get_src_port_id (struct airoha_gdm_port *port,int nbq) {switch (port->id) { -case 3 : +case AIROHA_GDM3_IDX :/* 7583 SoC supports eth serdes on GDM3 port */ if (!nbq)return HSGMII_LAN_7583_ETH_SRCPORT ;break ; -case 4 : +case AIROHA_GDM4_IDX :/* 7583 SoC supports PCIe and USB serdes on GDM4 port */ if (!nbq)return HSGMII_LAN_7583_PCIE_SRCPORT ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 874/957 net: airoha: Fix VIP configuration for AN7583 SoC
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 1acdfbdb516b32165a8ecd1d5f8c68e4eac64637 ]
EN7581 and AN7583 SoCs have different VIP definitions. Introduce get_vip_port callback in airoha_eth_soc_data struct in order to take into account EN7581 and AN7583 VIP register layout and definition differences.
Introduce nbq parameter in airoha_gdm_port struct. At the moment nbq is set statically to value previously used in airhoha_set_gdm2_loopback routine and it will be read from device tree in subsequent patches.
--- drivers/net/ethernet/airoha/airoha_eth.c | 66 ++++++++++++++++++------ drivers/net/ethernet/airoha/airoha_eth.h | 2 + 2 files changed, 51 insertions(+), 17 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +49 -17
@@ -107,19 +107,7 @@ static int airoha_set_vip_for_gdm_port(struct airoha_gdm_port *port,struct airoha_eth *eth = port->qdma->eth;u32 vip_port; -switch (port->id) { -case AIROHA_GDM3_IDX : -/* FIXME: handle XSI_PCIE1_PORT */ - vip_port =XSI_PCIE0_VIP_PORT_MASK ; -break ; -case AIROHA_GDM4_IDX : -/* FIXME: handle XSI_USB_PORT */ - vip_port =XSI_ETH_VIP_PORT_MASK ; -break ; -default : -return 0 ; - } - + vip_port = eth->soc->ops.get_vip_port (port, port->nbq);if (enable) {airoha_fe_set (eth,REG_FE_VIP_PORT_EN , vip_port);airoha_fe_set (eth,REG_FE_IFC_PORT_EN , vip_port);
@@ -1809,7 +1797,7 @@ static int airoha_dev_set_macaddr(struct net_device *dev, void *p)static int airhoha_set_gdm2_loopback (struct airoha_gdm_port *port) {struct airoha_eth *eth = port->qdma->eth; -u32 val, pse_port, chan, nbq; +u32 val, pse_port, chan;int src_port;/* Forward the traffic to the proper GDM port */
@@ -1839,9 +1827,7 @@ static int airhoha_set_gdm2_loopback(struct airoha_gdm_port *port)airoha_fe_clear (eth,REG_FE_VIP_PORT_EN ,BIT (AIROHA_GDM2_IDX ));airoha_fe_clear (eth,REG_FE_IFC_PORT_EN ,BIT (AIROHA_GDM2_IDX )); -/* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */ - nbq = port->id ==AIROHA_GDM3_IDX &&airoha_is_7581 (eth) ?4 :0 ; - src_port = eth->soc->ops.get_src_port_id (port, nbq); + src_port = eth->soc->ops.get_src_port_id (port, port->nbq);if (src_port <0 )return src_port;
@@ -3034,6 +3020,8 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth, port->qdma = qdma; port->dev = dev; port->id = id; +/* XXX: Read nbq from DTS */ + port->nbq = id ==AIROHA_GDM3_IDX &&airoha_is_7581 (eth) ?4 :0 ; eth->ports[p] = port;return airoha_metadata_dst_alloc (port);
@@ -3229,6 +3217,28 @@ static int airoha_en7581_get_src_port_id(struct airoha_gdm_port *port, int nbq)return -EINVAL ; } +static u32 airoha_en7581_get_vip_port (struct airoha_gdm_port *port,int nbq) +{ +switch (port->id) { +case AIROHA_GDM3_IDX : +if (nbq ==4 ) +return XSI_PCIE0_VIP_PORT_MASK ; +if (nbq ==5 ) +return XSI_PCIE1_VIP_PORT_MASK ; +break ; +case AIROHA_GDM4_IDX : +if (!nbq) +return XSI_ETH_VIP_PORT_MASK ; +if (nbq ==1 ) +return XSI_USB_VIP_PORT_MASK ; +break ; +default : +break ; + } + +return 0 ; +} +static const char *const an7583_xsi_rsts_names[] = {"xsi-mac" ,"hsi0-mac" ,
@@ -3258,6 +3268,26 @@ static int airoha_an7583_get_src_port_id(struct airoha_gdm_port *port, int nbq)return -EINVAL ; } +static u32 airoha_an7583_get_vip_port (struct airoha_gdm_port *port,int nbq) +{ +switch (port->id) { +case AIROHA_GDM3_IDX : +if (!nbq) +return XSI_ETH_VIP_PORT_MASK ; +break ; +case AIROHA_GDM4_IDX : +if (!nbq) +return XSI_PCIE0_VIP_PORT_MASK ; +if (nbq ==1 ) +return XSI_USB_VIP_PORT_MASK ; +break ; +default : +break ; + } + +return 0 ; +} +static const struct airoha_eth_soc_data en7581_soc_data = { .version =0x7581 , .xsi_rsts_names = en7581_xsi_rsts_names,
@@ -3265,6 +3295,7 @@ static const struct airoha_eth_soc_data en7581_soc_data = { .num_ppe = 2, .ops = { .get_src_port_id = airoha_en7581_get_src_port_id, + .get_vip_port = airoha_en7581_get_vip_port, }, };
@@ -3275,6 +3306,7 @@ static const struct airoha_eth_soc_data an7583_soc_data = { .num_ppe = 1, .ops = { .get_src_port_id = airoha_an7583_get_src_port_id, + .get_vip_port = airoha_an7583_get_vip_port, }, };
drivers/net/ethernet/airoha/airoha_eth.h +2 -0
@@ -536,6 +536,7 @@ struct airoha_gdm_port {struct airoha_qdma *qdma;struct net_device *dev;int id; +int nbq;struct airoha_hw_stats stats;
@@ -576,6 +577,7 @@ struct airoha_eth_soc_data {int num_ppe;struct {int (*get_src_port_id)(struct airoha_gdm_port *port,int nbq); +u32 (*get_vip_port)(struct airoha_gdm_port *port,int nbq); } ops; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 875/957 net: mana: Fix use-after-free in reset service rescan path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dipayaan Roy <[email protected]>
[ Upstream commit 3387a7ad478b46970ae8254049167d166e398aeb ]
When mana_serv_reset() encounters -ETIMEDOUT or -EPROTO from mana_gd_resume(), it performs a PCI rescan via mana_serv_rescan().
mana_serv_rescan() calls pci_stop_and_remove_bus_device(), which can invoke the driver's remove path and free the gdma_context associated with the device. After returning, mana_serv_reset() currently jumps to the out label and attempts to clear gc->in_service, dereferencing a freed gdma_context.
The issue was observed with the following call logs:
[ 698.942636] BUG: unable to handle page fault for address: ff6c2b638088508d [ 698.943121] #PF: supervisor write access in kernel mode [ 698.943423] #PF: error_code(0x0002) - not-present page
[S[ 698.943793] Pat Dec 6 07:GD5 100000067 P4D 1002f7067 PUD 1002f8067 PMD 101bef067 PTE 0 0:56 2025] hv_[n e 698.944283] Oops: Oops: 0002 [#1] SMP NOPTI
tvsc f8615163-00[ 698.944611] CPU: 28 UID: 0 PID: 249 Comm: kworker/28:1
...
[Sat Dec 6 07:50:56 2025] R10: [ 699.121594] mana 7870:00:00.0 enP30832s1: Configured vPort 0 PD 18 DB 16 000000000000001b R11: 0000000000000000 R12: ff44cf3f40270000 [Sat Dec 6 07:50:56 2025] R13: 0000000000000001 R14: ff44cf3f402700c8 R15: ff44cf3f4021b405 [Sat Dec 6 07:50:56 2025] FS: 0000000000000000(0000) GS:ff44cf7e9fcf9000(0000) knlGS:0000000000000000 [Sat Dec 6 07:50:56 2025] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [Sat Dec 6 07:50:56 2025] CR2: ff6c2b638088508d CR3: 000000011fe43001 CR4: 0000000000b73ef0 [Sat Dec 6 07:50:56 2025] Call Trace: [Sat Dec 6 07:50:56 2025] <TASK> [Sat Dec 6 07:50:56 2025] mana_serv_func+0x24/0x50 [mana] [Sat Dec 6 07:50:56 2025] process_one_work+0x190/0x350 [Sat Dec 6 07:50:56 2025] worker_thread+0x2b7/0x3d0 [Sat Dec 6 07:50:56 2025] kthread+0xf3/0x200 [Sat Dec 6 07:50:56 2025] ? __pfx_worker_thread+0x10/0x10 [Sat Dec 6 07:50:56 2025] ? __pfx_kthread+0x10/0x10 [Sat Dec 6 07:50:56 2025] ret_from_fork+0x21a/0x250 [Sat Dec 6 07:50:56 2025] ? __pfx_kthread+0x10/0x10 [Sat Dec 6 07:50:56 2025] ret_from_fork_asm+0x1a/0x30 [Sat Dec 6 07:50:56 2025] </TASK>
Fix this by returning immediately after mana_serv_rescan() to avoid accessing GC state that may no longer be valid.
--- drivers/net/ethernet/microsoft/mana/gdma_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/microsoft/mana/gdma_main.c +1 -1
@@ -481,7 +481,7 @@ static void mana_serv_reset(struct pci_dev *pdev)/* Perform PCI rescan on device if we failed on HWC */ dev_err (&pdev->dev,"MANA service: resume failed, rescanning\n" );mana_serv_rescan (pdev); - goto out; +return ; }if (ret)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 876/957 net: mana: Init gf_stats_work before potential error paths in probe
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 6e8bc03349fe4f09567fa76235abf52bdaf83082 ]
Move INIT_DELAYED_WORK(gf_stats_work) to before mana_create_eq(), while keeping schedule_delayed_work() at its original location.
Previously, if any function between mana_create_eq() and the INIT_DELAYED_WORK call failed, mana_probe() would call mana_remove() which unconditionally calls cancel_delayed_work_sync(gf_stats_work) in __flush_work() or debug object warnings with CONFIG_DEBUG_OBJECTS_WORK enabled.
--- drivers/net/ethernet/microsoft/mana/mana_en.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/microsoft/mana/mana_en.c +2 -1
@@ -3607,6 +3607,8 @@ int mana_probe(struct gdma_dev *gd, bool resuming)INIT_WORK (&ac->link_change_work, mana_link_state_handle); } +INIT_DELAYED_WORK (&ac->gf_stats_work, mana_gf_stats_work_handler); + err =mana_create_eq (ac);if (err) {dev_err (dev,"Failed to create EQs: %d\n" , err);
@@ -3680,7 +3682,6 @@ int mana_probe(struct gdma_dev *gd, bool resuming)if (!err) err =add_adev (gd,"eth" ); -INIT_DELAYED_WORK (&ac->gf_stats_work, mana_gf_stats_work_handler);schedule_delayed_work (&ac->gf_stats_work,MANA_GF_STATS_PERIOD ); out:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 877/957 sched/fair: Fix wakeup_preempt_fair() for not waking up task
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vincent Guittot <[email protected]>
[ Upstream commit 9f6d929ee2c6f0266edb564bcd2bd47fd6e884a8 ]
Make sure to only call pick_next_entity() on an non-empty cfs_rq.
The assumption that p is always enqueued and not delayed, is only true for wakeup. If p was moved while delayed, pick_next_entity() will dequeue it and the cfs might become empty. Test if there are still queued tasks before trying again to determine if p could be the next one to be picked.
There are at least 2 cases:
When cfs becomes idle, it tries to pull tasks but if those pulled tasks are delayed, they will be dequeued when attached to cfs. attach_tasks() -> attach_task() -> wakeup_preempt(rq, p, 0);
A misfit task running on cfs A triggers a load balance to be pulled on a better cpu, the load balance on cfs B starts an active load balance to pulled the running misfit task. If there is a delayed dequeue task on cfs A, it can be pulled instead of the previously running misfit task. attach_one_task() -> attach_task() -> wakeup_preempt(rq, p, 0);
--- kernel/sched/fair.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
kernel/sched/fair.c +3 -2
@@ -8985,9 +8985,10 @@ static void check_preempt_wakeup_fair(struct rq *rq, struct task_struct *p, int/* * Because p is enqueued, nse being null can only mean that we -* dequeued a delayed task. +* dequeued a delayed task. If there are still entities queued in +* cfs, check if the next one will be p. */ -if (!nse) +if (!nse && cfs_rq->nr_queued) goto pick;if (sched_feat (RUN_TO_PARITY ))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 878/957 sched/fair: Revert force wakeup preemption
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vincent Guittot <[email protected]>
[ Upstream commit 15257cc2f905dbf5813c0bfdd3c15885f28093c4 ]
This agressively bypasses run_to_parity and slice protection with the assumpiton that this is what waker wants but there is no garantee that the wakee will be the next to run. It is a better choice to use yield_to_task or WF_SYNC in such case.
This increases the number of resched and preemption because a task becomes quickly "ineligible" when it runs; We update the task vruntime periodically and before the task exhausted its slice or at least quantum.
Example:
2 tasks A and B wake up simultaneously with lag = 0. Both are eligible. Task A runs 1st and wakes up task C. Scheduler updates task A's vruntime which becomes greater than average runtime as all others have a lag == 0 and didn't run yet. Now task A is ineligible because it received more runtime than the other task but it has not yet exhausted its slice nor a min quantum. We force preemption, disable protection but Task B will run 1st not task C.
Sidenote, DELAY_ZERO increases this effect by clearing positive lag at wake up.
--- kernel/sched/fair.c | 10 ---------- 1 file changed, 10 deletions(-)
kernel/sched/fair.c +0 -10
@@ -8943,16 +8943,6 @@ static void check_preempt_wakeup_fair(struct rq *rq, struct task_struct *p, intif ((wake_flags &WF_FORK ) || pse->sched_delayed)return ; -/* -* If @p potentially is completing work required by current then -* consider preemption. -* -* Reschedule if waker is no longer eligible. */ -if (in_task () && !entity_eligible (cfs_rq, se)) { - preempt_action =PREEMPT_WAKEUP_RESCHED ; - goto preempt; - } -/* Prefer picking wakee soon if appropriate. */ if (sched_feat (NEXT_BUDDY ) &&set_preempt_buddy (cfs_rq, wake_flags, pse, se)) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 879/957 crypto: af_alg - Cap AEAD AD length to 0x80000000
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu <[email protected]>
commit e4c06479d7059888adf2f22bc1ebcf053bf691a2 upstream.
In order to prevent arithmetic overflows when checking the TX buffer size, cap the associated data length to 0x80000000.
--- crypto/af_alg.c | 2 ++ 1 file changed, 2 insertions(+)
crypto/af_alg.c +2 -0
@@ -586,6 +586,8 @@ static int af_alg_cmsg_send(struct msghdif (cmsg->cmsg_len <CMSG_LEN (sizeof (u32)))return -EINVAL ; con->aead_assoclen = *(u32 *)CMSG_DATA (cmsg); +if (con->aead_assoclen >=0x80000000u ) +return -EINVAL ;break ;default :
Greg Kroah-Hartman
maintainerPATCH 880/957 i40e: Cleanup PTP pins on probe failure
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Vollrath <[email protected]>
commit 678b713ece1e853f11e670a84cb887c35e1381b7 upstream.
PTP pin structs are allocated early in probe, but never cleaned up.
Fix this by calling i40e_ptp_free_pins in the error path.
To support this, i40e_ptp_free_pins is added to the header and pin_config is correctly nullified after being freed.
This has been an issue since i40e_ptp_alloc_pins was introduced.
--- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + drivers/net/ethernet/intel/i40e/i40e_ptp.c | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/i40e/i40e.h +1 -0
@@ -1314,6 +1314,7 @@ void i40e_ptp_restore_hw_time(struct i40void i40e_ptp_init (struct i40e_pf *pf);void i40e_ptp_stop (struct i40e_pf *pf);int i40e_ptp_alloc_pins (struct i40e_pf *pf); +void i40e_ptp_free_pins (struct i40e_pf *pf);int i40e_update_adq_vsi_queues (struct i40e_vsi *vsi,int vsi_offset);int i40e_is_vsi_uplink_mode_veb (struct i40e_vsi *vsi);int i40e_get_partition_bw_setting (struct i40e_pf *pf);
drivers/net/ethernet/intel/i40e/i40e_main.c +1 -0
@@ -16114,6 +16114,7 @@ err_vsis:i40e_clear_interrupt_scheme (pf);kfree (pf->vsi); err_switch_setup: +i40e_ptp_free_pins (pf);i40e_reset_interrupt_capability (pf);timer_shutdown_sync (&pf->service_timer); err_mac_addr:
drivers/net/ethernet/intel/i40e/i40e_ptp.c +2 -1
@@ -940,12 +940,13 @@ int i40e_ptp_hwtstamp_get(struct net_dev* * Release memory allocated for PTP pins. **/ -static void i40e_ptp_free_pins (struct i40e_pf *pf) +void i40e_ptp_free_pins (struct i40e_pf *pf) {if (i40e_is_ptp_pin_dev (&pf->hw)) {kfree (pf->ptp_pins);kfree (pf->ptp_caps.pin_config); pf->ptp_pins =NULL ; + pf->ptp_caps.pin_config =NULL ; } }
Greg Kroah-Hartman
maintainerPATCH 881/957 workqueue: Fix wq->cpu_pwq leak in alloc_and_link_pwqs() WQ_UNBOUND path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
commit 0143033dc22cdff912cfc13419f5db92fea3b4cb upstream.
For WQ_UNBOUND workqueues, alloc_and_link_pwqs() allocates wq->cpu_pwq via alloc_percpu() and then calls apply_workqueue_attrs_locked(). On failure it returns the error directly, bypassing the enomem: label which holds the only free_percpu(wq->cpu_pwq) in this function.
The caller's error path kfree()s wq without touching wq->cpu_pwq, leaking one percpu pointer table (nr_cpu_ids * sizeof(void *) bytes) per failed call.
If kmemleak is enabled, we can see:
unreferenced object (percpu) 0xc0fffa5b121048 (size 8):
comm "insmod", pid 776, jiffies 4294682844
backtrace (crc 0):
pcpu_alloc_noprof+0x665/0xac0
__alloc_workqueue+0x33f/0xa20
alloc_workqueue_noprof+0x60/0x100Route the error through the existing enomem: cleanup and any error before this one.
--- kernel/workqueue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/workqueue.c +3 -1
@@ -5619,7 +5619,9 @@ static int alloc_and_link_pwqs(struct wo ret =apply_workqueue_attrs_locked (wq, unbound_std_wq_attrs[highpri]); } -return ret; +if (ret) + goto enomem; +return 0 ; enomem:if (wq->cpu_pwq) {
Greg Kroah-Hartman
maintainerPATCH 882/957 net: ena: PHC: Fix potential use-after-free in get_timestamp
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arthur Kiyanovski <[email protected]>
commit e42c755582f0960e684298762f0ab927b3778376 upstream.
Move the phc->active check and resp pointer assignment to after acquiring the spinlock. Previously, phc->active was checked without holding the lock, and resp was cached from ena_dev->phc.virt_addr before the lock was acquired.
If ena_com_phc_destroy() runs between the lockless active check and the lock acquisition, it sets active=false, releases the lock, frees the DMA memory, and sets virt_addr=NULL. The get_timestamp path would then read a NULL virt_addr and dereference it.
With both the active check and the pointer read under the lock, destroy cannot free the memory while get_timestamp is using it.
--- drivers/net/ethernet/amazon/ena/ena_com.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/net/ethernet/amazon/ena/ena_com.c +5 -2
@@ -1782,20 +1782,23 @@ void ena_com_phc_destroy(struct ena_com_dev *ena_dev)int ena_com_phc_get_timestamp (struct ena_com_dev *ena_dev,u64 *timestamp) { -volatile struct ena_admin_phc_resp *resp = ena_dev->phc.virt_addr;const ktime_t zero_system_time =ktime_set (0 ,0 );struct ena_com_phc_info *phc = &ena_dev->phc; +volatile struct ena_admin_phc_resp *resp;ktime_t expire_time;ktime_t block_time;unsigned long flags =0 ;int ret =0 ; +spin_lock_irqsave (&phc->lock, flags); +if (!phc->active) { +spin_unlock_irqrestore (&phc->lock, flags);netdev_err (ena_dev->net_device,"PHC feature is not active in the device\n" );return -EOPNOTSUPP ; } -spin_lock_irqsave (&phc->lock, flags); + resp = ena_dev->phc.virt_addr;/* Check if PHC is in blocked state */ if (unlikely (ktime_compare (phc->system_time, zero_system_time))) {
Signature · 1 line
2.54.0
Greg Kroah-Hartman
maintainerPATCH 883/957 netfilter: nf_conntrack_sip: get helper before allocating expectation
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Xiasong <[email protected]>
commit eb6317739b1ea3ab28791e1f91b24781905fa815 upstream.
process_register_request() allocates an expectation and then checks whether a conntrack helper is available. If helper lookup fails, the function returns early and the allocated expectation is left behind.
Reorder the code to fetch and validate helper before calling nf_ct_expect_alloc(). This keeps the logic simpler and removes the leak path while preserving existing behavior.
--- net/netfilter/nf_conntrack_sip.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/netfilter/nf_conntrack_sip.c +4 -4
@@ -1367,6 +1367,10 @@ static int process_register_request(stru goto store_cseq; } + helper =rcu_dereference (nfct_help (ct)->helper); +if (!helper) +return NF_DROP ; + exp =nf_ct_expect_alloc (ct);if (!exp) {nf_ct_helper_log (skb, ct,"cannot alloc expectation" );
@@ -1377,10 +1381,6 @@ static int process_register_request(struif (sip_direct_signalling) saddr = &ct->tuplehash[!dir].tuple.src.u3; - helper =rcu_dereference (nfct_help (ct)->helper); -if (!helper) -return NF_DROP ; -nf_ct_expect_init (exp,SIP_EXPECT_SIGNALLING ,nf_ct_l3num (ct), saddr, &daddr, proto,NULL , &port); exp->timeout.expires = sip_timeout *HZ ;
Greg Kroah-Hartman
maintainerPATCH 884/957 audit: fix incorrect inheritable capability in CAPSET records
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergio Correia <[email protected]>
commit e4a640475e43f406fdfd56d370b1f34b0cbbc18d upstream.
__audit_log_capset() records the effective capability set into the inheritable field due to a copy-paste error. Every CAPSET audit record therefore reports cap_pi (process inheritable) with the value of cap_effective instead of cap_inheritable.
This silently corrupts audit data used for compliance and forensic
analysis: an attacker who modifies inheritable capabilities to prepare for a privilege-escalating exec would have the change masked in the audit trail.
The bug has been present since the original introduction of CAPSET audit records in 2008.
--- kernel/auditsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/auditsc.c +1 -1
@@ -2814,7 +2814,7 @@ void __audit_log_capset(const struct cre context->capset.pid =task_tgid_nr (current); context->capset.cap.effective = new->cap_effective; - context->capset.cap.inheritable = new->cap_effective; + context->capset.cap.inheritable = new->cap_inheritable; context->capset.cap.permitted = new->cap_permitted; context->capset.cap.ambient = new->cap_ambient; context->type =AUDIT_CAPSET ;
Greg Kroah-Hartman
maintainerPATCH 885/957 net: ena: PHC: Check return code before setting timestamp output
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arthur Kiyanovski <[email protected]>
commit 24a08d7d6218d60c033015cf4870b6096446e734 upstream.
ena_phc_gettimex64() is setting the output parameter regardless of whether ena_com_phc_get_timestamp() succeeded or failed.
When ena_com_phc_get_timestamp() returns an error, the timestamp parameter may contain uninitialized stack memory (e.g., when PHC is disabled or in blocked state) or invalid hardware values. Passing these to userspace via the PTP ioctl is both a security issue (information leak) and a correctness bug.
Fix by checking the return code after releasing the lock and only setting the output timestamp on success.
--- drivers/net/ethernet/amazon/ena/ena_phc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/ethernet/amazon/ena/ena_phc.c +4 -1
@@ -46,9 +46,12 @@ static int ena_phc_gettimex64(struct ptp_clock_info *clock_info,spin_unlock_irqrestore (&phc_info->lock, flags); +if (rc) +return rc; + *ts =ns_to_timespec64 (timestamp_nsec); -return rc; +return 0 ; } static int ena_phc_settime64(struct ptp_clock_info *clock_info,
Signature · 1 line
2.54.0
Greg Kroah-Hartman
maintainerPATCH 886/957 cgroup/dmem: Return -ENOMEM on failed pool preallocation
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guopeng Zhang <[email protected]>
commit 796ad622040f7f955ccc3973085e953415920496 upstream.
get_cg_pool_unlocked() handles allocation failures under dmemcg_lock by dropping the lock, preallocating a pool with GFP_KERNEL, and retrying the locked lookup and creation path.
If the fallback allocation fails too, pool remains NULL. Since the loop condition is while (!pool), the function can keep retrying instead of propagating the allocation failure to the caller.
Set pool to ERR_PTR(-ENOMEM) when the fallback allocation fails so the loop exits through the existing common return path. The callers already handle ERR_PTR() from get_cg_pool_unlocked(), so this restores the expected error path.
--- kernel/cgroup/dmem.c | 1 + 1 file changed, 1 insertion(+)
kernel/cgroup/dmem.c +1 -0
@@ -602,6 +602,7 @@ get_cg_pool_unlocked(struct dmemcg_state pool =NULL ;continue ; } + pool =ERR_PTR (-ENOMEM ); } }
Greg Kroah-Hartman
maintainerPATCH 887/957 idpf: fix double free and use-after-free in aux device error paths
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
commit 6c77b9510829a424d1b74409b7db9456e3522871 upstream.
When auxiliary_device_add() fails in idpf_plug_vport_aux_dev() or idpf_plug_core_aux_dev(), the err_aux_dev_add label calls auxiliary_device_uninit() and falls through to err_aux_dev_init. The uninit call will trigger put_device(), which invokes the release callback (idpf_vport_adev_release / idpf_core_adev_release) that frees iadev. The fall-through then reads adev->id from the freed iadev for ida_free() and double-frees iadev with kfree().
Free the IDA slot and clear the back-pointer before uninit, while adev is still valid, then return immediately.
Commit 65637c3a1811 ("idpf: fix UAF in RDMA core aux dev deinitialization") fixed the same use-after-free in the matching unplug path in this file but missed both probe error paths.
--- drivers/net/ethernet/intel/idpf/idpf_idc.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/net/ethernet/intel/idpf/idpf_idc.c +6 -0
@@ -90,7 +90,10 @@ static int idpf_plug_vport_aux_dev(struct iidc_rdma_core_dev_info *cdev_info,return 0 ; err_aux_dev_add: +ida_free (&idpf_idc_ida, adev->id); + vdev_info->adev =NULL ;auxiliary_device_uninit (adev); +return ret; err_aux_dev_init:ida_free (&idpf_idc_ida, adev->id); err_ida_alloc:
@@ -228,7 +231,10 @@ static int idpf_plug_core_aux_dev(struct iidc_rdma_core_dev_info *cdev_info)return 0 ; err_aux_dev_add: +ida_free (&idpf_idc_ida, adev->id); + cdev_info->adev =NULL ;auxiliary_device_uninit (adev); +return ret; err_aux_dev_init:ida_free (&idpf_idc_ida, adev->id); err_ida_alloc:
Signature · 1 line
2.54.0
Greg Kroah-Hartman
maintainerPATCH 888/957 Revert "ACPI: CPPC: Adjust debug messages in amd_set_max_freq_ratio() to warn"
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
commit db5dadb562cabb6da49959b473ed0d9645b6f2da upstream.
Some older systems don't support CPPC in the firmware and this just makes noise for them when booting. Drop back to debug.
This reverts commit 21fb59ab4b9767085f4fe1edbdbe3177fbb9ec97.
--- arch/x86/kernel/acpi/cppc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/x86/kernel/acpi/cppc.c +3 -3
@@ -88,19 +88,19 @@ static void amd_set_max_freq_ratio(void) rc =cppc_get_perf_caps (0 , &perf_caps);if (rc) { -pr_warn ("Could not retrieve perf counters (%d)\n" , rc); +pr_debug ("Could not retrieve perf counters (%d)\n" , rc);return ; } rc =amd_get_boost_ratio_numerator (0 , &numerator);if (rc) { -pr_warn ("Could not retrieve highest performance (%d)\n" , rc); +pr_debug ("Could not retrieve highest performance (%d)\n" , rc);return ; } nominal_perf = perf_caps.nominal_perf;if (!nominal_perf) { -pr_warn ("Could not retrieve nominal performance\n" ); +pr_debug ("Could not retrieve nominal performance\n" );return ; }
Greg Kroah-Hartman
maintainerPATCH 889/957 netfilter: nft_ct: fix missing expect put in obj eval
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Xiasong <[email protected]>
commit 19f94b6fee75b3ef7fbc06f3745b9a771a8a19a4 upstream.
nft_ct_expect_obj_eval() allocates an expectation and may call nf_ct_expect_related(), but never drops its local reference.
Add nf_ct_expect_put(exp) before return to balance allocation.
--- net/netfilter/nft_ct.c | 2 ++ 1 file changed, 2 insertions(+)
net/netfilter/nft_ct.c +2 -0
@@ -1382,6 +1382,8 @@ static void nft_ct_expect_obj_eval(strucif (nf_ct_expect_related (exp,0 ) !=0 ) regs->verdict.code =NF_DROP ; + +nf_ct_expect_put (exp); }static const struct nla_policy nft_ct_expect_policy[NFTA_CT_EXPECT_MAX +1 ] = {
Greg Kroah-Hartman
maintainerPATCH 890/957 net: atlantic: preserve PCI wake-from-D3 on shutdown when WOL enabled
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zoran Ilievski <[email protected]>
commit 2c308cf34284420963607d677d576a2b4124d8bd upstream.
The shutdown handler aq_pci_shutdown() unconditionally calls pci_wake_from_d3(pdev, false), clearing the PCI PME_En bit even when wake-on-LAN has been configured. While aq_nic_shutdown() correctly programs the NIC firmware via aq_nic_set_power() to listen for magic packets, the PCI subsystem will not propagate the resulting PME wake event from D3, so the system never wakes after poweroff.
WOL from suspend (S3) is unaffected because aq_suspend_common() does not touch pci_wake_from_d3() and relies on the PM core's wake configuration via device_may_wakeup().
This affects all atlantic-supported NICs (AQC107/108/111/112/113); users have reported that WOL works if the atlantic driver is never loaded, but breaks once it has run its shutdown path.
Pass the configured WOL state to pci_wake_from_d3() instead of a literal false, so the PCI PME_En bit is preserved when the user has armed WOL via ethtool.
--- drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +1 -1
@@ -371,7 +371,7 @@ static void aq_pci_shutdown(struct pci_dpci_disable_device (pdev);if (system_state ==SYSTEM_POWER_OFF ) { -pci_wake_from_d3 (pdev, false); +pci_wake_from_d3 (pdev, self->aq_hw->aq_nic_cfg->wol);pci_set_power_state (pdev, PCI_D3hot); } }
Greg Kroah-Hartman
maintainerPATCH 891/957 audit: enforce AUDIT_LOCKED for AUDIT_TRIM and AUDIT_MAKE_EQUIV
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergio Correia <[email protected]>
commit f9e1c1324b4d98d591a6f7568fdebf5cf456dfc2 upstream.
AUDIT_ADD_RULE and AUDIT_DEL_RULE correctly check for AUDIT_LOCKED and return -EPERM, but AUDIT_TRIM and AUDIT_MAKE_EQUIV do not. This allows a process with CAP_AUDIT_CONTROL to modify directory tree watches and equivalence mappings even when the audit configuration has been locked, undermining the purpose of the lock.
Add AUDIT_LOCKED checks to both commands.
--- kernel/audit.c | 4 ++++ 1 file changed, 4 insertions(+)
kernel/audit.c +4 -0
@@ -1462,6 +1462,8 @@ static int audit_receive_msg(struct sk_b err =audit_list_rules_send (skb, seq);break ;case AUDIT_TRIM : +if (audit_enabled ==AUDIT_LOCKED ) +return -EPERM ;audit_trim_trees ();audit_log_common_recv_msg (audit_context (), &ab,AUDIT_CONFIG_CHANGE );
@@ -1474,6 +1476,8 @@ static int audit_receive_msg(struct sk_bsize_t msglen = data_len;char *old, *new; +if (audit_enabled ==AUDIT_LOCKED ) +return -EPERM ; err = -EINVAL ;if (msglen <2 *sizeof (u32))break ;
Greg Kroah-Hartman
maintainerPATCH 892/957 KVM: Reject wrapped offset in kvm_reset_dirty_gfn()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aaron Sacks <[email protected]>
commit 577a8d3bae0531f0e5ccfac919cd8192f920a804 upstream.
kvm_reset_dirty_gfn() guards the gfn range with
if (!memslot || (offset + __fls(mask)) >= memslot->npages) return;
but offset is u64 and the addition is unchecked. The check can be silently bypassed by a u64 wrap.
The dirty ring backing those entries is MAP_SHARED at KVM_DIRTY_LOG_PAGE_OFFSET of the vcpu fd, so the VMM can rewrite the slot and offset fields of any entry between when the kernel pushes them and when KVM_RESET_DIRTY_RINGS consumes them. On reset, kvm_dirty_ring_reset() re-reads the values via READ_ONCE() and feeds them straight back into this check; only the flags handshake is treated as the handover, the slot/offset payload is taken on trust.
Crafting two entries
entry[i].offset = 0xffffffffffffffc1 entry[i+1].offset = 0
makes the coalescing loop in kvm_dirty_ring_reset() compute
delta = (s64)(0 - 0xffffffffffffffc1) = 63
which falls in [0, BITS_PER_LONG), so it folds entry[i+1] into the existing mask by setting bit 63. The trailing kvm_reset_dirty_gfn() call then sees offset = 0xffffffffffffffc1 and __fls(mask) = 63; the sum is 0 in u64 and the bounds check passes.
That offset propagates into kvm_arch_mmu_enable_log_dirty_pt_masked() unchanged. On the legacy MMU path -- kvm_memslots_have_rmaps() == true, i.e. shadow paging, any VM that has allocated shadow roots, or a write-tracked slot -- it reaches gfn_to_rmap(), which indexes slot->arch.rmap[0][] with a near-U64_MAX gfn. That is an out-of-bounds load of a kvm_rmap_head, followed by a conditional clear of PT_WRITABLE_MASK in whatever the loaded pointer points at. The path is reachable from any process holding /dev/kvm.
Range-check offset on its own first, so the addition cannot wrap. memslot->npages is bounded well below U64_MAX, so once offset < npages holds, offset + __fls(mask) (with __fls(mask) < BITS_PER_LONG) stays in range.
--- virt/kvm/dirty_ring.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
virt/kvm/dirty_ring.c +2 -1
@@ -63,7 +63,8 @@ static void kvm_reset_dirty_gfn(struct k memslot =id_to_memslot (__kvm_memslots (kvm, as_id), id); -if (!memslot || (offset +__fls (mask)) >= memslot->npages) +if (!memslot || offset >= memslot->npages || + offset +__fls (mask) >= memslot->npages)return ;KVM_MMU_LOCK (kvm);
Greg Kroah-Hartman
maintainerPATCH 893/957 KVM: s390: pci: fix GAIT table indexing due to double-scaling pointer arithmetic
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <[email protected]>
commit 16d990a15491cf76cd6eef0846e1b4100e63261a upstream.
kvm_s390_pci_aif_enable(), kvm_s390_pci_aif_disable(), and aen_host_forward() index the GAIT by manually multiplying the index with sizeof(struct zpci_gaite).
Since aift->gait is already a struct zpci_gaite pointer, this double-scales the offset, accessing element aisb*16 instead of aisb.
This causes out-of-bounds accesses when aisb >= 32 (with ZPCI_NR_DEVICES=512)
Fix by removing the erroneous sizeof multiplication.
--- arch/s390/kvm/interrupt.c | 3 +-- arch/s390/kvm/pci.c | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-)
arch/s390/kvm/interrupt.c +1 -2
@@ -3334,8 +3334,7 @@ static void aen_host_forward(unsigned lostruct zpci_gaite *gaite;struct kvm *kvm; - gaite = (struct zpci_gaite *)aift->gait + - (si *sizeof (struct zpci_gaite )); + gaite = aift->gait + si;if (gaite->count ==0 )return ;if (gaite->aisb !=0 )
arch/s390/kvm/pci.c +2 -4
@@ -291,8 +291,7 @@ static int kvm_s390_pci_aif_enable(struc phys_to_virt(fib->fmt0.aibv));spin_lock_irq (&aift->gait_lock); - gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb * -sizeof (struct zpci_gaite )); + gaite = aift->gait + zdev->aisb;/* If assist not requested, host will get all alerts */ if (assist)
@@ -358,8 +357,7 @@ static int kvm_s390_pci_aif_disable(struif (zdev->kzdev->fib.fmt0.aibv ==0 ) goto out;spin_lock_irq (&aift->gait_lock); - gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb * -sizeof (struct zpci_gaite )); + gaite = aift->gait + zdev->aisb; isc = gaite->gisc; gaite->count--;if (gaite->count ==0 ) {
Greg Kroah-Hartman
maintainerPATCH 894/957 KVM: x86: Fix Xen hypercall tracepoint argument assignment
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qiang Ma <[email protected]>
commit 2b72f1674e427c56e3772c5ccf785fdda2138820 upstream.
TRACE_EVENT(kvm_xen_hypercall) stores a5 in __entry->a4 instead of __entry->a5.
That overwrites the recorded a4 argument and leaves a5 unset in the trace entry. Fix the typo so both arguments are captured correctly.
--- arch/x86/kvm/trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/trace.h +1 -1
@@ -154,7 +154,7 @@ TRACE_EVENT(kvm_xen_hypercall, __entry->a2 = a2; __entry->a3 = a3; __entry->a4 = a4; - __entry->a4 = a5; + __entry->a5 = a5; ), TP_printk("cpl %d nr 0x%lx a0 0x%lx a1 0x%lx a2 0x%lx a3 0x%lx a4 0x%lx a5 %lx",
Greg Kroah-Hartman
maintainerPATCH 895/957 HID: pass the buffer size to hid_report_raw_event
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Tissoires <[email protected]>
[ Upstream commit 2c85c61d1332e1e16f020d76951baf167dcb6f7a ]
commit 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing bogus memset()") enforced the provided data to be at least the size of the declared buffer in the report descriptor to prevent a buffer overflow. However, we can try to be smarter by providing both the buffer size and the data size, meaning that hid_report_raw_event() can make better decision whether we should plaining reject the buffer (buffer overflow attempt) or if we can safely memset it to 0 and pass it to the rest of the stack.
Stable-dep-of: 206342541fc8 ("HID: core: introduce hid_safe_input_report()")
--- drivers/hid/bpf/hid_bpf_dispatch.c | 6 +++-- drivers/hid/hid-core.c | 42 ++++++++++++++++++++---------- drivers/hid/hid-gfrm.c | 4 +-- drivers/hid/hid-logitech-hidpp.c | 2 +- drivers/hid/hid-multitouch.c | 2 +- drivers/hid/hid-primax.c | 2 +- drivers/hid/hid-vivaldi-common.c | 2 +- drivers/hid/wacom_sys.c | 6 ++--- drivers/staging/greybus/hid.c | 2 +- include/linux/hid.h | 4 +-- include/linux/hid_bpf.h | 14 ++++++---- 11 files changed, 53 insertions(+), 33 deletions(-)
drivers/hid/bpf/hid_bpf_dispatch.c +4 -2
@@ -24,7 +24,8 @@ EXPORT_SYMBOL(hid_ops);u8 *dispatch_hid_bpf_device_event (struct hid_device *hdev,enum hid_report_type type,u8 *data, -u32 *size,int interrupt,u64 source,bool from_bpf) +size_t *buf_size,u32 *size,int interrupt,u64 source, +bool from_bpf) {struct hid_bpf_ctx_kern ctx_kern = { .ctx = {
@@ -74,6 +75,7 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type *size = ret; } + *buf_size = ctx_kern.ctx.allocated_size;return ctx_kern.data; }EXPORT_SYMBOL_GPL (dispatch_hid_bpf_device_event);
@@ -508,7 +510,7 @@ __hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *bif (ret)return ret; -return hid_ops->hid_input_report (ctx->hid, type, buf, size,0 , (u64 )(long )ctx, true, +return hid_ops->hid_input_report (ctx->hid, type, buf, size, size,0 , (u64 )(long )ctx, true, lock_already_taken); }
drivers/hid/hid-core.c +28 -14
106 lines not on this page · raw message
drivers/hid/hid-gfrm.c +2 -2
@@ -66,7 +66,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,switch (data[1 ]) {case GFRM100_SEARCH_KEY_DOWN : ret =hid_report_raw_event (hdev,HID_INPUT_REPORT , search_key_dn, -sizeof (search_key_dn),1 ); +sizeof (search_key_dn),sizeof (search_key_dn),1 );break ;case GFRM100_SEARCH_KEY_AUDIO_DATA :
@@ -74,7 +74,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,case GFRM100_SEARCH_KEY_UP : ret =hid_report_raw_event (hdev,HID_INPUT_REPORT , search_key_up, -sizeof (search_key_up),1 ); +sizeof (search_key_up),sizeof (search_key_up),1 );break ;default :
drivers/hid/hid-logitech-hidpp.c +1 -1
@@ -3664,7 +3664,7 @@ static int hidpp10_consumer_keys_raw_event(struct hidpp_device *hidpp,memcpy (&consumer_report[1 ], &data[3 ],4 );/* We are called from atomic context */ hid_report_raw_event (hidpp->hid_dev,HID_INPUT_REPORT , - consumer_report,5 ,1 ); + consumer_report,sizeof (consumer_report),5 ,1 );return 1 ; }
drivers/hid/hid-multitouch.c +1 -1
@@ -531,7 +531,7 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report) } ret =hid_report_raw_event (hdev,HID_FEATURE_REPORT , buf, - size,0 ); + size, size,0 );if (ret)dev_warn (&hdev->dev,"failed to report feature\n" ); }
drivers/hid/hid-primax.c +1 -1
@@ -44,7 +44,7 @@ static int px_raw_event(struct hid_device *hid, struct hid_report *report, data[0 ] |= (1 << (data[idx] -0xE0 )); data[idx] =0 ; } -hid_report_raw_event (hid,HID_INPUT_REPORT , data, size,0 ); +hid_report_raw_event (hid,HID_INPUT_REPORT , data, size, size,0 );return 1 ;default :/* unknown report */
drivers/hid/hid-vivaldi-common.c +1 -1
@@ -85,7 +85,7 @@ void vivaldi_feature_mapping(struct hid_device *hdev, } ret =hid_report_raw_event (hdev,HID_FEATURE_REPORT , report_data, - report_len,0 ); + report_len, report_len,0 );if (ret) {dev_warn (&hdev->dev,"failed to report feature %d\n" , field->report->id);
drivers/hid/wacom_sys.c +3 -3
@@ -90,7 +90,7 @@ static void wacom_wac_queue_flush(struct hid_device *hdev,kfree (buf);continue ; } - err =hid_report_raw_event (hdev,HID_INPUT_REPORT , buf, size, false); + err =hid_report_raw_event (hdev,HID_INPUT_REPORT , buf, size, size, false);if (err) {hid_warn (hdev,"%s: unable to flush event due to error %d\n" , __func__, err);
@@ -334,7 +334,7 @@ static void wacom_feature_mapping(struct hid_device *hdev, data, n, WAC_CMD_RETRIES);if (ret == n && features->type ==HID_GENERIC ) { ret =hid_report_raw_event (hdev, -HID_FEATURE_REPORT , data, n,0 ); +HID_FEATURE_REPORT , data, n, n,0 ); }else if (ret ==2 && features->type !=HID_GENERIC ) { features->touch_max = data[1 ]; }else {
@@ -395,7 +395,7 @@ static void wacom_feature_mapping(struct hid_device *hdev, data, n, WAC_CMD_RETRIES);if (ret == n) { ret =hid_report_raw_event (hdev,HID_FEATURE_REPORT , - data, n,0 ); + data, n, n,0 ); }else {hid_warn (hdev,"%s: could not retrieve sensor offsets\n" , __func__);
drivers/staging/greybus/hid.c +1 -1
@@ -201,7 +201,7 @@ static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report)* we just need to setup the input fields, so using * hid_report_raw_event is safe. */ -hid_report_raw_event (ghid->hid, report->type, ghid->inbuf, size,1 ); +hid_report_raw_event (ghid->hid, report->type, ghid->inbuf, ghid->bufsize, size,1 ); }static void gb_hid_init_reports (struct gb_hid *ghid)
include/linux/hid.h +2 -2
@@ -1258,8 +1258,8 @@ static inline u32 hid_report_len(struct hid_report *report)return DIV_ROUND_UP (report->size,8 ) + (report->id >0 ); } -int hid_report_raw_event (struct hid_device *hid,enum hid_report_type type,u8 *data,u32 size, -int interrupt); +int hid_report_raw_event (struct hid_device *hid,enum hid_report_type type,u8 *data, +size_t bufsize,u32 size,int interrupt);/* HID quirks API */ unsigned long hid_lookup_quirk (const struct hid_device *hdev);
include/linux/hid_bpf.h +9 -5
@@ -72,8 +72,8 @@ struct hid_ops {int (*hid_hw_output_report)(struct hid_device *hdev,__u8 *buf,size_t len,u64 source,bool from_bpf);int (*hid_input_report)(struct hid_device *hid,enum hid_report_type type, -u8 *data,u32 size,int interrupt,u64 source,bool from_bpf, -bool lock_already_taken); +u8 *data,size_t bufsize,u32 size,int interrupt,u64 source, +bool from_bpf,bool lock_already_taken);struct module *owner;const struct bus_type *bus_type; };
@@ -200,7 +200,8 @@ struct hid_bpf {#ifdef CONFIG_HID_BPF u8 *dispatch_hid_bpf_device_event (struct hid_device *hid,enum hid_report_type type,u8 *data, -u32 *size,int interrupt,u64 source,bool from_bpf); +size_t *buf_size,u32 *size,int interrupt,u64 source, +bool from_bpf); int dispatch_hid_bpf_raw_requests(struct hid_device *hdev, unsigned char reportnum, __u8 *buf, u32 size, enum hid_report_type rtype,
@@ -215,8 +216,11 @@ int hid_bpf_device_init(struct hid_device *hid);const u8 *call_hid_bpf_rdesc_fixup (struct hid_device *hdev,const u8 *rdesc,unsigned int *size);#else /* CONFIG_HID_BPF */ static inline u8 *dispatch_hid_bpf_device_event (struct hid_device *hid,enum hid_report_type type, -u8 *data,u32 *size,int interrupt, -u64 source,bool from_bpf) {return data; } +u8 *data,size_t *buf_size,u32 *size, +int interrupt,u64 source,bool from_bpf) +{ +return data; +} static inline int dispatch_hid_bpf_raw_requests(struct hid_device *hdev, unsigned char reportnum, u8 *buf, u32 size, enum hid_report_type rtype,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 896/957 HID: core: introduce hid_safe_input_report()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Tissoires <[email protected]>
[ Upstream commit 206342541fc887ae919774a43942dc883161fece ]
hid_input_report() is used in too many places to have a commit that doesn't cross subsystem borders. Instead of changing the API, introduce a new one when things matters in the transport layers:
- usbhid
- i2chid
This effectively revert to the old behavior for those two transport layers.
--- drivers/hid/hid-core.c | 25 +++++++++++++++++++++++++ drivers/hid/i2c-hid/i2c-hid-core.c | 7 ++++--- drivers/hid/usbhid/hid-core.c | 11 ++++++----- include/linux/hid.h | 2 ++ 4 files changed, 37 insertions(+), 8 deletions(-)
drivers/hid/hid-core.c +25 -0
@@ -2177,6 +2177,7 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,* @interrupt: distinguish between interrupt and control transfers * * This is data entry for lower layers. +* Legacy, please use hid_safe_input_report() instead. */ int hid_input_report (struct hid_device *hid,enum hid_report_type type,u8 *data,u32 size,int interrupt)
@@ -2187,6 +2188,30 @@ int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data }EXPORT_SYMBOL_GPL (hid_input_report); +/** +* hid_safe_input_report - report data from lower layer (usb, bt...) +* +* @hid: hid device +* @type: HID report type (HID_*_REPORT) +* @data: report contents +* @bufsize: allocated size of the data buffer +* @size: useful size of data parameter +* @interrupt: distinguish between interrupt and control transfers +* +* This is data entry for lower layers. +* Please use this function instead of the non safe version because we provide +* here the size of the buffer, allowing hid-core to make smarter decisions +* regarding the incoming buffer. +*/ +int hid_safe_input_report (struct hid_device *hid,enum hid_report_type type,u8 *data, +size_t bufsize,u32 size,int interrupt) +{ +return __hid_input_report (hid, type, data, bufsize, size, interrupt,0 , + false,/* from_bpf */ + false/* lock_already_taken */ ); +} +EXPORT_SYMBOL_GPL (hid_safe_input_report); +bool hid_match_one_id (const struct hid_device *hdev,const struct hid_device_id *id) {
drivers/hid/i2c-hid/i2c-hid-core.c +4 -3
@@ -574,9 +574,10 @@ static void i2c_hid_get_input(struct i2c_hid *ihid)if (ihid->hid->group !=HID_GROUP_RMI )pm_wakeup_event (&ihid->client->dev,0 ); -hid_input_report (ihid->hid,HID_INPUT_REPORT , - ihid->inbuf +sizeof (__le16), - ret_size -sizeof (__le16),1 ); +hid_safe_input_report (ihid->hid,HID_INPUT_REPORT , + ihid->inbuf +sizeof (__le16), + ihid->bufsize -sizeof (__le16), + ret_size -sizeof (__le16),1 ); }return ;
drivers/hid/usbhid/hid-core.c +6 -5
@@ -283,9 +283,9 @@ static void hid_irq_in(struct urb *urb)break ;usbhid_mark_busy (usbhid);if (!test_bit (HID_RESUME_RUNNING , &usbhid->iofl)) { -hid_input_report (urb->context,HID_INPUT_REPORT , - urb->transfer_buffer, - urb->actual_length,1 ); +hid_safe_input_report (urb->context,HID_INPUT_REPORT , + urb->transfer_buffer, urb->transfer_buffer_length, + urb->actual_length,1 );/* * autosuspend refused while keys are pressed * because most keyboards don't wake up when
@@ -482,9 +482,10 @@ static void hid_ctrl(struct urb *urb)switch (status) {case 0 :/* success */ if (usbhid->ctrl[usbhid->ctrltail].dir ==USB_DIR_IN ) -hid_input_report (urb->context, +hid_safe_input_report (urb->context, usbhid->ctrl[usbhid->ctrltail].report->type, - urb->transfer_buffer, urb->actual_length,0 ); + urb->transfer_buffer, urb->transfer_buffer_length, + urb->actual_length,0 );break ;case -ESHUTDOWN :/* unplug */ unplug =1 ;
include/linux/hid.h +2 -0
@@ -990,6 +990,8 @@ struct hid_field *hid_find_field(struct hid_device *hdev, unsigned int report_tyint hid_set_field (struct hid_field *,unsigned ,__s32 );int hid_input_report (struct hid_device *hid,enum hid_report_type type,u8 *data,u32 size,int interrupt); +int hid_safe_input_report (struct hid_device *hid,enum hid_report_type type,u8 *data, +size_t bufsize,u32 size,int interrupt);struct hid_field *hidinput_get_led_field (struct hid_device *hid);unsigned int hidinput_count_leds (struct hid_device *hid);__s32 hidinput_calc_abs_res (const struct hid_field *field,__u16 code);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 897/957 HID: core: Fix size_t specifier in hid_report_raw_event()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor <[email protected]>
[ Upstream commit 4d3a2a466b8d68d852a1f3bbf11204b718428dc4 ]
When building for 32-bit platforms, for which 'size_t' is 'unsigned int', there are warnings around using the incorrect format specifier to print bsize in hid_report_raw_event():
drivers/hid/hid-core.c:2054:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat]
2053 | hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
| ~~~
| %zu
2054 | report->id, csize, bsize);
| ^~~~~
drivers/hid/hid-core.c:2076:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat]
2075 | hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
| ~~~
| %zu
2076 | report->id, rsize, bsize);
| ^~~~~Use the proper 'size_t' format specifier, '%zu', to clear up the warnings.
--- drivers/hid/hid-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/hid/hid-core.c +2 -2
@@ -2046,7 +2046,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *return 0 ;if (unlikely (bsize < csize)) { -hid_warn_ratelimited (hid,"Event data for report %d is incorrect (%d vs %ld)\n" , +hid_warn_ratelimited (hid,"Event data for report %d is incorrect (%d vs %zu)\n" , report->id, csize, bsize);return -EINVAL ; }
@@ -2068,7 +2068,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 * rsize = max_buffer_size;if (bsize < rsize) { -hid_warn_ratelimited (hid,"Event data for report %d was too short (%d vs %ld)\n" , +hid_warn_ratelimited (hid,"Event data for report %d was too short (%d vs %zu)\n" , report->id, rsize, bsize);return -EINVAL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 898/957 fuse: avoid 0x10 fault in fuse_readahead when max_pages == 0
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vlad Poenaru <[email protected]>
[ Upstream commit 4ea907108a5c ("fuse: use iomap for readahead") ]
The upstream fix is the iomap conversion in commit 4ea907108a5c ("fuse: use iomap for readahead"), which rewrote fuse_readahead() entirely and removed the buggy loop along with it. That refactor is too invasive to backport to the pre-iomap readahead path still used by 6.18.y (and earlier stable branches), so this is a minimal, equivalent fix to the same bug on those branches.
When fc->max_read is smaller than PAGE_SIZE (common on aarch64 with 64K base pages if the FUSE server advertises a small max_read in INIT), max_pages = min(fc->max_pages, fc->max_read / PAGE_SIZE) is 0, so cur_pages is 0 on every outer iteration.
fuse_io_alloc(NULL, 0) then calls fuse_folios_alloc(0, ...), which calls kzalloc(0, ...) and gets back ZERO_SIZE_PTR == (void *)16. The "if (!ia->ap.folios)" guard in fuse_io_alloc does not catch ZERO_SIZE_PTR, so fuse_io_alloc happily returns an ia whose ap.folios is 0x10.
The inner "while (pages < cur_pages)" loop runs zero times, then fuse_send_readpages(ia, ...) dereferences ap->folios[0] in folio_pos(), faulting at virtual address 0x10:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010 fuse_readahead+0x14c/0x490 read_pages+0x80/0x318 page_cache_ra_unbounded+0x1c0/0x2b0 page_cache_ra_order+0xb8/0x368 page_cache_sync_ra+0x210/0x320 filemap_get_pages+0x290/0xdb0 generic_file_read_iter+0xd0/0x540 fuse_file_read_iter+0x8c/0x158 __arm64_sys_read+0x1a0/0x488
addr2line on the aarch64 vmlinux maps fuse_readahead+0x14c to fs/fuse/file.c:897 inlined into :999, i.e. "folio_pos(ap->folios[0])" inside fuse_send_readpages. The faulting instruction "ldr x8, [x8]" loads ap->folios[0]; ap->folios was previously loaded as 0x10 (ZERO_SIZE_PTR).
Without this fix the function would also spin forever, since "nr_pages -= pages" makes no progress when pages stays 0; in practice the NULL deref masks the spin.
Bail out of the outer loop if cur_pages is 0 -- there is no work we can issue via FUSE in this iteration, and remaining folios will be handled by read_pages() falling back to ->read_folio.
--- fs/fuse/file.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/fuse/file.c +10 -0
@@ -974,6 +974,16 @@ static void fuse_readahead(struct readahead_control *rac)unsigned cur_pages =min (max_pages, nr_pages);unsigned int pages =0 ; +/* +* If max_pages == 0 (e.g. fc->max_read < PAGE_SIZE on a +* 64K-page kernel), cur_pages is 0 and we cannot make +* progress. Bailing here avoids passing 0 to fuse_io_alloc, +* which would return an ia whose ap.folios is ZERO_SIZE_PTR +* (0x10) -- later dereferenced by fuse_send_readpages. +*/ +if (!cur_pages) +break ; +if (fc->num_background >= fc->congestion_threshold && rac->ra->async_size >=readahead_count (rac))/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 899/957 ata: libata-scsi: fix requeue of deferred ATA PASS-THROUGH commands
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Igor Pylypiv <[email protected]>
[ Upstream commit 8ebf408e7d463eee02c348a3c8277b95587b710d ]
Commit 0ea84089dbf6 ("ata: libata-scsi: avoid Non-NCQ command starvation") introduced ata_scsi_requeue_deferred_qc() to handle commands deferred during resets or NCQ failures. This deferral logic completed commands with DID_SOFT_ERROR to trigger a retry in the SCSI mid-layer.
However, DID_SOFT_ERROR is subject to scsi_cmd_retry_allowed() checks. ATA PASS-THROUGH commands sent via SG_IO ioctl have scmd->allowed set to zero. This causes the mid-layer to fail the command immediately instead of retrying, even though the command was never actually issued to the hardware.
Switch to DID_REQUEUE to ensure these commands are inserted back into the request queue regardless of retry limits.
--- drivers/ata/libata-scsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/ata/libata-scsi.c +2 -2
@@ -1691,7 +1691,7 @@ void ata_scsi_requeue_deferred_qc(struct ata_port *ap)/* * If we have a deferred qc when a reset occurs or NCQ commands fail, * do not try to be smart about what to do with this deferred command -* and simply retry it by completing it with DID_SOFT_ERROR. +* and simply requeue it by completing it with DID_REQUEUE. */ if (!qc)return ;
@@ -1700,7 +1700,7 @@ void ata_scsi_requeue_deferred_qc(struct ata_port *ap) ap->deferred_qc =NULL ;cancel_work (&ap->deferred_qc_work);ata_qc_free (qc); - scmd->result = (DID_SOFT_ERROR <<16 ); + scmd->result = (DID_REQUEUE <<16 );scsi_done (scmd); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 900/957 media: staging: imx: configure src_mux in csi_start
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Tretter <[email protected]>
[ Upstream commit ebeec2b000a90cd8aae86d1931ff5ef23af8284e ]
After media_pipeline_start() was called, the media graph is assumed to be validated. It won't be validated again if a second stream starts.
The imx-media-csi driver, however, changes hardware configuration in the link_validate() callback. This can result in started streams with misconfigured hardware.
In the concrete example, the ipu2_csi1 is driven by a parallel video input. After the media pipeline has been started with this configuration, a second stream is configured to use ipu1_csi0 with MIPI-CSI input from imx6-mipi-csi2. This may require the reconfiguration of ipu1_csi0 with ipu_set_csi_src_mux(). Since the media pipeline is already running, link_validate won't be called, and the ipu1_csi0 won't be reconfigured. The resulting video is broken, because the ipu1_csi0 is misconfigured, but no error is reported.
Move ipu_set_csi_src_mux from csi_link_validate to csi_start to ensure that input to ipu1_csi0 is configured correctly when starting the stream. This is a local reconfiguration in ipu1_csi0 and is possible while the media pipeline is running.
Since csi_start() is called with priv->lock already locked, csi_set_src() must not lock priv->lock again. Thus, the mutex_lock() is dropped.
--- drivers/staging/media/imx/imx-media-csi.c | 44 ++++++++++++----------- 1 file changed, 24 insertions(+), 20 deletions(-)
drivers/staging/media/imx/imx-media-csi.c +24 -20
@@ -744,6 +744,28 @@ static int csi_setup(struct csi_priv *priv,return 0 ; } +static void csi_set_src (struct csi_priv *priv, +struct v4l2_mbus_config *mbus_cfg) +{ +bool is_csi2; + + is_csi2 = !is_parallel_bus (mbus_cfg); +if (is_csi2) { +/* +* NOTE! It seems the virtual channels from the mipi csi-2 +* receiver are used only for routing by the video mux's, +* or for hard-wired routing to the CSI's. Once the stream +* enters the CSI's however, they are treated internally +* in the IPU as virtual channel 0. +*/ +ipu_csi_set_mipi_datatype (priv->csi,0 , + &priv->format_mbus[CSI_SINK_PAD ]); + } + +/* select either parallel or MIPI-CSI2 as input to CSI */ +ipu_set_csi_src_mux (priv->ipu, priv->csi_id, is_csi2); +} +static int csi_start (struct csi_priv *priv) {struct v4l2_mbus_config mbus_cfg = { .type =0 };
@@ -760,6 +782,8 @@ static int csi_start(struct csi_priv *priv) input_fi = &priv->frame_interval[CSI_SINK_PAD ]; output_fi = &priv->frame_interval[priv->active_output_pad]; +csi_set_src (priv, &mbus_cfg); +/* start upstream */ ret =v4l2_subdev_call (priv->src_sd, video, s_stream,1 ); ret = (ret && ret != -ENOIOCTLCMD ) ? ret :0 ;
@@ -1130,7 +1154,6 @@ static int csi_link_validate(struct v4l2_subdev *sd, {struct csi_priv *priv =v4l2_get_subdevdata (sd);struct v4l2_mbus_config mbus_cfg = { .type =0 }; -bool is_csi2;int ret; ret = v4l2_subdev_link_validate_default(sd, link,
@@ -1145,25 +1168,6 @@ static int csi_link_validate(struct v4l2_subdev *sd,return ret; } -mutex_lock (&priv->lock); - - is_csi2 = !is_parallel_bus (&mbus_cfg); -if (is_csi2) { -/* -* NOTE! It seems the virtual channels from the mipi csi-2 -* receiver are used only for routing by the video mux's, -* or for hard-wired routing to the CSI's. Once the stream -* enters the CSI's however, they are treated internally -* in the IPU as virtual channel 0. -*/ -ipu_csi_set_mipi_datatype (priv->csi,0 , - &priv->format_mbus[CSI_SINK_PAD ]); - } - -/* select either parallel or MIPI-CSI2 as input to CSI */ -ipu_set_csi_src_mux (priv->ipu, priv->csi_id, is_csi2); - -mutex_unlock (&priv->lock);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 901/957 Bluetooth: btmtk: accept too short WMT FUNC_CTRL events
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
commit e3ac0d9f1a205f33a43fba3b79ef74d2f604c78b upstream.
MT7925 (USB ID 0e8d:e025) on fw version 20260106153314 sends WMT FUNC_CTRL events that are missing the status field.
Prior to commit 006b9943b982 ("Bluetooth: btmtk: validate WMT event SKB length before struct access") the status was read from out-of-bounds of SKB data, which usually would result to success with BTMTK_WMT_ON_UNDONE, although I don't know the intent here. The bounds check added in that commit returns with error instead, producing "Bluetooth: hci0: Failed to send wmt func ctrl (-22)" and makes the device unusable.
Fix the regression by interpreting too short packet as status BTMTK_WMT_ON_UNDONE, which makes the device work normally again.
--- drivers/bluetooth/btmtk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/bluetooth/btmtk.c +2 -2
@@ -678,8 +678,8 @@ static int btmtk_usb_hci_wmt_sync(structcase BTMTK_WMT_FUNC_CTRL :if (!skb_pull_data (data->evt_skb,sizeof (wmt_evt_funcc->status))) { - err = -EINVAL ; - goto err_free_skb; + status =BTMTK_WMT_ON_UNDONE ; +break ; } wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
Greg Kroah-Hartman
maintainerPATCH 902/957 nvme-apple: Reset q->sq_tail during queue init
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nick Chan <[email protected]>
commit a6ab75639e23169a741b0b2e12191fd8acb32c73 upstream.
Fixes a "duplicate tag error for tag 0" firmware crash during controller reset while setting up a queue on Apple A11 / T8015 caused by stale entries in the submission queue due to an invalid sq_tail offset after reset.
--- drivers/nvme/host/apple.c | 1 + 1 file changed, 1 insertion(+)
drivers/nvme/host/apple.c +1 -0
@@ -1009,6 +1009,7 @@ static void apple_nvme_init_queue(structunsigned int depth =apple_nvme_queue_depth (q);struct apple_nvme *anv =queue_to_apple_nvme (q); + q->sq_tail =0 ; q->cq_head =0 ; q->cq_phase =1 ;if (anv->hw->has_lsq_nvmmu)
Greg Kroah-Hartman
maintainerPATCH 903/957 smb/client: fix possible infinite loop and oob read in symlink_data()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ye Bin <[email protected]>
commit 7d9a7f1f96cd617ee9e75bb22217c709038e26b8 upstream.
On 32-bit architectures, the infinite loop is as follows:
len = p->ErrorDataLength == 0xfffffff8
u8 *next = p->ErrorContextData + len
next == p
On 32-bit architectures, the out-of-bounds read is as follows:
len = p->ErrorDataLength == 0xfffffff0
u8 *next = p->ErrorContextData + len
next == (u8 *)p - 8
--- fs/smb/client/smb2file.c | 3 +++ 1 file changed, 3 insertions(+)
fs/smb/client/smb2file.c +3 -0
@@ -49,6 +49,9 @@ static struct smb2_symlink_err_rsp *syml __func__, le32_to_cpu(p->ErrorId)); len =ALIGN (le32_to_cpu (p->ErrorDataLength),8 ); +if (len > end - ((u8 *)p +sizeof (*p))) +return ERR_PTR (-EINVAL ); + p = (struct smb2_error_context_rsp *)(p->ErrorContextData + len); } } else if (le32_to_cpu(err->ByteCount) >= sizeof(*sym) &&
Greg Kroah-Hartman
maintainerPATCH 904/957 drm/loongson: Use managed KMS polling
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <[email protected]>
commit 0a9c56dd387605d17dabeedd9fdd2c4c1d0bab7b upstream.
lsdc_pci_probe() initializes KMS polling before setting up vblank support, requesting the IRQ and registering the DRM device. If any of those later steps fails, probe returns without finalizing polling. The driver also never finalizes polling on regular removal.
Use drmm_kms_helper_poll_init() so polling is tied to the DRM device lifetime and automatically finalized on probe failure and device removal.
This issue was identified during our ongoing static-analysis research while reviewing kernel code.
--- drivers/gpu/drm/loongson/lsdc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/loongson/lsdc_drv.c +1 -1
@@ -291,7 +291,7 @@ static int lsdc_pci_probe(struct pci_devvga_client_register (pdev, lsdc_vga_set_decode); -drm_kms_helper_poll_init (ddev); +drmm_kms_helper_poll_init (ddev);if (loongson_vblank) { ret =drm_vblank_init (ddev, descp->num_of_crtc);
Greg Kroah-Hartman
maintainerPATCH 905/957 drm: Replace old pointer to new idr
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis <[email protected]>
commit dc366607c41c45fd0ae6f3db090f31dd611b644a upstream.
Commit 5e28b7b94408 introduced a logical error by failing to replace the newly generated IDR pointer to old id's pointer at the correct location within the "change handle" logic; this resulted in the issue reported by syzbot [1].
Specifically, the new IDR object pointer is intended to replace the original id's pointer during the normal execution flow.
Additionally, an unnecessary conditional check for the ret exit path has been removed.
[1]
!RB_EMPTY_ROOT(&prime_fpriv->dmabufs)
WARNING: drivers/gpu/drm/drm_prime.c:224 at drm_prime_destroy_file_private+0x48/0x60 drivers/gpu/drm/drm_prime.c:224, CPU#0: syz.0.17/5833 Call Trace: drm_file_free.part.0+0x7e6/0xcc0 drivers/gpu/drm/drm_file.c:269 drm_file_free drivers/gpu/drm/drm_file.c:237 [inline] drm_close_helper.isra.0+0x186/0x200 drivers/gpu/drm/drm_file.c:290 drm_release+0x1ab/0x360 drivers/gpu/drm/drm_file.c:438
--- drivers/gpu/drm/drm_gem.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/gpu/drm/drm_gem.c +2 -5
@@ -1017,17 +1017,12 @@ int drm_gem_change_handle_ioctl(struct dspin_unlock (&file_priv->table_lock); -if (ret <0 ) - goto out_unlock; -if (obj->dma_buf) { ret =drm_prime_add_buf_handle (&file_priv->prime, obj->dma_buf, handle);if (ret <0 ) {spin_lock (&file_priv->table_lock);idr_remove (&file_priv->object_idr, handle); - idrobj =idr_replace (&file_priv->object_idr, obj, handle); -WARN_ON (idrobj !=NULL );spin_unlock (&file_priv->table_lock); goto out_unlock; }
@@ -1039,7 +1034,9 @@ int drm_gem_change_handle_ioctl(struct dspin_lock (&file_priv->table_lock);idr_remove (&file_priv->object_idr, args->handle); + idrobj =idr_replace (&file_priv->object_idr, obj, handle);spin_unlock (&file_priv->table_lock); +WARN_ON (idrobj !=NULL ); out_unlock:mutex_unlock (&file_priv->prime.lock);
Greg Kroah-Hartman
maintainerPATCH 906/957 drm/i915/dp: Fix VSC dynamic range signaling for RGB formats
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chaitanya Kumar Borah <[email protected]>
commit 1ae15b6c7965d137eef21f2cc7d367b29cb88369 upstream.
For RGB, set dynamic_range to CTA or VESA based on crtc_state->limited_color_range so sinks apply correct quantization. YCbCr remains limited (CTA) range. (DP v1.4, Table 5-1)
v2:
- Added Reported-by and Tested-by tags
v3:
- Add back YCbCr comment(Suraj)
--- drivers/gpu/drm/i915/display/intel_dp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/display/intel_dp.c +7 -2
@@ -2869,8 +2869,13 @@ static void intel_dp_compute_vsc_colorimdrm_WARN_ON (display->drm, vsc->bpc ==6 && vsc->pixelformat !=DP_PIXELFORMAT_RGB ); -/* all YCbCr are always limited range */ - vsc->dynamic_range =DP_DYNAMIC_RANGE_CTA ; +/* All YCbCr formats are always limited range. */ +if (vsc->pixelformat ==DP_PIXELFORMAT_RGB ) + vsc->dynamic_range = crtc_state->limited_color_range ? +DP_DYNAMIC_RANGE_CTA :DP_DYNAMIC_RANGE_VESA ; +else + vsc->dynamic_range =DP_DYNAMIC_RANGE_CTA ; + vsc->content_type =DP_CONTENT_TYPE_NOT_DEFINED ; }
Greg Kroah-Hartman
maintainerPATCH 907/957 platform/x86: intel: Move debugfs register before creating devices
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivas Pandruvada <[email protected]>
commit ad3bff944c0f4f2e913298a9664391af32f87491 upstream.
It is possible that the driver handling device is enumerated before registering debugfs. If the driver wants to access debugfs by calling tpmi_get_debugfs_dir(), this will return error in this case.
Hence register debugfs before creating devices.
--- drivers/platform/x86/intel/vsec_tpmi.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/platform/x86/intel/vsec_tpmi.c +6 -4
@@ -813,10 +813,6 @@ static int intel_vsec_tpmi_init(struct aauxiliary_set_drvdata (auxdev, tpmi_info); - ret =tpmi_create_devices (tpmi_info); -if (ret) -return ret; -/* * Allow debugfs when security policy allows. Everything this debugfs * interface provides, can also be done via /dev/mem access. If
@@ -826,6 +822,12 @@ static int intel_vsec_tpmi_init(struct aif (!security_locked_down (LOCKDOWN_DEV_MEM ) &&capable (CAP_SYS_RAWIO ))tpmi_dbgfs_register (tpmi_info); + ret =tpmi_create_devices (tpmi_info); +if (ret) { +debugfs_remove_recursive (tpmi_info->dbgfs_dir); +return ret; + } +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 908/957 platform/x86: lenovo-wmi-helpers: Move gamezone enums to wmi-helpers
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Derek J. Clark <[email protected]>
commit 7e27896e16a1c450085c3fe020eeb1b223880f37 upstream.
In a later patch in the series the thermal mode enum will be accessed across three separate drivers (wmi-capdata, wmi-gamezonem and wmi-other). An additional patch in the series will also add a function prototype that needs to reference this enum in wmi-helpers.h. To avoid having all these drivers begin to import each others headers, and to avoid declaring an opaque enum to hande the second case, move the thermal mode enum to helpers where it can be safely accessed by everything that needs it from a single import.
While at it, since the gamezone_events_type enum is the only remaining item in the header, move that as well and remove the gamezone header entirely.
--- drivers/platform/x86/lenovo/wmi-events.c | 2 +- drivers/platform/x86/lenovo/wmi-gamezone.c | 1 - drivers/platform/x86/lenovo/wmi-gamezone.h | 20 -------------------- drivers/platform/x86/lenovo/wmi-helpers.h | 13 +++++++++++++ drivers/platform/x86/lenovo/wmi-other.c | 1 - 5 files changed, 14 insertions(+), 23 deletions(-) delete mode 100644 drivers/platform/x86/lenovo/wmi-gamezone.h
drivers/platform/x86/lenovo/wmi-events.c +1 -1
@@ -17,7 +17,7 @@#include <linux/wmi.h> #include "wmi-events.h" -#include "wmi-gamezone.h" +#include "wmi-helpers.h" #define THERMAL_MODE_EVENT_GUID "D320289E-8FEA-41E0-86F9-911D83151B5F"
drivers/platform/x86/lenovo/wmi-gamezone.c +0 -1
@@ -21,7 +21,6 @@#include <linux/wmi.h> #include "wmi-events.h" -#include "wmi-gamezone.h" #include "wmi-helpers.h" #include "wmi-other.h"
drivers/platform/x86/lenovo/wmi-gamezone.h deleted +0 -20
@@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/* Copyright (C) 2025 Derek J. Clark <[email protected]> */ - -#ifndef _LENOVO_WMI_GAMEZONE_H_ -#define _LENOVO_WMI_GAMEZONE_H_ - -enum gamezone_events_type { -LWMI_GZ_GET_THERMAL_MODE =1 , -}; - -enum thermal_mode { -LWMI_GZ_THERMAL_MODE_QUIET =0x01 , -LWMI_GZ_THERMAL_MODE_BALANCED =0x02 , -LWMI_GZ_THERMAL_MODE_PERFORMANCE =0x03 , -LWMI_GZ_THERMAL_MODE_EXTREME =0xE0 ,/* Ver 6+ */ -LWMI_GZ_THERMAL_MODE_CUSTOM =0xFF , -}; - -#endif /* !_LENOVO_WMI_GAMEZONE_H_ */
drivers/platform/x86/lenovo/wmi-helpers.h +13 -0
@@ -14,6 +14,19 @@ struct wmi_method_args_32 {u32 arg1; }; +enum lwmi_event_type { +LWMI_GZ_GET_THERMAL_MODE =0x01 , +}; + +enum thermal_mode { +LWMI_GZ_THERMAL_MODE_NONE =0x00 , +LWMI_GZ_THERMAL_MODE_QUIET =0x01 , +LWMI_GZ_THERMAL_MODE_BALANCED =0x02 , +LWMI_GZ_THERMAL_MODE_PERFORMANCE =0x03 , +LWMI_GZ_THERMAL_MODE_EXTREME =0xE0 ,/* Ver 6+ */ +LWMI_GZ_THERMAL_MODE_CUSTOM =0xFF , +}; +int lwmi_dev_evaluate_int (struct wmi_device *wdev,u8 instance,u32 method_id,unsigned char *buf,size_t size,u32 *retval);
drivers/platform/x86/lenovo/wmi-other.c +0 -1
@@ -36,7 +36,6 @@#include "wmi-capdata01.h" #include "wmi-events.h" -#include "wmi-gamezone.h" #include "wmi-helpers.h" #include "wmi-other.h" #include "../firmware_attributes_class.h"
Greg Kroah-Hartman
maintainerPATCH 909/957 platform/x86: lenovo-wmi-other: Fix tunable_attr_01 struct members
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Derek J. Clark <[email protected]>
commit 71f3843e0f81e3c097a088c1121154bb9a44da0a upstream.
In struct tunable_attr_01 the capdata pointer is unused and the size of the id members is u32 when it should be u8. Fix these prior to adding additional members.
No functional change intended.
--- drivers/platform/x86/lenovo/wmi-other.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/platform/x86/lenovo/wmi-other.c +3 -4
@@ -82,11 +82,10 @@ struct lwmi_om_priv { };struct tunable_attr_01 { -struct capdata01 *capdata;struct device *dev; -u32 feature_id; -u32 device_id; -u32 type_id; +u8 feature_id; +u8 device_id; +u8 type_id; };static struct tunable_attr_01 ppt_pl1_spl = {
Greg Kroah-Hartman
maintainerPATCH 910/957 accel/rocket: Fix prep_bo ioctl leaking positive return from dma_resv_wait_timeout()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gyeyoung Baek <[email protected]>
commit 74570e12b4705ea11dcdfbfbd0a0b0fdaeff3059 upstream.
dma_resv_wait_timeout() returns a positive 'remaining jiffies' value on success, 0 on timeout, and -errno on failure.
rocket_ioctl_prep_bo() returns this 'long' result from an int-typed ioctl handler, so positive values reach userspace as bogus errors. Explicitly set ret to 0 on the success path.
--- drivers/accel/rocket/rocket_gem.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/accel/rocket/rocket_gem.c +2 -0
@@ -144,6 +144,8 @@ int rocket_ioctl_prep_bo(struct drm_devi ret =dma_resv_wait_timeout (gem_obj->resv,DMA_RESV_USAGE_WRITE , true, timeout);if (!ret) ret = timeout ? -ETIMEDOUT : -EBUSY ; +else if (ret >0 ) + ret =0 ; shmem_obj = &to_rocket_bo (gem_obj)->base;
Greg Kroah-Hartman
maintainerPATCH 911/957 ALSA: hda/realtek: Add mute LED quirk for HP Pavilion Laptop 16-ag0xxx
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrien Burnett <[email protected]>
commit 7d1051ad68df3d584b5f24bfa1fb19f3a24db278 upstream.
Add a SND_PCI_QUIRK entry for the HP Pavilion Laptop 16-ag0xxx (subsystem 0x103c:0x8cbc, Realtek ALC245). The ALC245_FIXUP_HP_X360_MUTE_LEDS fixup is already used by the neighbouring HP Pavilion Aero Laptop 13-bg0xxx (0x103c:0x8cbd); it chains the master-mute COEF handler with the GPIO mic-mute LED handler, which is what this machine needs.
Tested on the affected hardware: both the mute and mic-mute key LEDs respond correctly to the keyboard hotkeys after this change.
--- sound/hda/codecs/realtek/alc269.c | 1 + 1 file changed, 1 insertion(+)
sound/hda/codecs/realtek/alc269.c +1 -0
@@ -6960,6 +6960,7 @@ static const struct hda_quirk alc269_fixSND_PCI_QUIRK (0x103c ,0x8ca4 ,"HP ZBook Fury" ,ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED ),SND_PCI_QUIRK (0x103c ,0x8ca7 ,"HP ZBook Fury" ,ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED ),SND_PCI_QUIRK (0x103c ,0x8caf ,"HP Elite mt645 G8 Mobile Thin Client" ,ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF ), +SND_PCI_QUIRK (0x103c ,0x8cbc ,"HP Pavilion Laptop 16-ag0xxx" ,ALC245_FIXUP_HP_X360_MUTE_LEDS ),SND_PCI_QUIRK (0x103c ,0x8cbd ,"HP Pavilion Aero Laptop 13-bg0xxx" ,ALC245_FIXUP_HP_X360_MUTE_LEDS ),SND_PCI_QUIRK (0x103c ,0x8cdd ,"HP Spectre" ,ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX ), SND_PCI_QUIRK(0x103c, 0x8cde, "HP OmniBook Ultra Flip Laptop 14t", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
Greg Kroah-Hartman
maintainerPATCH 912/957 ALSA: hda/realtek: Add quirk for Samsung Galaxy Book5 360 headphone
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Markus Kramer <[email protected]>
commit fd87b510f5f543125ecf51e7c706a9f4bc3352be upstream.
The Samsung Galaxy Book5 360 (NP750QHA, PCI subsystem ID 0x144d:0xc902) has severe audio distortion on the 3.5mm headphone jack. Applying ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET corrects the output path configuration, consistent with fixes already applied to other Samsung Galaxy Book models using the same ALC256 codec.
--- sound/hda/codecs/realtek/alc269.c | 1 + 1 file changed, 1 insertion(+)
sound/hda/codecs/realtek/alc269.c +1 -0
@@ -7240,6 +7240,7 @@ static const struct hda_quirk alc269_fixSND_PCI_QUIRK (0x144d ,0xc870 ,"Samsung Galaxy Book2 Pro (NP950XED)" ,ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS ),SND_PCI_QUIRK (0x144d ,0xc872 ,"Samsung Galaxy Book2 Pro (NP950XEE)" ,ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS ),SND_PCI_QUIRK (0x144d ,0xc886 ,"Samsung Galaxy Book3 Pro (NP964XFG)" ,ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS ), +SND_PCI_QUIRK (0x144d ,0xc902 ,"Samsung Galaxy Book5 360 (NP750QHA)" ,ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET ),SND_PCI_QUIRK (0x144d ,0xc1ca ,"Samsung Galaxy Book3 Pro 360 (NP960QFG)" ,ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS ),SND_PCI_QUIRK (0x144d ,0xc1cb ,"Samsung Galaxy Book3 Pro 360 (NP965QFG)" ,ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS ), SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
Greg Kroah-Hartman
maintainerPATCH 913/957 ALSA: usb-audio: Bound MIDI 2.0 endpoint descriptor scans
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]>
commit 918be519c7876329e1b6e2ea1c59f0b75e792dca upstream.
The USB MIDI 2.0 endpoint parser has the same descriptor walking pattern as the legacy MIDI parser. It validates bLength against bNumGrpTrmBlock before reading baAssoGrpTrmBlkID[], but not against the remaining bytes in the endpoint-extra scan.
A malformed device can therefore make later baAssoGrpTrmBlkID[] reads consume bytes past the walked descriptor.
Reject zero-length and overlong descriptors while walking endpoint extras.
--- sound/usb/midi2.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
sound/usb/midi2.c +7 -5
@@ -496,15 +496,17 @@ static void *find_usb_ms_endpoint_descriwhile (extralen >3 ) {struct usb_ms_endpoint_descriptor *ms_ep = (struct usb_ms_endpoint_descriptor *)extra; +int length = ms_ep->bLength; -if (ms_ep->bLength >3 && +if (!length || length > extralen) +break ; + +if (length >3 && ms_ep->bDescriptorType ==USB_DT_CS_ENDPOINT && ms_ep->bDescriptorSubtype == subtype)return ms_ep; -if (!extra[0 ]) -break ; - extralen -= extra[0 ]; - extra += extra[0 ]; + extralen -= length; + extra += length; }return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 914/957 ALSA: usb-audio: Bound MIDI endpoint descriptor scans
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]>
commit d6854daa67be623860f4e1873fd3d3c275aba4ed upstream.
snd_usbmidi_get_ms_info() validates the internal MIDIStreaming endpoint descriptor size before using baAssocJackID[], but the descriptor walker can still return a class-specific endpoint descriptor whose bLength exceeds the remaining bytes in the endpoint-extra scan.
That leaves later flexible-array reads bounded by bLength, but not by the remaining bytes in the endpoint-extra scan.
Stop walking when bLength is zero or
extends past the remaining endpoint-extra scan.
--- sound/usb/midi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
sound/usb/midi.c +7 -5
@@ -1947,15 +1947,17 @@ static struct usb_ms_endpoint_descriptorwhile (extralen >3 ) {struct usb_ms_endpoint_descriptor *ms_ep = (struct usb_ms_endpoint_descriptor *)extra; +int length = ms_ep->bLength; -if (ms_ep->bLength >3 && +if (!length || length > extralen) +break ; + +if (length >3 && ms_ep->bDescriptorType ==USB_DT_CS_ENDPOINT && ms_ep->bDescriptorSubtype ==UAC_MS_GENERAL )return ms_ep; -if (!extra[0 ]) -break ; - extralen -= extra[0 ]; - extra += extra[0 ]; + extralen -= length; + extra += length; }return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 915/957 ALSA: usb-audio: qcom: Check offload mapping failures
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]>
commit 814b2c9b30e56074e11fc0a6e5419b3fee0639bc upstream.
uaudio_transfer_buffer_setup() calls dma_get_sgtable() and then passes the sg_table to uaudio_iommu_map_xfer_buf() without checking whether sg table construction succeeded. If dma_get_sgtable() fails, the sg_table contents are not valid.
uaudio_iommu_map_pa() also ignores iommu_map() failures for the event and transfer rings and still returns the allocated IOVA to the QMI response. That can expose an unmapped IOVA to the audio DSP. For transfer rings, the failed mapping also leaves the IOVA allocator state marked in use.
Check both operations. Free the coherent transfer buffer when sg table construction fails, free the sg table when transfer-buffer IOMMU mapping fails, and release the transfer-ring IOVA if iommu_map() fails. Also return the existing event-ring IOVA when the event ring is already mapped, matching the pre-split helper behavior.
--- sound/usb/qcom/qc_audio_offload.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-)
sound/usb/qcom/qc_audio_offload.c +25 -6
@@ -565,6 +565,7 @@ static unsigned long uaudio_iommu_map_paunsigned long iova =0 ;bool map = true;int prot =uaudio_iommu_map_prot (dma_coherent); +int ret;switch (mtype) {case MEM_EVENT_RING :
@@ -582,10 +583,24 @@ static unsigned long uaudio_iommu_map_padev_err (uaudio_qdev->data->dev,"unknown mem type %d\n" , mtype); } -if (!iova || !map) +if (!iova)return 0 ; -iommu_map (uaudio_qdev->data->domain, iova, pa, size, prot,GFP_KERNEL ); +if (!map) +return iova; + + ret =iommu_map (uaudio_qdev->data->domain, iova, pa, size, prot, +GFP_KERNEL ); +if (ret) { +dev_err (uaudio_qdev->data->dev, +"failed to map %zu bytes at iova 0x%08lx: %d\n" , + size, iova, ret); +if (mtype ==MEM_XFER_RING ) +uaudio_put_iova (iova, size, + &uaudio_qdev->xfer_ring_list, + &uaudio_qdev->xfer_ring_iova_size); +return 0 ; + }return iova; }
@@ -1054,15 +1069,17 @@ static int uaudio_transfer_buffer_setup(if (!xfer_buf)return -ENOMEM ; -dma_get_sgtable (subs->dev->bus->sysdev, &xfer_buf_sgt, xfer_buf, - xfer_buf_dma, len); + ret =dma_get_sgtable (subs->dev->bus->sysdev, &xfer_buf_sgt, xfer_buf, + xfer_buf_dma, len); +if (ret) + goto free_xfer_buf;/* map the physical buffer into sysdev as well */ xfer_buf_dma_sysdev =uaudio_iommu_map_xfer_buf (dma_coherent, len, &xfer_buf_sgt);if (!xfer_buf_dma_sysdev) { ret = -ENOMEM ; - goto unmap_sync; + goto free_sgt; } mem_info->dma = xfer_buf_dma;
@@ -1073,7 +1090,9 @@ static int uaudio_transfer_buffer_setup(return 0 ; -unmap_sync: +free_sgt: +sg_free_table (&xfer_buf_sgt); +free_xfer_buf:usb_free_coherent (subs->dev, len, xfer_buf, xfer_buf_dma);return ret;
Greg Kroah-Hartman
maintainerPATCH 916/957 btrfs: only release the dirty pages io tree after successful writes
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit 4066c55e109475a06d18a1f127c939d551211956 upstream.
[WARNING]
With extra warning on dirty extent buffers at umount (aka, the next patch in the series), test case generic/388 can trigger the following warning about dirty extent buffers at unmount time:
BTRFS critical (device dm-2 state E): emergency shutdown
BTRFS error (device dm-2 state E): error while writing out transaction: -30
BTRFS warning (device dm-2 state E): Skipping commit of aborted transaction.
BTRFS error (device dm-2 state EA): Transaction 9 aborted (error -30)
BTRFS: error (device dm-2 state EA) in cleanup_transaction:2068: errno=-30 Readonly filesystem BTRFS info (device dm-2 state EA): forced readonly
BTRFS info (device dm-2 state EA): last unmount of filesystem 4fbf2e15-f941-49a0-bc7c-716315d2777c
------------[ cut here ]------------ WARNING: disk-io.c:3311 at invalidate_and_check_btree_folios+0xfd/0x1ca [btrfs], CPU#8: umount/914368 CPU: 8 UID: 0 PID: 914368 Comm: umount Tainted: G OE 7.1.0-rc1-custom+ #372 PREEMPT(full) 2de38db8d1deae71fde295430a0ff3ab98ccf596 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 02/02/2022 RIP: 0010:invalidate_and_check_btree_folios+0xfd/0x1ca [btrfs] Call Trace: <TASK> close_ctree+0x52e/0x574 [btrfs d2f0b1cd330d1287e7a9919d112eadfc0e914efd] generic_shutdown_super+0x89/0x1a0 kill_anon_super+0x16/0x40 btrfs_kill_super+0x16/0x20 [btrfs d2f0b1cd330d1287e7a9919d112eadfc0e914efd] deactivate_locked_super+0x2d/0xb0 cleanup_mnt+0xdc/0x140 task_work_run+0x5a/0xa0 exit_to_user_mode_loop+0x123/0x4b0 do_syscall_64+0x243/0x7c0 entry_SYSCALL_64_after_hwframe+0x4b/0x53 </TASK> ---[ end trace 0000000000000000 ]--- BTRFS warning (device dm-2 state EA): unable to release extent buffer 30539776 owner 9 gen 9 refs 2 flags 0x7 BTRFS warning (device dm-2 state EA): unable to release extent buffer 30621696 owner 257 gen 9 refs 2 flags 0x7 BTRFS warning (device dm-2 state EA): unable to release extent buffer 30638080 owner 258 gen 9 refs 2 flags 0x7 BTRFS warning (device dm-2 state EA): unable to release extent buffer 30654464 owner 7 gen 9 refs 2 flags 0x7 BTRFS warning (device dm-2 state EA): unable to release extent buffer 30703616 owner 2 gen 9 refs 2 flags 0x7 BTRFS warning (device dm-2 state EA): unable to release extent buffer 30720000 owner 10 gen 9 refs 2 flags 0x7 BTRFS warning (device dm-2 state EA): unable to release extent buffer 30736384 owner 4 gen 9 refs 2 flags 0x7 BTRFS warning (device dm-2 state EA): unable to release extent buffer 30752768 owner 11 gen 9 refs 2 flags 0x7
I'm using a stripped down version, which seems to trigger the warning more reliably:
_fsstress_pid=""
workload()
{
dmesg -C
mkfs.btrfs -f -K $dev > /dev/null
echo 1 > /sys/kernel/debug/clear_warn_once
mount $dev $mnt
$fsstress -w -n 1024 -p 4 -d $mnt &
_fsstress_pid=$!
sleep 0
$godown $mnt
pkill --echo -PIPE fsstress > /dev/null
wait $_fsstress_pid
unset _fsstress_pid
umount $mnt if dmesg | grep -q "WARNING"; then
fail
fi
}
for (( i = 0; i < $runtime; i++ )); do
echo "=== $i/$runtime ==="
workload
done
[CAUSE]
Inside btrfs_write_and_wait_transaction(), we first try to write all dirty ebs, then wait for them to finish.
After that we call btrfs_extent_io_tree_release() to free all extent states from dirty_pages io tree.
However if we hit an error from btrfs_write_marked_extent(), then we still call btrfs_extent_io_tree_release() to clear that dirty_pages io tree, which may contain dirty records that we haven't yet submitted.
Furthermore, the later transaction cleanup path will utilize that dirty_pages io tree to properly cleanup those dirty ebs, but since it's already empty, no dirty ebs are properly cleaned up, thus will later trigger the warnings inside invalidate_btree_folios().
[FIX]
Normally such dirty ebs won't cause problems, as when the iput() is called on the btree inode, the dirty ebs will be forcibly written back, and since the fs is already in an error status, such writeback will not reach disk and finish immediately.
But it's still better to get rid of such dirty ebs, if we ended up with dirty ebs but the fs is not in an error status, then such writeback at iput() time will be too late, as all workers are already stopped but writeback will utilize workers, which will lead to NULL pointer dereferences.
Instead of unconditionally calling btrfs_extent_io_tree_release(), only call it if btrfs_write_and_wait_transaction() finished successfully, so that @dirty_pages extent io tree is kept untouched for transaction cleanup.
--- fs/btrfs/disk-io.c | 1 + fs/btrfs/transaction.c | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-)
fs/btrfs/disk-io.c +1 -0
@@ -4646,6 +4646,7 @@ static void btrfs_destroy_marked_extentsfree_extent_buffer_stale (eb); } } +btrfs_extent_io_tree_release (dirty_pages); } static void btrfs_destroy_pinned_extent(struct btrfs_fs_info *fs_info,
fs/btrfs/transaction.c +4 -5
@@ -1268,14 +1268,13 @@ static int btrfs_write_and_wait_transactblk_finish_plug (&plug); ret2 =btrfs_wait_extents (fs_info, dirty_pages); -btrfs_extent_io_tree_release (&trans->transaction->dirty_pages); -if (ret)return ret; -else if (ret2) +if (ret2)return ret2; -else -return 0 ; + +btrfs_extent_io_tree_release (&trans->transaction->dirty_pages); +return 0 ; }/*
Greg Kroah-Hartman
maintainerPATCH 917/957 ceph: fix a buffer leak in __ceph_setxattr()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Viacheslav Dubeyko <[email protected]>
commit 5d3cc36b4e77a27ce7b686b7c59c7072bcb3fa8e upstream.
The old_blob in __ceph_setxattr() can store ci->i_xattrs.prealloc_blob value during the retry. However, it is never called the ceph_buffer_put() for the old_blob object. This patch fixes the issue of the buffer leak.
--- fs/ceph/xattr.c | 1 + 1 file changed, 1 insertion(+)
fs/ceph/xattr.c +1 -0
@@ -1296,6 +1296,7 @@ retry: do_sync:spin_unlock (&ci->i_ceph_lock); +ceph_buffer_put (old_blob); do_sync_unlocked:if (lock_snap_rwsem)up_read (&mdsc->snap_rwsem);
Greg Kroah-Hartman
maintainerPATCH 918/957 ceph: fix BUG_ON in __ceph_build_xattrs_blob() due to stale blob size
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Viacheslav Dubeyko <[email protected]>
commit 0c22d9511cbde746622f8e4c11aaa63fe76d45f9 upstream.
The generic/642 test-case can reproduce the kernel crash:
[40243.605254] ------------[ cut here ]------------ [40243.605956] kernel BUG at fs/ceph/xattr.c:918! [40243.607142] Oops: invalid opcode: 0000 [#1] SMP PTI [40243.608067] CPU: 7 UID: 0 PID: 498762 Comm: kworker/7:1 Not tainted 7.0.0-rc7+ #3 PREEMPT(full) [40243.609700] Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [40243.611820] Workqueue: ceph-msgr ceph_con_workfn [40243.612715] RIP: 0010:__ceph_build_xattrs_blob+0x1b8/0x1e0 [40243.613731] Code: 0f 84 82 fe ff ff e9 cf 8e 56 ff 48 8d 65 e8 31 c0 5b 41 5c 41 5d 5d 31 d2 31 c9 31 f6 31 ff 45 31 c0 45 31 c9 c3 cc cc cc cc <0f> 0b 4c 8b 62 08 41 8b 85 24 07 00 00 49 83 c4 04 41 89 44 24 fc [40243.616888] RSP: 0018:ffffcc80c4d4b688 EFLAGS: 00010287 [40243.617773] RAX: 0000000000010026 RBX: 0000000000000001 RCX: 0000000000000000 [40243.618928] RDX: ffff8a773798dee0 RSI: 0000000000000000 RDI: 0000000000000000 [40243.620158] RBP: ffffcc80c4d4b6a0 R08: 0000000000000000 R09: 0000000000000000 [40243.621573] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8a75f3b58000 [40243.622907] R13: ffff8a75f3b58000 R14: 0000000000000080 R15: 000000000000bffd [40243.624054] FS: 0000000000000000(0000) GS:ffff8a787d1b4000(0000) knlGS:0000000000000000 [40243.625331] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [40243.626269] CR2: 000072f390b623c0 CR3: 000000011c02a003 CR4: 0000000000372ef0 [40243.627408] Call Trace: [40243.627839] <TASK> [40243.628188] __prep_cap+0x3fd/0x4a0 [40243.628789] ? do_raw_spin_unlock+0x4e/0xe0 [40243.629474] ceph_check_caps+0x46a/0xc80 [40243.630094] ? __lock_acquire+0x4a2/0x2650 [40243.630773] ? find_held_lock+0x31/0x90 [40243.631347] ? handle_cap_grant+0x79f/0x1060 [40243.632068] ? lock_release+0xd9/0x300 [40243.632696] ? __mutex_unlock_slowpath+0x3e/0x340 [40243.633429] ? lock_release+0xd9/0x300 [40243.634052] handle_cap_grant+0xcf6/0x1060 [40243.634745] ceph_handle_caps+0x122b/0x2110 [40243.635415] mds_dispatch+0x5bd/0x2160 [40243.636034] ? ceph_con_process_message+0x65/0x190 [40243.636828] ? lock_release+0xd9/0x300 [40243.637431] ceph_con_process_message+0x7a/0x190 [40243.638184] ? kfree+0x311/0x4f0 [40243.638749] ? kfree+0x311/0x4f0 [40243.639268] process_message+0x16/0x1a0 [40243.639915] ? sg_free_table+0x39/0x90 [40243.640572] ceph_con_v2_try_read+0xf58/0x2120 [40243.641255] ? lock_acquire+0xc8/0x300 [40243.641863] ceph_con_workfn+0x151/0x820 [40243.642493] process_one_work+0x22f/0x630 [40243.643093] ? process_one_work+0x254/0x630 [40243.643770] worker_thread+0x1e2/0x400 [40243.644332] ? __pfx_worker_thread+0x10/0x10 [40243.645020] kthread+0x109/0x140 [40243.645560] ? __pfx_kthread+0x10/0x10 [40243.646125] ret_from_fork+0x3f8/0x480 [40243.646752] ? __pfx_kthread+0x10/0x10 [40243.647316] ? __pfx_kthread+0x10/0x10 [40243.647919] ret_from_fork_asm+0x1a/0x30 [40243.648556] </TASK> [40243.648902] Modules linked in: overlay hctr2 libpolyval chacha libchacha adiantum libnh libpoly1305 essiv intel_rapl_msr intel_rapl_common intel_uncore_frequency_common skx_edac_common nfit kvm_intel kvm irqbypass joydev ghash_clmulni_intel aesni_intel rapl input_leds mac_hid psmouse vga16fb serio_raw vgastate floppy i2c_piix4 pata_acpi bochs qemu_fw_cfg i2c_smbus sch_fq_codel rbd dm_crypt msr parport_pc ppdev lp parport efi_pstore [40243.654766] ---[ end trace 0000000000000000 ]---
Commit d93231a6bc8a ("ceph: prevent a client from exceeding the MDS maximum xattr size") moved the required_blob_size computation to before the __build_xattrs() call, introducing a race.
__build_xattrs() releases and reacquires i_ceph_lock during execution. In that window, handle_cap_grant() may update i_xattrs.blob with a newer MDS-provided blob and bump i_xattrs.version. When __build_xattrs() detects that index_version < version, it destroys and rebuilds the entire xattr rb-tree from the new blob, potentially increasing count, names_size, and vals_size.
The prealloc_blob size check that follows still uses the stale required_blob_size computed before the rebuild, so it passes even when prealloc_blob is too small for the now-larger tree. After __set_xattr() adds one more xattr on top, __ceph_build_xattrs_blob() is called from the cap flush path and hits:
BUG_ON(need > ci->i_xattrs.prealloc_blob->alloc_len);
Fix this by recomputing required_blob_size after __build_xattrs() returns, using the current tree state. Also re-validate against m_max_xattr_size to fall back to the sync path if the rebuilt tree now exceeds the MDS limit.
--- fs/ceph/xattr.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
fs/ceph/xattr.c +16 -0
@@ -1256,6 +1256,22 @@ retry: ceph_vinop(inode), name, ceph_cap_string(issued));__build_xattrs (inode); +/* +* __build_xattrs() may have released and reacquired i_ceph_lock, +* during which handle_cap_grant() could have replaced i_xattrs.blob +* with a newer MDS-provided blob and bumped i_xattrs.version. If that +* caused __build_xattrs() to rebuild the rb-tree from the new blob, +* count/names_size/vals_size may now be larger than when +* required_blob_size was computed above. Recompute it here so the +* prealloc_blob size check below reflects the current tree state. +*/ + required_blob_size =__get_required_blob_size (ci, name_len, val_len); +if (required_blob_size > mdsc->mdsmap->m_max_xattr_size) { +doutc (cl,"sync (size too large): %d > %llu\n" , + required_blob_size, mdsc->mdsmap->m_max_xattr_size); + goto do_sync; + } +if (!ci->i_xattrs.prealloc_blob || required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) {struct ceph_buffer *blob;
Greg Kroah-Hartman
maintainerPATCH 919/957 io-wq: check that the predecessor is hashed in io_wq_remove_pending()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicholas Carlini <[email protected]>
commit d6a2d7b04b5a093021a7a0e2e69e9d5237dfa8cc upstream.
io_wq_remove_pending() needs to fix up wq->hash_tail[] if the cancelled work was the tail of its hash bucket. When doing this, it checks whether the preceding entry in acct->work_list has the same hash value, but never checks that the predecessor is hashed at all. io_get_work_hash() is simply atomic_read(&work->flags) >> IO_WQ_HASH_SHIFT, and the hash bits are never set for non-hashed work, so it returns 0. Thus, when a hashed bucket-0 work is cancelled while a non-hashed work is its list predecessor, the check spuriously passes and a pointer to the non-hashed io_kiocb is stored in wq->hash_tail[0].
Because non-hashed work is dequeued via the fast path in io_get_next_work(), which never touches hash_tail[], the stale pointer is never cleared. Therefore, after the non-hashed io_kiocb completes and is freed back to req_cachep, wq->hash_tail[0] is a dangling pointer. The io_wq is per-task (tctx->io_wq) and survives ring open/close, so the dangling pointer persists for the lifetime of the task; the next hashed bucket-0 enqueue dereferences it in io_wq_insert_work() and wq_list_add_after() writes through freed memory.
Add the missing io_wq_is_hashed() check so a non-hashed predecessor never inherits a hash_tail[] slot.
--- io_uring/io-wq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
io_uring/io-wq.c +2 -1
@@ -1125,7 +1125,8 @@ static inline void io_wq_remove_pending(if (io_wq_is_hashed (work) && work == wq->hash_tail[hash]) {if (prev) prev_work = container_of(prev, struct io_wq_work, list); -if (prev_work &&io_get_work_hash (prev_work) == hash) +if (prev_work &&io_wq_is_hashed (prev_work) && +io_get_work_hash (prev_work) == hash) wq->hash_tail[hash] = prev_work;else wq->hash_tail[hash] =NULL ;
Greg Kroah-Hartman
maintainerPATCH 920/957 iommu/amd: Bounds-check devid in __rlookup_amd_iommu()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jose Fernandez (Anthropic) <[email protected]>
commit 07d0f496fe7ec5abe3bee7e38be709521567bb33 upstream.
iommu_device_register() walks every device on the PCI bus via bus_for_each_dev() and calls amd_iommu_probe_device() for each. The inlined check_device() path computes the device's sbdf, calls rlookup_amd_iommu() to find the owning IOMMU, and only afterwards verifies devid <= pci_seg->last_bdf. __rlookup_amd_iommu() indexes rlookup_table[devid] with no bounds check of its own, so for a PCI device whose BDF is not described by the IVRS, the lookup reads past the end of the allocation before the caller's bounds check can run.
This was harmless before commit e874c666b15b ("iommu/amd: Change rlookup, irq_lookup, and alias to use kvalloc()"): the table was a zeroed page-order allocation, so the over-read returned NULL and the caller's NULL check skipped the device. After that commit the table is a tight kvcalloc() and the over-read returns adjacent slab contents, which check_device() then dereferences as a struct amd_iommu *, causing a boot-time GPF.
Seen on Google Compute Engine ct6e VMs, where the virtualized IVRS describes only the four TPU endpoints 00:04.0-07.0; the gVNIC at 00:08.0 (devid 0x40) indexes 56 bytes past the 456-byte allocation, into the adjacent kmalloc-512 slab object:
pci 0000:00:04.0: Adding to iommu group 0
pci 0000:00:05.0: Adding to iommu group 1
pci 0000:00:06.0: Adding to iommu group 2
pci 0000:00:07.0: Adding to iommu group 3
Oops: general protection fault, probably for non-canonical address 0x3a64695f78746382: 0000 [#1] SMP NOPTI CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.18.22 #1 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 12/06/2025 RIP: 0010:amd_iommu_probe_device+0x54/0x3a0 Call Trace: __iommu_probe_device+0x107/0x520 probe_iommu_group+0x29/0x50 bus_for_each_dev+0x7e/0xe0 iommu_device_register+0xc9/0x240 iommu_go_to_state+0x9c0/0x1c60 amd_iommu_init+0x14/0x40 pci_iommu_init+0x16/0x60 do_one_initcall+0x47/0x2f0
Guard the array access in __rlookup_amd_iommu(). With the fix applied on 6.18.22, the gVNIC at 00:08.0 is skipped cleanly and the VM boots.
--- drivers/iommu/amd/iommu.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/iommu/amd/iommu.c +6 -2
@@ -329,8 +329,12 @@ static struct amd_iommu *__rlookup_amd_istruct amd_iommu_pci_seg *pci_seg;for_each_pci_segment (pci_seg) { -if (pci_seg->id == seg) -return pci_seg->rlookup_table[devid]; +if (pci_seg->id != seg) +continue ; +/* IVRS may not describe every device on the bus */ +if (devid > pci_seg->last_bdf) +return NULL ; +return pci_seg->rlookup_table[devid]; }return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 921/957 x86/kexec: Push kjump return address even for non-kjump kexec
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Woodhouse <[email protected]>
commit 786a45757dcdf8f2beb9d4a6db605db16c18b2b4 upstream.
The version of purgatory code shipped by kexec-tools attempts to look above the top of its stack to find a return address for a kjump, even in a non-kjump kexec.
After the commit in Fixes: the word above the stack might not be there, leading to a fault (which is at least now caught by my exception-handling code in kexec).
That commit fixed things for the actual kjump path, but no longer "gratuitously" pushes the unused return address to the stack in the non-kjump path. Put that *back* in the non-kjump path, to prevent purgatory from crashing when trying to access it.
--- arch/x86/kernel/relocate_kernel_64.S | 8 ++++++++ 1 file changed, 8 insertions(+)
arch/x86/kernel/relocate_kernel_64.S +8 -0
@@ -133,6 +133,14 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_ma * %r13 original CR4 when relocate_kernel() was invoked */ + /* + * Set return address to 0 if not preserving context. The purgatory + * shipped in kexec-tools will unconditionally look for the return + * address on the stack and set a kexec_jump_back_entry= command + * line option if it's non-zero. There's no other way that it can + * tell a preserve-context (kjump) kexec from a normal one. + */ + pushq $0 /* store the start address on the stack */ pushq %rdx
Greg Kroah-Hartman
maintainerPATCH 922/957 xfs: fix memory leak on error in xfs_alloc_zone_info()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wilfred Mallawa <[email protected]>
commit 592975da8c3ca87b043077e6eafa37665eae7936 upstream.
Currently, the 0th index of the zi_used_bucket_bitmap array is not freed on error due to the pre-decrement then evaluate semantic of the while loop used in xfs_alloc_zone_info(). Fix it by allowing for the i == 0 case to be covered.
--- fs/xfs/xfs_zone_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/xfs/xfs_zone_alloc.c +1 -1
@@ -1178,7 +1178,7 @@ xfs_alloc_zone_info(return zi; out_free_bitmaps: -while (--i >0 ) +while (--i >=0 )kvfree (zi->zi_used_bucket_bitmap[i]);kfree (zi);return NULL ;
Greg Kroah-Hartman
maintainerPATCH 923/957 virt: sev-guest: Do not use host-controlled page order in cleanup path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carlos López <[email protected]>
commit 23e6a1ca04ae44806439a5a446e62e4d42e80bb4 upstream.
When issuing an extended guest request (SVM_VMGEXIT_EXT_GUEST_REQUEST), get_ext_report() allocates a buffer to retrieve a certificate blob from the host, keeping track of its size in report_req->certs_len.
However, the host may return SNP_GUEST_VMM_ERR_INVALID_LEN, indicating an invalid buffer size, as well as the expected length of such buffer. get_ext_report() subsequently updates report_req->certs_len with the host-controlled value, and cleans up the buffer by computing a page order from such value. This is incorrect, as the host-provided length may not match the page order of the original allocation, potentially resulting in corruption in the page allocator.
Fix this by using alloc_pages_exact() instead, and reusing @npages to compute the size passed to free_pages_exact(). For consistency, also use @npages to compute the size when allocating the pages, even though this last change has no functional effect.
--- drivers/virt/coco/sev-guest/sev-guest.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
drivers/virt/coco/sev-guest/sev-guest.c +5 -7
@@ -176,7 +176,6 @@ static int get_ext_report(struct snp_guestruct snp_guest_req req = {};int ret, npages =0 , resp_len;sockptr_t certs_address; -struct page *page;if (sockptr_is_null (io->req_data) ||sockptr_is_null (io->resp_data))return -EINVAL ;
@@ -211,16 +210,15 @@ static int get_ext_report(struct snp_gue* zeros to indicate that certificate data was not provided. */ npages = report_req->certs_len >>PAGE_SHIFT ; - page =alloc_pages (GFP_KERNEL_ACCOUNT | __GFP_ZERO, -get_order (report_req->certs_len)); -if (!page) + req.certs_data =alloc_pages_exact (npages <<PAGE_SHIFT , +GFP_KERNEL_ACCOUNT | __GFP_ZERO); +if (!req.certs_data)return -ENOMEM ; - req.certs_data =page_address (page); ret =set_memory_decrypted ((unsigned long )req.certs_data, npages);if (ret) {pr_err ("failed to mark page shared, ret=%d\n" , ret); -__free_pages (page,get_order (report_req->certs_len)); +free_pages_exact (req.certs_data, npages <<PAGE_SHIFT );return -EFAULT ; }
@@ -277,7 +275,7 @@ e_free_data:if (set_memory_encrypted ((unsigned long )req.certs_data, npages))WARN_ONCE (ret,"failed to restore encryption mask (leak it)\n" );else -__free_pages (page,get_order (report_req->certs_len)); +free_pages_exact (req.certs_data, npages <<PAGE_SHIFT ); }return ret; }
Greg Kroah-Hartman
maintainerPATCH 924/957 riscv: misaligned: Make enabling delegation depend on NONPORTABLE
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vivian Wang <[email protected]>
commit b69bcb13ed7024a84d6cd8ad330f1e32782fcf28 upstream.
The unaligned access emulation code in Linux has various deficiencies. For example, it doesn't emulate vector instructions [1] [2], and doesn't emulate KVM guest accesses. Therefore, requesting misaligned exception delegation with SBI FWFT actually regresses vector instructions' and KVM guests' behavior.
Until Linux can handle it properly, guard these sbi_fwft_set() calls behind RISCV_SBI_FWFT_DELEGATE_MISALIGNED, which in turn depends on NONPORTABLE. Those who are sure that this wouldn't be a problem can enable this option, perhaps getting better performance.
The rest of the existing code proceeds as before, except as if SBI_FWFT_MISALIGNED_EXC_DELEG is not available, to handle any remaining address misaligned exceptions on a best-effort basis. The KVM SBI FWFT implementation is also not touched, but it is disabled if the firmware emulates unaligned accesses.
--- arch/riscv/Kconfig | 22 ++++++++++++++++++++++ arch/riscv/kernel/traps_misaligned.c | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-)
arch/riscv/Kconfig +22 -0
@@ -925,6 +925,28 @@ config RISCV_VECTOR_MISALIGNED help Enable detecting support for vector misaligned loads and stores. +config RISCV_SBI_FWFT_DELEGATE_MISALIGNED + bool "Request firmware delegation of unaligned access exceptions" + depends on RISCV_SBI + depends on NONPORTABLE + help + Use SBI FWFT to request delegation of load address misaligned and + store address misaligned exceptions, if possible, and prefer Linux + kernel emulation of these accesses to firmware emulation. + + Unfortunately, Linux's emulation is still incomplete. Namely, it + currently does not handle vector instructions and KVM guest accesses. + On platforms where these accesses would have been handled by firmware, + enabling this causes unexpected kernel oopses, userspaces crashes and + KVM guest crashes. If you are sure that these are not a problem for + your platform, you can say Y here, which may improve performance. + + Saying N here will not worsen emulation support for unaligned accesses + even in the case where the firmware also has incomplete support. It + simply keeps the firmware's emulation enabled. + + If you don't know what to do here, say N. + choice prompt "Unaligned Accesses Support" default RISCV_PROBE_UNALIGNED_ACCESS
arch/riscv/kernel/traps_misaligned.c +1 -1
@@ -584,7 +584,7 @@ static int cpu_online_check_unaligned_acstatic bool misaligned_traps_delegated; -#ifdef CONFIG_RISCV_SBI +#if defined(CONFIG_RISCV_SBI_FWFT_DELEGATE_MISALIGNED )static int cpu_online_sbi_unaligned_setup (unsigned int cpu) {
Greg Kroah-Hartman
maintainerPATCH 925/957 powerpc/warp: Fix error handling in pika_dtm_thread
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ma Ke <[email protected]>
commit 108d7f951271cbd36ca36efc5e5d106966f5180c upstream.
pika_dtm_thread() acquires client through of_find_i2c_device_by_node() but fails to release it in error handling path. This could result in a reference count leak, preventing proper cleanup and potentially leading to resource exhaustion. Add put_device() to release the reference in the error handling path.
Found by code review.
--- arch/powerpc/platforms/44x/warp.c | 2 ++ 1 file changed, 2 insertions(+)
arch/powerpc/platforms/44x/warp.c +2 -0
@@ -293,6 +293,8 @@ static int pika_dtm_thread(void __iomemschedule_timeout (HZ ); } +put_device (&client->dev); +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 926/957 netfs: fix error handling in netfs_extract_user_iter()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
commit 0aad5704c6b4d14007d4eab15883e8524e4310f4 upstream.
In netfs_extract_user_iter(), if iov_iter_extract_pages() failed to extract user pages, bail out on -ENOMEM, otherwise return the error code only if @npages == 0, allowing short DIO reads and writes to be issued.
This fixes mmapstress02 from LTP tests against CIFS.
--- fs/netfs/iterator.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
fs/netfs/iterator.c +10 -3
@@ -22,7 +22,7 @@* * Extract the page fragments from the given amount of the source iterator and * build up a second iterator that refers to all of those bits. This allows -* the original iterator to disposed of. +* the original iterator to be disposed of. * * @extraction_flags can have ITER_ALLOW_P2PDMA set to request peer-to-peer DMA be * allowed on the pages extracted.
@@ -67,8 +67,8 @@ ssize_t netfs_extract_user_iter(struct i ret =iov_iter_extract_pages (orig, &pages, count, max_pages - npages, extraction_flags, &offset); -if (ret <0 ) { -pr_err ("Couldn't get user pages (rc=%zd)\n" , ret); +if (unlikely (ret <=0 )) { + ret = ret ?: -EIO ;break ; }
@@ -97,6 +97,13 @@ ssize_t netfs_extract_user_iter(struct i npages += cur_npages; } +if (ret <0 && (ret == -ENOMEM || npages ==0 )) { +for (i =0 ; i < npages; i++) +unpin_user_page (bv[i].bv_page); +kvfree (bv); +return ret; + } +iov_iter_bvec (new, orig->data_source, bv, npages, orig_len - count);return npages; }
Greg Kroah-Hartman
maintainerPATCH 927/957 nfsd: fix file change detection in CB_GETATTR
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Scott Mayhew <[email protected]>
commit 304d81a2fbf2b454def4debcb38ea173911b72cd upstream.
RFC 8881, section 10.4.3 doesn't say anything about caching the file size in the delegation record, nor does it say anything about comparing a cached file size with the size reported by the client in the CB_GETATTR reply for the purpose of determining if the client holds modified data for the file.
What section 10.4.3 of RFC 8881 does say is that the server should compare the *current* file size with the size reported by the client holding the delegation in the CB_GETATTR reply, and if they differ to treat it as a modification regardless of the change attribute retrieved via the CB_GETATTR.
Doing otherwise would cause the server to believe the client holding the delegation has a modified version of the file, even if the client flushed the modifications to the server prior to the CB_GETATTR. This would have the added side effect of subsequent CB_GETATTRs causing updates to the mtime, ctime, and change attribute even if the client holding the delegation makes no further updates to the file.
Modify nfsd4_deleg_getattr_conflict() to obtain the current file size via i_size_read(). Retain the ncf_cur_fsize field, since it's a convenient way to return the file size back to nfsd4_encode_fattr4(), but don't use it for the purpose of detecting file changes. Remove the unnecessary initialization of ncf_cur_fsize in nfs4_open_delegation().
Also, if we recall the delegation (because the client didn't respond to the CB_GETATTR), then skip the logic that checks the nfs4_cb_fattr fields.
--- fs/nfsd/nfs4state.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
fs/nfsd/nfs4state.c +8 -5
@@ -6350,7 +6350,6 @@ nfs4_open_delegation(struct svc_rqst *rq } open->op_delegate_type = deleg_ts ?OPEN_DELEGATE_WRITE_ATTRS_DELEG :OPEN_DELEGATE_WRITE ; - dp->dl_cb_fattr.ncf_cur_fsize = stat.size; dp->dl_cb_fattr.ncf_initial_cinfo =nfsd4_change_attribute (&stat); dp->dl_atime = stat.atime; dp->dl_ctime = stat.ctime;
@@ -9396,11 +9395,15 @@ nfsd4_deleg_getattr_conflict(struct svc_if (status != nfserr_jukebox || !nfsd_wait_for_delegreturn (rqstp, inode)) goto out_status; + status = nfs_ok; + goto out_status; + } +if (!ncf->ncf_file_modified) { +if (ncf->ncf_initial_cinfo != ncf->ncf_cb_change) + ncf->ncf_file_modified = true; +else if (i_size_read (inode) != ncf->ncf_cb_fsize) + ncf->ncf_file_modified = true; } -if (!ncf->ncf_file_modified && - (ncf->ncf_initial_cinfo != ncf->ncf_cb_change || - ncf->ncf_cur_fsize != ncf->ncf_cb_fsize)) - ncf->ncf_file_modified = true;if (ncf->ncf_file_modified) {int err;
Greg Kroah-Hartman
maintainerPATCH 928/957 irqchip/riscv-imsic: Clear interrupt move state during CPU offlining
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yong-Xuan Wang <[email protected]>
commit cefafbd561402b0fe6447449364a30315b9b1570 upstream.
Affinity changes of IMSIC interrupts have to be careful to not lose an interrupt in the process. Each vector keeps track of an affinity change in progress with two pointers in struct imsic_vector.
imsic_vector::move_prev points to the previous CPU target data and imsic_vector::move_next to the designated new CPU target data.
imsic_vector::move_prev on the new CPU can only be cleared after the previous CPU has cleared imsic_vector::move_next, which ususally happens in __imsic_remote_sync().
In case of CPU hot-unplug __imsic_remote_sync() is not invoked because the CPU is already marked offline. That means imsic_vector::move_prev becomes stale until the CPU is onlined again.
The stale pointer prevents further affinity changes for the affected interrupts.
Solve this by clearing the imsic_vector::move_prev pointers in the CPU hotplug offline path.
[ tglx: Replace word salad in change log ]
--- drivers/irqchip/irq-riscv-imsic-early.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/irqchip/irq-riscv-imsic-early.c +2 -0
@@ -163,6 +163,8 @@ static int imsic_dying_cpu(unsigned int/* Cleanup IPIs */ imsic_ipi_dying_cpu (); +imsic_local_sync_all (false); +/* Mark per-CPU IMSIC state as offline */ imsic_state_offline ();
Greg Kroah-Hartman
maintainerPATCH 929/957 irqchip/meson-gpio: Use the correct register in meson_s4_gpio_irq_set_type()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xianwei Zhao <[email protected]>
commit 5363b67ac8ebcc3e227dbf59fc8061949109841d upstream.
meson_s4_gpio_irq_set_type() uses the both-edge trigger register for configuring level type and single edge mode interrupts, which is not correct.
Use REG_EDGE_POL instead.
--- drivers/irqchip/irq-meson-gpio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/irqchip/irq-meson-gpio.c +1 -2
@@ -404,8 +404,7 @@ static int meson_s4_gpio_irq_set_type(stif (type & (IRQ_TYPE_EDGE_RISING |IRQ_TYPE_EDGE_FALLING )) val |=BIT (ctl->params->edge_single_offset + idx); -meson_gpio_irq_update_bits (ctl, params->edge_pol_reg, -BIT (idx) |BIT (12 + idx), val); +meson_gpio_irq_update_bits (ctl,REG_EDGE_POL ,BIT (idx) |BIT (12 + idx), val);return 0 ; };
Greg Kroah-Hartman
maintainerPATCH 930/957 irqchip/gic-v5: Move LPI allocation into the LPI domain
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sascha Bischoff <[email protected]>
commit dec85d2fbd20de3711a71e65397dfdb40c3fa953 upstream.
The IPI and ITS MSI domains currently allocate and release LPIs directly, then pass the selected LPI ID to the parent LPI domain. This leaks the LPI domain's allocation policy into its child domains and forces each child to duplicate part of the parent domain's teardown.
Make the LPI domain allocate LPIs in its .alloc() callback and release them in a matching .free() callback. Child domains can then request a parent interrupt without passing an implementation-specific LPI ID, and the LPI lifetime is tied to the domain that owns the LPI namespace.
Remove the gicv5_alloc_lpi() and gicv5_free_lpi() wrappers now that no external caller needs to manage LPIs directly.
This is a preparatory change for an actual leakage problem in the allocation code and therefore tagged with the same Fixes tag.
--- drivers/irqchip/irq-gic-v5-its.c | 14 +-------- drivers/irqchip/irq-gic-v5.c | 53 ++++++++++++++++++------------------- include/linux/irqchip/arm-gic-v5.h | 3 -- 3 files changed, 28 insertions(+), 42 deletions(-)
drivers/irqchip/irq-gic-v5-its.c +2 -12
@@ -927,8 +927,8 @@ static void gicv5_its_free_eventid(strucstatic int gicv5_its_irq_domain_alloc (struct irq_domain *domain,unsigned int virq,unsigned int nr_irqs,void *arg) { -u32 device_id, event_id_base, lpi;struct gicv5_its_dev *its_dev; +u32 device_id, event_id_base;msi_alloc_info_t *info = arg;irq_hw_number_t hwirq;struct irq_data *irqd;
@@ -947,16 +947,8 @@ static int gicv5_its_irq_domain_alloc(st device_id = its_dev->device_id;for (i =0 ; i < nr_irqs; i++) { - ret =gicv5_alloc_lpi (); -if (ret <0 ) { -pr_debug ("Failed to find free LPI!\n" ); - goto out_free_irqs; - } - lpi = ret; - - ret =irq_domain_alloc_irqs_parent (domain, virq + i,1 , &lpi); + ret =irq_domain_alloc_irqs_parent (domain, virq + i,1 ,NULL );if (ret) { -gicv5_free_lpi (lpi); goto out_free_irqs; }
@@ -981,7 +973,6 @@ static int gicv5_its_irq_domain_alloc(st out_free_irqs:while (--i >=0 ) { irqd =irq_domain_get_irq_data (domain, virq + i); -gicv5_free_lpi (irqd->parent_data->hwirq);irq_domain_reset_irq_data (irqd);irq_domain_free_irqs_parent (domain, virq + i,1 ); }
@@ -1011,7 +1002,6 @@ static void gicv5_its_irq_domain_free(stfor (i =0 ; i < nr_irqs; i++) { d =irq_domain_get_irq_data (domain, virq + i); -gicv5_free_lpi (d->parent_data->hwirq);irq_domain_reset_irq_data (d);irq_domain_free_irqs_parent (domain, virq + i,1 ); }
drivers/irqchip/irq-gic-v5.c +26 -27
104 lines not on this page · raw message
include/linux/irqchip/arm-gic-v5.h +0 -3
@@ -387,8 +387,5 @@ struct gicv5_its_itt_cfg {void gicv5_init_lpis (u32 max);void gicv5_deinit_lpis (void ); -int gicv5_alloc_lpi (void ); -void gicv5_free_lpi (u32 lpi); -void __init gicv5_its_of_probe (struct device_node *parent);#endif
Greg Kroah-Hartman
maintainerPATCH 931/957 irqchip/gic-v5: Support range allocation for LPIs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sascha Bischoff <[email protected]>
commit eb6f6d523813ead9dc2799194a2839d42c049734 upstream.
The per-IPI parent allocation loop returns immediately on failure and leaks any parent interrupts allocated by earlier iterations.
The GICv5 LPI domain now owns LPI allocation and teardown internally, but its irq_domain callbacks still reject requests where nr_irqs is greater than one. This forces child domains to allocate and free LPIs one at a time even when the interrupt core requests a contiguous range.
Handle multi-interrupt allocation and teardown in the LPI domain by iterating over the requested range and unwinding any partially allocated state on failure.
Allocate the parent LPIs for the IPI domain with a single range request as well, which cures the leakage problem.
--- drivers/irqchip/irq-gic-v5.c | 77 +++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 35 deletions(-)
drivers/irqchip/irq-gic-v5.c +42 -35
@@ -746,15 +746,14 @@ static void gicv5_irq_lpi_domain_free(st {struct irq_data *d; -if (WARN_ON_ONCE (nr_irqs !=1 )) -return ; +for (unsigned int i =0 ; i < nr_irqs; i++, virq++) { + d =irq_domain_get_irq_data (domain, virq); - d =irq_domain_get_irq_data (domain, virq); +release_lpi (d->hwirq); -release_lpi (d->hwirq); - -irq_set_handler (virq,NULL ); -irq_domain_reset_irq_data (d); +irq_set_handler (virq,NULL ); +irq_domain_reset_irq_data (d); + } } static int gicv5_irq_lpi_domain_alloc(struct irq_domain *domain, unsigned int virq,
@@ -762,32 +761,39 @@ static int gicv5_irq_lpi_domain_alloc(st {irq_hw_number_t hwirq;struct irq_data *irqd; +unsigned int i;int ret; -if (WARN_ON_ONCE (nr_irqs !=1 )) -return -EINVAL ; - - ret =alloc_lpi (); -if (ret <0 ) -return ret; - hwirq = ret; +for (i =0 ; i < nr_irqs; i++) { + ret =alloc_lpi (); +if (ret <0 ) + goto out_free_lpis; + hwirq = ret; + + ret =gicv5_irs_iste_alloc (hwirq); +if (ret <0 ) { +/* Undo partial state first, then clean up the rest */ +release_lpi (hwirq); + goto out_free_lpis; + } - irqd =irq_domain_get_irq_data (domain, virq); + irqd =irq_domain_get_irq_data (domain, virq + i); -irq_domain_set_info (domain, virq, hwirq, &gicv5_lpi_irq_chip,NULL , - handle_fasteoi_irq,NULL ,NULL ); -irqd_set_single_target (irqd); +irq_domain_set_info (domain, virq + i, hwirq, &gicv5_lpi_irq_chip, +NULL , handle_fasteoi_irq,NULL ,NULL ); +irqd_set_single_target (irqd); - ret =gicv5_irs_iste_alloc (hwirq); -if (ret <0 ) { -release_lpi (hwirq); -return ret; +gicv5_hwirq_init (hwirq,GICV5_IRQ_PRI_MI ,GICV5_HWIRQ_TYPE_LPI ); +gicv5_lpi_config_reset (irqd); } -gicv5_hwirq_init (hwirq,GICV5_IRQ_PRI_MI ,GICV5_HWIRQ_TYPE_LPI ); -gicv5_lpi_config_reset (irqd); -return 0 ; + +out_free_lpis: +if (i) +gicv5_irq_lpi_domain_free (domain, virq, i); + +return ret; }static const struct irq_domain_ops gicv5_irq_lpi_domain_ops = {
@@ -813,21 +819,21 @@ static int gicv5_irq_ipi_domain_alloc(st unsigned int nr_irqs, void *arg) { struct irq_data *irqd; -int ret, i; +int ret; -for (i =0 ; i < nr_irqs; i++) { - ret =irq_domain_alloc_irqs_parent (domain, virq + i,1 ,NULL ); -if (ret) -return ret; + ret =irq_domain_alloc_irqs_parent (domain, virq, nr_irqs, arg); +if (ret) +return ret; - irqd =irq_domain_get_irq_data (domain, virq + i); +for (unsigned int i =0 ; i < nr_irqs; i++, virq++) { + irqd =irq_domain_get_irq_data (domain, virq); -irq_domain_set_hwirq_and_chip (domain, virq + i, i, - &gicv5_ipi_irq_chip,NULL ); +irq_domain_set_hwirq_and_chip (domain, virq, i, + &gicv5_ipi_irq_chip,NULL );irqd_set_single_target (irqd); -irq_set_handler (virq + i, handle_percpu_irq); +irq_set_handler (virq, handle_percpu_irq); }return 0 ;
@@ -847,8 +853,9 @@ static void gicv5_irq_ipi_domain_free(stirq_set_handler (virq + i,NULL );irq_domain_reset_irq_data (d); -irq_domain_free_irqs_parent (domain, virq + i,1 ); } + +irq_domain_free_irqs_parent (domain, virq, nr_irqs); }static const struct irq_domain_ops gicv5_irq_ipi_domain_ops = {
Greg Kroah-Hartman
maintainerPATCH 932/957 irqchip/gic-v5: Allocate ITS parent LPIs as a range
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sascha Bischoff <[email protected]>
commit a7c7e42654b6a8676610ee09d22901432c4851af upstream.
The ITS MSI domain no longer manages LPI allocation directly. LPIs are allocated and freed by the parent LPI domain, which can now handle a full range of interrupts and unwind partial allocations internally.
Make the ITS domain request and release the parent IRQs as a single range instead of iterating over each interrupt. The ITS allocation path then only needs to reserve EventIDs, allocate the parent range, and fill in the ITS irq_data for each MSI. Since no operation in the per-MSI loop can fail, the partial parent-free unwind becomes unnecessary.
On teardown, reset the ITS irq_data for the range and then release the parent range in one call, leaving LPI teardown to the LPI domain.
--- drivers/irqchip/irq-gic-v5-its.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-)
drivers/irqchip/irq-gic-v5-its.c +7 -15
@@ -935,6 +935,7 @@ static int gicv5_its_irq_domain_alloc(stint ret, i; its_dev = info->scratchpad[0 ].ptr; + device_id = its_dev->device_id; ret =gicv5_its_alloc_eventid (its_dev, info, nr_irqs, &event_id_base);if (ret)
@@ -944,14 +945,11 @@ static int gicv5_its_irq_domain_alloc(stif (ret) goto out_eventid; - device_id = its_dev->device_id; + ret =irq_domain_alloc_irqs_parent (domain, virq, nr_irqs,NULL ); +if (ret) + goto out_eventid;for (i =0 ; i < nr_irqs; i++) { - ret =irq_domain_alloc_irqs_parent (domain, virq + i,1 ,NULL ); -if (ret) { - goto out_free_irqs; - } -/* * Store eventid and deviceid into the hwirq for later use. *
@@ -970,12 +968,6 @@ static int gicv5_its_irq_domain_alloc(streturn 0 ; -out_free_irqs: -while (--i >=0 ) { - irqd =irq_domain_get_irq_data (domain, virq + i); -irq_domain_reset_irq_data (irqd); -irq_domain_free_irqs_parent (domain, virq + i,1 ); - } out_eventid:gicv5_its_free_eventid (its_dev, event_id_base, nr_irqs);return ret;
@@ -998,14 +990,14 @@ static void gicv5_its_irq_domain_free(stbitmap_release_region (its_dev->event_map, event_id_base,get_count_order (nr_irqs)); -/* Hierarchically free irq data */ for (i =0 ; i < nr_irqs; i++) { d =irq_domain_get_irq_data (domain, virq + i); -irq_domain_reset_irq_data (d); -irq_domain_free_irqs_parent (domain, virq + i,1 ); } +/* Hierarchically free irq data */ +irq_domain_free_irqs_parent (domain, virq, nr_irqs); +gicv5_its_syncr (its, its_dev);gicv5_irs_syncr (); }
Greg Kroah-Hartman
maintainerPATCH 933/957 libceph: Fix potential out-of-bounds access in osdmap_decode()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raphael Zimmer <[email protected]>
commit 35d0ed82d03e5ee77ea4f31f20e29562a7721649 upstream.
When decoding osd_state and osd_weight from an incoming osdmap in osdmap_decode(), both are decoded for each osd, i.e., map->max_osd times. The ceph_decode_need() check only accounts for sizeof(*map->osd_weight) once. This can potentially result in an out-of-bounds memory access if the incoming message is corrupted such that the max_osd value exceeds the actual content of the osdmap message.
This patch fixes the issue by changing the corresponding part in the ceph_decode_need() check to account for map->max_osd*sizeof(*map->osd_weight).
--- net/ceph/osdmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ceph/osdmap.c +1 -1
@@ -1703,7 +1703,7 @@ static int osdmap_decode(void **p, voidceph_decode_need (p, end,3 *sizeof (u32) + map->max_osd*(struct_v >=5 ?sizeof (u32) :sizeof (u8)) + -sizeof (*map->osd_weight), e_inval); + map->max_osd*sizeof (*map->osd_weight), e_inval);if (ceph_decode_32 (p) != map->max_osd) goto e_inval;
Greg Kroah-Hartman
maintainerPATCH 934/957 libceph: Fix potential null-ptr-deref in decode_choose_args()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raphael Zimmer <[email protected]>
commit 28b0a2ab8c82d0bbdeb8013029c67c978ce6e4bf upstream.
A message of type CEPH_MSG_OSD_MAP contains an OSD map that itself contains a CRUSH map. When decoding this CRUSH map in crush_decode(), an array of max_buckets CRUSH buckets is decoded, where some indices may not refer to actual buckets and are therefore set to NULL. The received CRUSH map may optionally contain choose_args that get decoded in decode_choose_args(). When decoding a crush_choose_arg_map, a series of choose_args for different buckets is decoded, with the bucket_index being read from the incoming message. It is only checked that the bucket index does not exceed max_buckets, but not that it doesn't point to an index with a NULL bucket. If a (potentially corrupted) message contains a crush_choose_arg_map including such a bucket_index, a null pointer dereference may occur in the subsequent processing when attempting to access the bucket with the given index.
This patch fixes the issue by extending the affected check. Now, it is only attempted to access the bucket if it is not NULL.
--- net/ceph/osdmap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/ceph/osdmap.c +2 -1
@@ -390,7 +390,8 @@ static int decode_choose_args(void **p, goto fail;if (arg->ids_size && - arg->ids_size != c->buckets[bucket_index]->size) + (!c->buckets[bucket_index] || + arg->ids_size != c->buckets[bucket_index]->size)) goto e_inval; }
Greg Kroah-Hartman
maintainerPATCH 935/957 libceph: Fix potential out-of-bounds access in crush_decode()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raphael Zimmer <[email protected]>
commit 4c79fc2d598694bda845b46229c9d48b65042970 upstream.
A message of type CEPH_MSG_OSD_MAP containing a crush map with at least one bucket has two fields holding the bucket algorithm. If the values in these two fields differ, an out-of-bounds access can occur. This is the case because the first algorithm field (alg) is used to allocate the correct amount of memory for a bucket of this type, while the second algorithm field inside the bucket (b->alg) is used in the subsequent processing.
This patch fixes the issue by adding a check that compares alg and b->alg and aborts the processing in case they differ. Furthermore, b->alg is set to 0 in this case, because the destruction of the crush map also uses this field to determine the bucket type, which can again result in an out-of-bounds access when trying to free the memory pointed to by the fields of the bucket. To correctly free the memory allocated for the bucket in such a case, the corresponding call to kfree is moved from the algorithm-specific crush_destroy_bucket functions to the generic crush_destroy_bucket().
--- net/ceph/crush/crush.c | 6 +----- net/ceph/osdmap.c | 4 ++++ 2 files changed, 5 insertions(+), 5 deletions(-)
net/ceph/crush/crush.c +1 -5
@@ -47,7 +47,6 @@ int crush_get_bucket_item_weight(const svoid crush_destroy_bucket_uniform (struct crush_bucket_uniform *b) {kfree (b->h.items); -kfree (b); }void crush_destroy_bucket_list (struct crush_bucket_list *b)
@@ -55,14 +54,12 @@ void crush_destroy_bucket_list(struct crkfree (b->item_weights);kfree (b->sum_weights);kfree (b->h.items); -kfree (b); }void crush_destroy_bucket_tree (struct crush_bucket_tree *b) {kfree (b->h.items);kfree (b->node_weights); -kfree (b); }void crush_destroy_bucket_straw (struct crush_bucket_straw *b)
@@ -70,14 +67,12 @@ void crush_destroy_bucket_straw(struct ckfree (b->straws);kfree (b->item_weights);kfree (b->h.items); -kfree (b); }void crush_destroy_bucket_straw2 (struct crush_bucket_straw2 *b) {kfree (b->item_weights);kfree (b->h.items); -kfree (b); }void crush_destroy_bucket (struct crush_bucket *b)
@@ -99,6 +94,7 @@ void crush_destroy_bucket(struct crush_bcrush_destroy_bucket_straw2 ((struct crush_bucket_straw2 *)b);break ; } +kfree (b); }/**
net/ceph/osdmap.c +4 -0
@@ -518,6 +518,10 @@ static struct crush_map *crush_decode(vo b->id =ceph_decode_32 (p); b->type =ceph_decode_16 (p); b->alg =ceph_decode_8 (p); +if (b->alg != alg) { + b->alg =0 ; + goto bad; + } b->hash =ceph_decode_8 (p); b->weight =ceph_decode_32 (p); b->size =ceph_decode_32 (p);
Greg Kroah-Hartman
maintainerPATCH 936/957 libceph: handle rbtree insertion error in decode_choose_args()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raphael Zimmer <[email protected]>
commit d289478cfc0bcf81c7914200d6abdcb78bd04ded upstream.
A message of type CEPH_MSG_OSD_MAP contains an OSD map that itself contains a CRUSH map. The received CRUSH map may optionally contain choose_args that get decoded in decode_choose_args(). In this function, num_choose_arg_maps is read from the message, and a corresponding number of crush_choose_arg_maps gets decoded afterwards. Each crush_choose_arg_map has a choose_args_index, which serves as the key when inserting it into the choose_args rbtree of the decoded crush_map. If a (potentially corrupted) message contains two crush_choose_arg_maps with the same index, the assertion in insert_choose_arg_map() triggers a kernel BUG when trying to insert the second crush_choose_arg_map.
This patch fixes the issue by switching to the non-asserting rbtree insertion function and rejecting the message if the insertion fails.
[ idryomov: changelog ]
--- net/ceph/osdmap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/ceph/osdmap.c +4 -1
@@ -395,7 +395,10 @@ static int decode_choose_args(void **p, goto e_inval; } -insert_choose_arg_map (&c->choose_args, arg_map); +if (!__insert_choose_arg_map (&c->choose_args, arg_map)) { + ret = -EEXIST ; + goto fail; + } }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 937/957 iommu/vt-d: Disable DMAR for Intel Q35 IGFX
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Naval Alcalá <[email protected]>
commit 2cda2e10dc8343ae01eae9e999a876b7e7d37861 upstream.
Intel Q35 integrated graphics (8086:29b2) exhibits broken DMAR behaviour similar to other G4x/GM45 devices for which DMAR is already disabled via quirks.
When DMAR is enabled, the system may hard lock up during boot or early device initialization, requiring a reset.
Add the missing PCI ID to the existing quirk list to disable DMAR for this device.
--- drivers/iommu/intel/iommu.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/iommu/intel/iommu.c +3 -0
@@ -4517,6 +4517,9 @@ static void quirk_iommu_igfx(struct pci_ disable_igfx_iommu =1 ; } +/* Q35 integrated gfx dmar support is totally busted. */ +DECLARE_PCI_FIXUP_HEADER (PCI_VENDOR_ID_INTEL ,0x29b2 , quirk_iommu_igfx); +/* G4x/GM45 integrated gfx dmar support is totally busted. */ DECLARE_PCI_FIXUP_HEADER (PCI_VENDOR_ID_INTEL ,0x2a40 , quirk_iommu_igfx);DECLARE_PCI_FIXUP_HEADER (PCI_VENDOR_ID_INTEL ,0x2e00 , quirk_iommu_igfx);
Greg Kroah-Hartman
maintainerPATCH 938/957 iommu/vt-d: Fix oops due to out of scope access
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhenzhong Duan <[email protected]>
commit a6dea58d8625c06b9654c0555f101742481335c3 upstream.
Below oops triggers when kill QEMU process:
Oops: general protection fault, probably for non-canonical address 0x7fffffff844eaaa7: 0000 [#1] SMP NOPTI Call Trace: <TASK> do_raw_spin_lock+0xaa/0xc0 _raw_spin_lock_irqsave+0x21/0x40 domain_remove_dev_pasid+0x52/0x160 intel_nested_set_dev_pasid+0x1b9/0x1e0 __iommu_set_group_pasid+0x56/0x120 pci_dev_reset_iommu_done+0xe3/0x180 pcie_flr+0x65/0x160 __pci_reset_function_locked+0x5b/0x120 vfio_pci_core_close_device+0x63/0xe0 [vfio_pci_core] vfio_df_close+0x4f/0xa0 vfio_df_unbind_iommufd+0x2d/0x60 vfio_device_fops_release+0x3e/0x40 __fput+0xe5/0x2c0 task_work_run+0x58/0xa0 do_exit+0x2c8/0x600 do_group_exit+0x2f/0xa0 get_signal+0x863/0x8c0 arch_do_signal_or_restart+0x24/0x100 exit_to_user_mode_loop+0x87/0x380 do_syscall_64+0x2ff/0x11e0 entry_SYSCALL_64_after_hwframe+0x76/0x7e
The global static blocked domain is a dummy domain without corresponding dmar_domain structure, accessing beyond iommu_domain structure triggers oops easily. Fix it by return early in domain_remove_dev_pasid() like identity domain.
--- drivers/iommu/intel/iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iommu/intel/iommu.c +2 -2
@@ -4068,8 +4068,8 @@ void domain_remove_dev_pasid(struct iommif (!domain)return ; -/* Identity domain has no meta data for pasid. */ -if (domain->type ==IOMMU_DOMAIN_IDENTITY ) +/* Identity domain and blocked domain have no meta data for pasid. */ +if (domain->type ==IOMMU_DOMAIN_IDENTITY || domain->type ==IOMMU_DOMAIN_BLOCKED )return ; dmar_domain =to_dmar_domain (domain);
Greg Kroah-Hartman
maintainerPATCH 939/957 iommu/vt-d: Avoid NULL pointer dereference or refcount corruption
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhenzhong Duan <[email protected]>
commit 79ea2feb917b05366b49d85573c9c5331f043b2c upstream.
Commit 60f030f7418d ("iommu/vt-d: Avoid use of NULL after WARN_ON_ONCE") fixed a NULL pointer dereference in an unlikely situation partly.
If dev_pasid is not found in the dev_pasids list, it remains NULL. However, the teardown operations are executed unconditionally, this lead to a NULL pointer dereference or refcount corruption.
If the domain was never attached to this IOMMU, info will be NULL, which would cause an immediate dereference when checking --info->refcnt.
Even if info is not NULL, decrementing the refcount without having removed a valid PASID might unbalance the count. This could lead to premature dropping of the refcount to 0, potentially causing a use-after-free for the remaining active devices sharing the domain.
Fix it by returning early if dev_pasid is NULL, before executing the teardown operations.
Issue found by AI review and suggested by Kevin Tian.
https://sashiko.dev/#/patchset/20260421031347.1408890-1-zhenzhong.duan%40intel.com
--- drivers/iommu/intel/iommu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/iommu/intel/iommu.c +5 -4
@@ -4083,12 +4083,13 @@ void domain_remove_dev_pasid(struct iomm }spin_unlock_irqrestore (&dmar_domain->lock, flags); +if (WARN_ON_ONCE (!dev_pasid)) +return ; +cache_tag_unassign_domain (dmar_domain, dev, pasid);domain_detach_iommu (dmar_domain, iommu); -if (!WARN_ON_ONCE (!dev_pasid)) { -intel_iommu_debugfs_remove_dev_pasid (dev_pasid); -kfree (dev_pasid); - } +intel_iommu_debugfs_remove_dev_pasid (dev_pasid); +kfree (dev_pasid); } static int blocking_domain_set_dev_pasid(struct iommu_domain *domain,
Greg Kroah-Hartman
maintainerPATCH 940/957 drm/i915: skip __i915_request_skip() for already signaled requests
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Brzezinka <[email protected]>
commit 4cfe4c0efbdcde742a47813180cc69b132d7598e upstream.
After a GPU reset the HWSP is zeroed, so previously completed requests appear incomplete. If such a request is picked up during reset_rewind() and marked guilty, i915_request_set_error_once() returns early (fence already signaled), leaving fence.error without a fatal error code. The subsequent __i915_request_skip() then hits:
``` GEM_BUG_ON(!fatal_error(rq->fence.error)) ```
Fixes a kernel BUG observed on Sandy Bridge (Gen6) during heartbeat-triggered engine resets.
``` kernel BUG at drivers/gpu/drm/i915/i915_request.c:556! RIP: __i915_request_skip+0x15e/0x1d0 [i915] ... __i915_request_reset+0x212/0xa70 [i915] reset_rewind+0xe4/0x280 [i915] intel_gt_reset+0x30d/0x5b0 [i915] heartbeat+0x516/0x530 [i915] ```
Guard __i915_request_skip() with i915_request_signaled(), if the fence is already signaled, the ring content is committed and there is nothing left to skip.
--- drivers/gpu/drm/i915/gt/intel_reset.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/gt/intel_reset.c +2 -1
@@ -132,7 +132,8 @@ void __i915_request_reset(struct i915_rercu_read_lock ();/* protect the GEM context */ if (guilty) {i915_request_set_error_once (rq, -EIO ); -__i915_request_skip (rq); +if (!i915_request_signaled (rq)) +__i915_request_skip (rq); banned =mark_guilty (rq); }else {i915_request_set_error_once (rq, -EAGAIN );
Greg Kroah-Hartman
maintainerPATCH 941/957 drm/panfrost: Fix wait_bo ioctl leaking positive return from dma_resv_wait_timeout()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gyeyoung Baek <[email protected]>
commit 459d75523b71c0ec254d153d8850d0b7008af396 upstream.
dma_resv_wait_timeout() returns a positive 'remaining jiffies' value on success, 0 on timeout, and -errno on failure.
panfrost_ioctl_wait_bo() returns this 'long' result from an int-typed ioctl handler, so positive values reach userspace as bogus errors. Explicitly set ret to 0 on the success path.
--- drivers/gpu/drm/panfrost/panfrost_drv.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/panfrost/panfrost_drv.c +2 -0
@@ -365,6 +365,8 @@ panfrost_ioctl_wait_bo(struct drm_device true, timeout);if (!ret) ret = timeout ? -ETIMEDOUT : -EBUSY ; +else if (ret >0 ) + ret =0 ;drm_gem_object_put (gem_obj);
Greg Kroah-Hartman
maintainerPATCH 942/957 drm/xe/dma-buf: handle empty bo and UAF races
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Auld <[email protected]>
commit 981bedbbe61364fcc3a3b87ebaf648a66cd07108 upstream.
There look to be some nasty races here when triggering the invalidate_mappings hook:
1) We do xe_bo_alloc() followed by the attach, before the actual full bo init step in xe_dma_buf_init_obj(). However the bo is visible on the attachments list after the attach. This is bad since exporter driver, say amdgpu, can at any time call back into our invalidate_mappings hook, with an empty/bogus bo, leading to potential bugs/crashes.
2) Similar to 1) but here we get a UAF, when the invalidate_mappings hook is triggered. For example, we get as far as xe_bo_init_locked() but this fails in some way. But here the bo will be freed on error, but we still have it attached from dma-buf pov, so if the invalidate_mappings is now triggered then the bo we access is gone and we trigger UAF and more bugs/crashes.
To fix this, move the attach step until after we actually have a fully set up buffer object. Note that the bo is not published to userspace until later, so not sure what the comment "Don't publish the bo until we have a valid attachment", is referring to.
We have at least two different customers reporting hitting a NULL ptr deref in evict_flags when importing something from amdgpu, followed by triggering the evict flow. Hit rate is also pretty low, which would hint at some kind of race, so something like 1) or 2) might explain this.
v2:
- Shuffle the order of the ops slightly (no functional change)
- Improve the comment to better explain the ordering (Matt B)
--- drivers/gpu/drm/xe/xe_dma_buf.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-)
drivers/gpu/drm/xe/xe_dma_buf.c +16 -15
@@ -326,15 +326,25 @@ struct drm_gem_object *xe_gem_prime_impo } } -/* -* Don't publish the bo until we have a valid attachment, and a -* valid attachment needs the bo address. So pre-create a bo before -* creating the attachment and publish. -*/ bo =xe_bo_alloc ();if (IS_ERR (bo))return ERR_CAST (bo); +/* +* xe_dma_buf_init_obj() takes ownership of the raw bo, so do not touch +* on fail, since it will already take care of cleanup. On success we +* still need to drop the ref, if something later fails. +* +* In addition this needs to happen before the attach, since +* it will create a new attachment for this, and add it to the list of +* attachments, at which point it is globally visible, and at any point +* the export side can call into on invalidate_mappings callback, which +* require a working object. +*/ + obj =xe_dma_buf_init_obj (dev, bo, dma_buf); +if (IS_ERR (obj)) +return obj; + attach_ops = &xe_dma_buf_attach_ops;#if IS_ENABLED (CONFIG_DRM_XE_KUNIT_TEST )if (test)
@@ -347,21 +357,12 @@ struct drm_gem_object *xe_gem_prime_impo goto out_err; } -/* -* xe_dma_buf_init_obj() takes ownership of bo on both success -* and failure, so we must not touch bo after this call. -*/ - obj =xe_dma_buf_init_obj (dev, bo, dma_buf); -if (IS_ERR (obj)) { -dma_buf_detach (dma_buf, attach); -return obj; - }get_dma_buf (dma_buf); obj->import_attach = attach;return obj; out_err: -xe_bo_free (bo); +xe_bo_put (bo);return obj; }
Greg Kroah-Hartman
maintainerPATCH 943/957 drm/xe/dma-buf: fix UAF with retry loop
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Auld <[email protected]>
commit 155a372a1cc50fa93387c5d3cdfd614a61e1afd1 upstream.
Retry doesn't work here, since bo will be freed on error, leading to UAF. However, now that we do the alloc & init before the attach, we can now combine this as one unit and have the init do the alloc for us. This should make the retry safe.
Reported by Sashiko.
v2: Fix up the error unwind (CI)
--- drivers/gpu/drm/xe/xe_dma_buf.c | 49 +++++++++------------------------------- 1 file changed, 12 insertions(+), 37 deletions(-)
drivers/gpu/drm/xe/xe_dma_buf.c +12 -37
@@ -227,16 +227,8 @@ struct dma_buf *xe_gem_prime_export(strureturn buf; } -/* -* Takes ownership of @storage: on success it is transferred to the returned -* drm_gem_object; on failure it is freed before returning the error. -* This matches the contract of xe_bo_init_locked() which frees @storage on -* its error paths, so callers need not (and must not) free @storage after -* this call. -*/ static struct drm_gem_object * -xe_dma_buf_init_obj (struct drm_device *dev,struct xe_bo *storage, -struct dma_buf *dma_buf) +xe_dma_buf_create_obj (struct drm_device *dev,struct dma_buf *dma_buf) {struct dma_resv *resv = dma_buf->resv;struct xe_device *xe =to_xe_device (dev);
@@ -247,10 +239,8 @@ xe_dma_buf_init_obj(struct drm_device *dint ret =0 ; dummy_obj =drm_gpuvm_resv_object_alloc (&xe->drm); -if (!dummy_obj) { -xe_bo_free (storage); +if (!dummy_obj)return ERR_PTR (-ENOMEM ); - } dummy_obj->resv = resv; xe_validation_guard(&ctx, &xe->val, &exec, (struct xe_val_flags) {}, ret) {
@@ -259,8 +249,7 @@ xe_dma_buf_init_obj(struct drm_device *dif (ret)break ; -/* xe_bo_init_locked() frees storage on error */ - bo =xe_bo_init_locked (xe, storage,NULL , resv,NULL , dma_buf->size, + bo =xe_bo_init_locked (xe,NULL ,NULL , resv,NULL , dma_buf->size,0 ,/* Will require 1way or 2way for vm_bind */ ttm_bo_type_sg,XE_BO_FLAG_SYSTEM , &exec);drm_exec_retry_on_contention (&exec);
@@ -311,7 +300,6 @@ struct drm_gem_object *xe_gem_prime_impoconst struct dma_buf_attach_ops *attach_ops;struct dma_buf_attachment *attach;struct drm_gem_object *obj; -struct xe_bo *bo;if (dma_buf->ops == &xe_dmabuf_ops) { obj = dma_buf->priv;
@@ -326,22 +314,14 @@ struct drm_gem_object *xe_gem_prime_impo } } - bo =xe_bo_alloc (); -if (IS_ERR (bo)) -return ERR_CAST (bo); -/* -* xe_dma_buf_init_obj() takes ownership of the raw bo, so do not touch -* on fail, since it will already take care of cleanup. On success we -* still need to drop the ref, if something later fails. -* -* In addition this needs to happen before the attach, since -* it will create a new attachment for this, and add it to the list of -* attachments, at which point it is globally visible, and at any point -* the export side can call into on invalidate_mappings callback, which -* require a working object. +* This needs to happen before the attach, since it will create a new +* attachment for this, and add it to the list of attachments, at which +* point it is globally visible, and at any point the export side can +* call into on invalidate_mappings callback, which require a working +* object. */ - obj =xe_dma_buf_init_obj (dev, bo, dma_buf); + obj =xe_dma_buf_create_obj (dev, dma_buf);if (IS_ERR (obj))return obj;
@@ -351,20 +331,15 @@ struct drm_gem_object *xe_gem_prime_impo attach_ops = test->attach_ops;#endif - attach =dma_buf_dynamic_attach (dma_buf, dev->dev, attach_ops, &bo->ttm.base); + attach =dma_buf_dynamic_attach (dma_buf, dev->dev, attach_ops, obj);if (IS_ERR (attach)) { - obj =ERR_CAST (attach); - goto out_err; +xe_bo_put (gem_to_xe_bo (obj)); +return ERR_CAST (attach); }get_dma_buf (dma_buf); obj->import_attach = attach;return obj; - -out_err: -xe_bo_put (bo); - -return obj; }#if IS_ENABLED (CONFIG_DRM_XE_KUNIT_TEST )
Greg Kroah-Hartman
maintainerPATCH 944/957 drm/ttm: Convert -EAGAIN from dmem_cgroup_try_charge to -ENOSPC
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Hellström <[email protected]>
commit 591711b32681a04b57d00c2a404658f8419a081c upstream.
dmem_cgroup_try_charge() returns -EAGAIN when the cgroup limit is hit and the charge fails. TTM has no concept of -EAGAIN from resource allocation; -ENOSPC is the canonical error meaning "no space, try eviction". Convert at the source in ttm_resource_alloc() so no caller needs to handle an unexpected error code, and clean up the now-redundant -EAGAIN check in ttm_bo_alloc_resource().
Without this, -EAGAIN escaping ttm_resource_alloc() during an eviction walk causes the walk to terminate early instead of continuing to the next candidate.
--- drivers/gpu/drm/ttm/ttm_bo.c | 2 +- drivers/gpu/drm/ttm/ttm_resource.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-)
drivers/gpu/drm/ttm/ttm_bo.c +1 -1
@@ -739,7 +739,7 @@ static int ttm_bo_alloc_resource(struct may_evict = (force_space && place->mem_type !=TTM_PL_SYSTEM ); ret =ttm_resource_alloc (bo, place, res, force_space ? &limit_pool :NULL );if (ret) { -if (ret != -ENOSPC && ret != -EAGAIN ) { +if (ret != -ENOSPC ) {dmem_cgroup_pool_state_put (limit_pool);return ret; }
drivers/gpu/drm/ttm/ttm_resource.c +4 -1
@@ -384,8 +384,11 @@ int ttm_resource_alloc(struct ttm_bufferif (man->cg) { ret =dmem_cgroup_try_charge (man->cg, bo->base.size, &pool, ret_limit_pool); -if (ret) +if (ret) { +if (ret == -EAGAIN ) + ret = -ENOSPC ;return ret; + } } ret = man->func->alloc (man, bo, place, res_ptr);
Greg Kroah-Hartman
maintainerPATCH 945/957 drm/gma500/oaktrail_hdmi: fix i2c adapter leak on setup
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 950953f774b3f69da6f413e045ef075e1f3da2df upstream.
Make sure to drop the reference taken to the I2C adapter (and its module) when setting up HDMI to allow the adapter to be deregistered.
--- drivers/gpu/drm/gma500/oaktrail_hdmi.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/gma500/oaktrail_hdmi.c +1 -0
@@ -579,6 +579,7 @@ static int oaktrail_hdmi_get_modes(struc }else { edid = (struct edid *)raw_edid;/* FIXME ? edid = drm_get_edid(connector, i2c_adap); */ +i2c_put_adapter (i2c_adap); }if (edid) {
Greg Kroah-Hartman
maintainerPATCH 946/957 drm/gma500/oaktrail_lvds: fix hang on init failure
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 657a091ab6d01d0091b77660c75cfed573c9a53e upstream.
The LVDS init code looks up an I2C adapter using i2c_get_adapter() and tries to read the EDID before falling back to allocating and registering its own adapter.
The error handling does not separate these cases so on a late init failure it will try to deregister and free also an adapter that had previously been registered. Since i2c_get_adapter() takes another reference to the adapter, deregistration hangs indefinitely while waiting for the reference to be released.
Fix this by only destroying adapters allocated during LVDS init on errors.
--- drivers/gpu/drm/gma500/oaktrail_lvds.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/gma500/oaktrail_lvds.c +3 -2
@@ -292,7 +292,7 @@ void oaktrail_lvds_init(struct drm_devic {struct gma_encoder *gma_encoder;struct gma_connector *gma_connector; -struct gma_i2c_chan *ddc_bus; +struct gma_i2c_chan *ddc_bus =NULL ;struct drm_connector *connector;struct drm_encoder *encoder;struct drm_psb_private *dev_priv =to_drm_psb_private (dev);
@@ -420,7 +420,8 @@ out: err_unlock:mutex_unlock (&dev->mode_config.mutex); -gma_i2c_destroy (to_gma_i2c_chan (connector->ddc)); +if (!IS_ERR_OR_NULL (ddc_bus)) +gma_i2c_destroy (ddc_bus);drm_encoder_cleanup (encoder); err_connector_cleanup:drm_connector_cleanup (connector);
Greg Kroah-Hartman
maintainerPATCH 947/957 drm/gma500/oaktrail_lvds: fix i2c adapter leaks on init
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 84d1c9b416d54afe760ca4c378bd95c89261254c upstream.
The LVDS init code looks up an I2C adapter using i2c_get_adapter() and tries to read the EDID before falling back to allocating and registering its own adapter.
Make sure to drop the references taken by i2c_get_adapter() when falling back to allocating an adapter as well as on late errors to allow the looked up adapter to be deregistered.
--- drivers/gpu/drm/gma500/oaktrail_lvds.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/gpu/drm/gma500/oaktrail_lvds.c +4 -0
@@ -366,6 +366,8 @@ void oaktrail_lvds_init(struct drm_devicif (edid ==NULL && dev_priv->lpc_gpio_base) { ddc_bus =oaktrail_lvds_i2c_init (dev);if (!IS_ERR (ddc_bus)) { +if (i2c_adap) +i2c_put_adapter (i2c_adap); i2c_adap = &ddc_bus->base; edid =drm_get_edid (connector, i2c_adap); }
@@ -422,6 +424,8 @@ err_unlock:mutex_unlock (&dev->mode_config.mutex);if (!IS_ERR_OR_NULL (ddc_bus))gma_i2c_destroy (ddc_bus); +else if (i2c_adap) +i2c_put_adapter (i2c_adap);drm_encoder_cleanup (encoder); err_connector_cleanup:drm_connector_cleanup (connector);
Greg Kroah-Hartman
maintainerPATCH 948/957 drm/v3d: Reject empty multisync extension to prevent infinite loop
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Desai <[email protected]>
commit fb44d589bf3148e13452185a6e772a7efbf2d684 upstream.
v3d_get_extensions() walks a userspace-provided singly-linked list of ioctl extensions without any bound on the chain length. A local user can craft a self-referential extension (ext->next == &ext) with zero in_sync_count and out_sync_count, which bypasses the existing duplicate- extension guard:
if (se->in_sync_count || se->out_sync_count)
return -EINVAL;The guard never fires because v3d_get_multisync_post_deps() returns immediately when count is zero, leaving both fields at zero on every iteration. The result is an infinite loop in kernel context, blocking the calling thread and pegging a CPU core indefinitely.
Fix this by rejecting a multisync extension where both in_sync_count and out_sync_count are zero in v3d_get_multisync_submit_deps(). An empty multisync carries no synchronization information and serves no useful purpose, so returning -EINVAL for such an extension is the correct defense against this attack vector.
--- drivers/gpu/drm/v3d/v3d_submit.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/gpu/drm/v3d/v3d_submit.c +5 -0
@@ -390,6 +390,11 @@ v3d_get_multisync_submit_deps(struct drmif (multisync.pad)return -EINVAL ; +if (!multisync.in_sync_count && !multisync.out_sync_count) { +DRM_DEBUG ("Empty multisync extension\n" ); +return -EINVAL ; + } + ret =v3d_get_multisync_post_deps (file_priv, se, multisync.out_sync_count, multisync.out_syncs);if (ret)
Greg Kroah-Hartman
maintainerPATCH 949/957 eventfs: Use list_add_tail_rcu() for SRCU-protected children list
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 f67950b2887fa10df50c4317a1fe98a65bc6875b ]
Commit d2603279c7d6 ("eventfs: Use list_del_rcu() for SRCU protected list variable") converted the removal side to pair with the list_for_each_entry_srcu() walker in eventfs_iterate(). The insertion in eventfs_create_dir() was left as a plain list_add_tail(), which on weakly-ordered architectures can expose a new entry to the SRCU reader before its list pointers and fields are observable.
Use list_add_tail_rcu() so the publication pairs with the existing list_del_rcu() and list_for_each_entry_srcu().
--- fs/tracefs/event_inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/tracefs/event_inode.c +1 -1
@@ -732,7 +732,7 @@ struct eventfs_inode *eventfs_create_dirmutex_lock (&eventfs_mutex);if (!parent->is_freed) -list_add_tail (&ei->list, &parent->children); +list_add_tail_rcu (&ei->list, &parent->children);mutex_unlock (&eventfs_mutex);/* Was the parent freed? */
Greg Kroah-Hartman
maintainerPATCH 950/957 smb: client: Use FullSessionKey for AES-256 encryption key derivation
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Piyush Sachdeva <[email protected]>
[ Upstream commit 5be7a0cef3229fb3b63a07c0d289daf752545424 ]
When Kerberos authentication is used with AES-256 encryption (AES-256-CCM or AES-256-GCM), the SMB3 encryption and decryption keys must be derived using the full session key (Session.FullSessionKey) rather than just the first 16 bytes (Session.SessionKey).
Per MS-SMB2 section 3.2.5.3.1, when Connection.Dialect is "3.1.1" and Connection.CipherId is AES-256-CCM or AES-256-GCM, Session.FullSessionKey must be set to the full cryptographic key from the GSS authentication context. The encryption and decryption key derivation (SMBC2SCipherKey, SMBS2CCipherKey) must use this FullSessionKey as the KDF input. The signing key derivation continues to use Session.SessionKey (first 16 bytes) in all cases.
Previously, generate_key() hardcoded SMB2_NTLMV2_SESSKEY_SIZE (16) as the HMAC-SHA256 key input length for all derivations. When Kerberos with AES-256 provides a 32-byte session key, the KDF for encryption/decryption was using only the first 16 bytes, producing keys that did not match the server's, causing mount failures with sec=krb5 and require_gcm_256=1.
Add a full_key_size parameter to generate_key() and pass the appropriate size from generate_smb3signingkey():
- Signing: always SMB2_NTLMV2_SESSKEY_SIZE (16 bytes)
- Encryption/Decryption: ses->auth_key.len when AES-256, otherwise 16
Also fix cifs_dump_full_key() to report the actual session key length for AES-256 instead of hardcoded CIFS_SESS_KEY_SIZE, so that userspace tools like Wireshark receive the correct key for decryption.
--- fs/smb/client/ioctl.c | 2 +- fs/smb/client/smb2transport.c | 32 +++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-)
fs/smb/client/ioctl.c +1 -1
@@ -297,7 +297,7 @@ search_end:break ;case SMB2_ENCRYPTION_AES256_CCM :case SMB2_ENCRYPTION_AES256_GCM : - out.session_key_length =CIFS_SESS_KEY_SIZE ; + out.session_key_length = ses->auth_key.len; out.server_in_key_length = out.server_out_key_length =SMB3_GCM256_CRYPTKEY_SIZE ;break ;default :
fs/smb/client/smb2transport.c +25 -7
@@ -259,7 +259,8 @@ smb2_calc_signature(struct smb_rqst *rqs }static int generate_key (struct cifs_ses *ses,struct kvec label, -struct kvec context,__u8 *key,unsigned int key_size) +struct kvec context,__u8 *key,unsigned int key_size, +unsigned int full_key_size) {unsigned char zero =0x0 ;__u8 i[4 ] = {0 ,0 ,0 ,1 };
@@ -280,7 +281,7 @@ static int generate_key(struct cifs_ses }hmac_sha256_init_usingrawkey (&hmac_ctx, ses->auth_key.response, -SMB2_NTLMV2_SESSKEY_SIZE ); + full_key_size);hmac_sha256_update (&hmac_ctx, i,4 );hmac_sha256_update (&hmac_ctx, label.iov_base, label.iov_len);hmac_sha256_update (&hmac_ctx, &zero,1 );
@@ -314,6 +315,7 @@ generate_smb3signingkey(struct cifs_sesstruct TCP_Server_Info *server, const struct derivation_triplet *ptriplet) { + unsigned int full_key_size = SMB2_NTLMV2_SESSKEY_SIZE;int rc;bool is_binding = false;int chan_index =0 ;
@@ -348,17 +350,31 @@ generate_smb3signingkey(struct cifs_ses rc =generate_key (ses, ptriplet->signing.label, ptriplet->signing.context, ses->chans[chan_index].signkey, -SMB3_SIGN_KEY_SIZE ); +SMB3_SIGN_KEY_SIZE , +SMB2_NTLMV2_SESSKEY_SIZE );if (rc)return rc; }else { rc =generate_key (ses, ptriplet->signing.label, ptriplet->signing.context, ses->smb3signingkey, -SMB3_SIGN_KEY_SIZE ); +SMB3_SIGN_KEY_SIZE , +SMB2_NTLMV2_SESSKEY_SIZE );if (rc)return rc; +/* +* Per MS-SMB2 3.2.5.3.1, signing key always uses Session.SessionKey +* (first 16 bytes). Encryption/decryption keys use +* Session.FullSessionKey when dialect is 3.1.1 and cipher is +* AES-256-CCM or AES-256-GCM, otherwise Session.SessionKey. +*/ + +if (server->dialect ==SMB311_PROT_ID && + (server->cipher_type ==SMB2_ENCRYPTION_AES256_CCM || + server->cipher_type ==SMB2_ENCRYPTION_AES256_GCM )) + full_key_size = ses->auth_key.len; +/* safe to access primary channel, since it will never go away */ spin_lock (&ses->chan_lock); memcpy(ses->chans[chan_index].signkey, ses->smb3signingkey,
@@ -368,13 +384,15 @@ generate_smb3signingkey(struct cifs_ses rc =generate_key (ses, ptriplet->encryption.label, ptriplet->encryption.context, ses->smb3encryptionkey, -SMB3_ENC_DEC_KEY_SIZE ); +SMB3_ENC_DEC_KEY_SIZE , + full_key_size);if (rc)return rc; rc =generate_key (ses, ptriplet->decryption.label, ptriplet->decryption.context, ses->smb3decryptionkey, -SMB3_ENC_DEC_KEY_SIZE ); +SMB3_ENC_DEC_KEY_SIZE , + full_key_size);if (rc)return rc; }
@@ -389,7 +407,7 @@ generate_smb3signingkey(struct cifs_ses &ses->Suid);cifs_dbg (VFS ,"Cipher type %d\n" , server->cipher_type);cifs_dbg (VFS ,"Session Key %*ph\n" , -SMB2_NTLMV2_SESSKEY_SIZE , ses->auth_key.response); + (int )ses->auth_key.len, ses->auth_key.response);cifs_dbg (VFS ,"Signing Key %*ph\n" ,SMB3_SIGN_KEY_SIZE , ses->smb3signingkey); if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
Greg Kroah-Hartman
maintainerPATCH 951/957 btrfs: do not mark inode incompressible after inline attempt fails
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit 2e0e3716c7b6f8d71df2fbe709b922e54700f71b ]
[BUG]
The following sequence will set the file with nocompress flag:
# mkfs.btrfs -f $dev # mount $dev $mnt -o max_inline=4,compress # xfs_io -f -c "pwrite 0 2k" -c sync $mnt/foobar
The inode will have NOCOMPRESS flag, even if the content itself (all 0xcd) can still be compressed very well:
item 4 key (257 INODE_ITEM 0) itemoff 15879 itemsize 160 generation 9 transid 10 size 2097152 nbytes 1052672 block group 0 mode 100600 links 1 uid 0 gid 0 rdev 0 sequence 257 flags 0x8(NOCOMPRESS)
Please note that, this behavior is there even before commit 59615e2c1f63 ("btrfs: reject single block sized compression early").
[CAUSE]
At compress_file_range(), after btrfs_compress_folios() call, we try making an inlined extent by calling cow_file_range_inline().
But cow_file_range_inline() calls can_cow_file_range_inline() which has more accurate checks on if the range can be inlined.
One of the user configurable conditions is the "max_inline=" mount option. If that value is set low (like the example, 4 bytes, which cannot store any header), or the compressed content is just slightly larger than 2K (the default value, meaning a 50% compression ratio), cow_file_range_inline() will return 1 immediately.
And since we're here only to try inline the compressed data, the range is no larger than a single fs block.
Thus compression is never going to make it a win, we fall back to marking the inode incompressible unavoidably.
[FIX]
Just add an extra check after inline attempt, so that if the inline attempt failed, do not set the nocompress flag.
As there is no way to remove that flag, and the default 50% compression ratio is way too strict for the whole inode.
--- fs/btrfs/inode.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/btrfs/inode.c +6 -0
@@ -1006,6 +1006,12 @@ again:mapping_set_error (mapping, -EIO ); goto free_pages; } +/* +* If a single block at file offset 0 cannot be inlined, fall back to +* regular writes without marking the file incompressible. +*/ +if (start ==0 && end <= blocksize) + goto cleanup_and_bail_uncompressed;/* * We aren't doing an inline extent. Round the compressed size up to a
Greg Kroah-Hartman
maintainerPATCH 952/957 perf/x86/intel: Disable PMI for self-reloaded ACR events
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dapeng Mi <[email protected]>
[ Upstream commit 1271aeccc307066315b2d3b0d5af2510e27018b5 ]
On platforms with Auto Counter Reload (ACR) support, such as NVL, a "NMI received for unknown reason 30" warning is observed when running multiple events in a group with ACR enabled:
$ perf record -e '{instructions/period=20000,acr_mask=0x2/u,\
cycles/period=40000,acr_mask=0x3/u}' ./testThe warning occurs because the Performance Monitoring Interrupt (PMI) is enabled for the self-reloaded event (the cycles event in this case). According to the Intel SDM, the overflow bit (IA32_PERF_GLOBAL_STATUS.PMCn_OVF) is never set for self-reloaded events. Since the bit is not set, the perf NMI handler cannot identify the source of the interrupt, leading to the "unknown reason" message.
Furthermore, enabling PMI for self-reloaded events is unnecessary and can lead to extraneous records that pollute the user's requested data.
Disable the interrupt bit for all events configured with ACR self-reload.
--- arch/x86/events/intel/core.c | 17 +++++++++++++---- arch/x86/events/perf_event.h | 10 ++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-)
arch/x86/events/intel/core.c +13 -4
@@ -2866,11 +2866,11 @@ static void intel_pmu_enable_fixed(strucintel_set_masks (event, idx);/* -* Enable IRQ generation (0x8), if not PEBS, -* and enable ring-3 counting (0x2) and ring-0 counting (0x1) -* if requested: +* Enable IRQ generation (0x8), if not PEBS or self-reloaded +* ACR event, and enable ring-3 counting (0x2) and ring-0 +* counting (0x1) if requested: */ -if (!event->attr.precise_ip) +if (!event->attr.precise_ip && !is_acr_self_reload_event (event)) bits |=INTEL_FIXED_0_ENABLE_PMI ;if (hwc->config &ARCH_PERFMON_EVENTSEL_USR ) bits |=INTEL_FIXED_0_USER ;
@@ -2955,6 +2955,15 @@ static void intel_pmu_enable_event(struc enable_mask |=ARCH_PERFMON_EVENTSEL_BR_CNTR ;intel_set_masks (event, idx);static_call_cond (intel_pmu_enable_acr_event)(event); +/* +* For self-reloaded ACR event, don't enable PMI since +* HW won't set overflow bit in GLOBAL_STATUS. Otherwise, +* the PMI would be recognized as a suspicious NMI. +*/ +if (is_acr_self_reload_event (event)) + hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT ; +else if (!event->attr.precise_ip) + hwc->config |=ARCH_PERFMON_EVENTSEL_INT ;__x86_pmu_enable_event (hwc, enable_mask);break ; case INTEL_PMC_IDX_FIXED ... INTEL_PMC_IDX_FIXED_BTS - 1:
arch/x86/events/perf_event.h +10 -0
@@ -133,6 +133,16 @@ static inline bool is_acr_event_group(streturn check_leader_group (event->group_leader,PERF_X86_EVENT_ACR ); } +static inline bool is_acr_self_reload_event (struct perf_event *event) +{ +struct hw_perf_event *hwc = &event->hw; + +if (hwc->idx <0 ) +return false; + +return test_bit (hwc->idx, (unsigned long *)&hwc->config1); +} +struct amd_nb {int nb_id;/* NorthBridge id */ int refcnt;/* reference count */
Greg Kroah-Hartman
maintainerPATCH 953/957 sched_ext: Guard scx_dsq_move() against NULL kit->dsq after failed iter_new
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
[ Upstream commit 4fda9f0e7c950da4fe03cedeb2ac818edf5d03e9 ]
bpf_iter_scx_dsq_new() clears kit->dsq on failure and bpf_iter_scx_dsq_{next,destroy}() guard against that. scx_dsq_move() doesn't - it dereferences kit->dsq immediately, so a BPF program that calls scx_bpf_dsq_move[_vtime]() after a failed iter_new oopses the kernel.
Return false if kit->dsq is NULL.
--- kernel/sched/ext.c | 8 ++++++++ 1 file changed, 8 insertions(+)
kernel/sched/ext.c +8 -0
@@ -5650,6 +5650,14 @@ static bool scx_dsq_move(struct bpf_iterbool in_balance;unsigned long flags; +/* +* The verifier considers an iterator slot initialized on any +* KF_ITER_NEW return, so a BPF program may legally reach here after +* bpf_iter_scx_dsq_new() failed and left @kit->dsq NULL. +*/ +if (unlikely (!src_dsq)) +return false; +if (!scx_kf_allowed_if_unlocked () && !scx_kf_allowed (sch,SCX_KF_DISPATCH ))return false;
Greg Kroah-Hartman
maintainerPATCH 954/957 sched_ext: Pass held rq to SCX_CALL_OP() for core_sched_before
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
[ Upstream commit 4155fb489fa175ec74eedde7d02219cf2fe74303 ]
scx_prio_less() runs from core-sched's pick_next_task() path with rq locked but invokes ops.core_sched_before() with NULL locked_rq, leaving scx_locked_rq_state NULL. If the BPF callback calls a kfunc that re-acquires rq based on scx_locked_rq() - e.g. scx_bpf_cpuperf_set(cpu)
- it re-acquires the already-held rq.
Pass task_rq(a).
--- kernel/sched/ext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sched/ext.c +1 -1
@@ -2522,7 +2522,7 @@ bool scx_prio_less(const struct task_strif (SCX_HAS_OP (sch, core_sched_before) && !scx_rq_bypassing (task_rq (a)))return SCX_CALL_OP_2TASKS_RET (sch,SCX_KF_REST , core_sched_before, -NULL , +task_rq (a), (struct task_struct *)a, (struct task_struct *)b);else
Greg Kroah-Hartman
maintainerPATCH 955/957 f2fs: fix false alarm of lockdep on cp_global_sem lock
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 6a5e3de9c2bb0b691d16789a5d19e9276a09b308 ]
lockdep reported a potential deadlock:
a) TCMU device removal context:
- call del_gendisk() to get q->q_usage_counter
- call start_flush_work() to get work_completion of wb->dwork
b) f2fs writeback context:
- in wb_workfn(), which holds work_completion of wb->dwork
- call f2fs_balance_fs() to get sbi->gc_lock
c) f2fs vfs_write context:
- call f2fs_gc() to get sbi->gc_lock
- call f2fs_write_checkpoint() to get sbi->cp_global_sem
d) f2fs mount context:
- call recover_fsync_data() to get sbi->cp_global_sem
- call f2fs_check_and_fix_write_pointer() to call blkdev_report_zones() that goes down to blk_mq_alloc_request and get q->q_usage_counter
Original callstack is in Closes tag.
However, I think this is a false alarm due to before mount returns successfully (context d), we can not access file therein via vfs_write (context c).
Let's introduce per-sb cp_global_sem_key, and assign the key for cp_global_sem, so that lockdep can recognize cp_global_sem from different super block correctly.
A lot of work are done by Shin'ichiro Kawasaki, thanks a lot for the work.
--- fs/f2fs/f2fs.h | 3 +++ fs/f2fs/super.c | 11 +++++++++++ 2 files changed, 14 insertions(+)
fs/f2fs/f2fs.h +3 -0
@@ -1967,6 +1967,9 @@ struct f2fs_sb_info {spinlock_t iostat_lat_lock;struct iostat_lat_info *iostat_io_lat;#endif +#ifdef CONFIG_DEBUG_LOCK_ALLOC +struct lock_class_key cp_global_sem_key; +#endif };/* Definitions to access f2fs_sb_info */
fs/f2fs/super.c +11 -0
@@ -4889,6 +4889,11 @@ try_onemore:init_f2fs_rwsem (&sbi->gc_lock);mutex_init (&sbi->writepages);init_f2fs_rwsem (&sbi->cp_global_sem); +#ifdef CONFIG_DEBUG_LOCK_ALLOC +lockdep_register_key (&sbi->cp_global_sem_key); +lockdep_set_class (&sbi->cp_global_sem.internal_rwsem, + &sbi->cp_global_sem_key); +#endif init_f2fs_rwsem (&sbi->node_write);init_f2fs_rwsem (&sbi->node_change);spin_lock_init (&sbi->stat_lock);
@@ -5360,6 +5365,9 @@ free_options: free_sb_buf:kfree (raw_super); free_sbi: +#ifdef CONFIG_DEBUG_LOCK_ALLOC +lockdep_unregister_key (&sbi->cp_global_sem_key); +#endif kfree (sbi); sb->s_fs_info =NULL ;
@@ -5441,6 +5449,9 @@ static void kill_f2fs_super(struct super/* Release block devices last, after fscrypt_destroy_keyring(). */ if (sbi) {destroy_device_list (sbi); +#ifdef CONFIG_DEBUG_LOCK_ALLOC +lockdep_unregister_key (&sbi->cp_global_sem_key); +#endif kfree (sbi); sb->s_fs_info =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 956/957 spi: sifive: Simplify clock handling with devm_clk_get_enabled()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pei Xiao <[email protected]>
[ Upstream commit 140039c23aca067b9ff0242e3c0ce96276bb95f3 ]
Replace devm_clk_get() followed by clk_prepare_enable() with devm_clk_get_enabled() for the bus clock. This reduces boilerplate code and error handling, as the managed API automatically disables the clock when the device is removed or if probe fails.
Remove the now-unnecessary clk_disable_unprepare() calls from the probe error path and the remove callback. Adjust the error handling to use the existing put_host label.
Stable-dep-of: 0f25236694a2 ("spi: sifive: fix controller deregistration")
--- drivers/spi/spi-sifive.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-)
drivers/spi/spi-sifive.c +6 -15
@@ -312,7 +312,8 @@ static int sifive_spi_probe(struct platf goto put_host; } - spi->clk =devm_clk_get (&pdev->dev,NULL ); +/* Spin up the bus clock before hitting registers */ + spi->clk =devm_clk_get_enabled (&pdev->dev,NULL );if (IS_ERR (spi->clk)) {dev_err (&pdev->dev,"Unable to find bus clock\n" ); ret =PTR_ERR (spi->clk);
@@ -342,13 +343,6 @@ static int sifive_spi_probe(struct platf goto put_host; } -/* Spin up the bus clock before hitting registers */ - ret =clk_prepare_enable (spi->clk); -if (ret) { -dev_err (&pdev->dev,"Unable to enable bus clock\n" ); - goto put_host; - } -/* probe the number of CS lines */ spi->cs_inactive =sifive_spi_read (spi,SIFIVE_SPI_REG_CSDEF );sifive_spi_write (spi,SIFIVE_SPI_REG_CSDEF ,0xffffffffU );
@@ -357,14 +351,14 @@ static int sifive_spi_probe(struct platfif (!cs_bits) {dev_err (&pdev->dev,"Could not auto probe CS lines\n" ); ret = -EINVAL ; - goto disable_clk; + goto put_host; } num_cs =ilog2 (cs_bits) +1 ;if (num_cs >SIFIVE_SPI_MAX_CS ) {dev_err (&pdev->dev,"Invalid number of spi targets\n" ); ret = -EINVAL ; - goto disable_clk; + goto put_host; }/* Define our host */
@@ -393,7 +387,7 @@ static int sifive_spi_probe(struct platf dev_name(&pdev->dev), spi);if (ret) {dev_err (&pdev->dev,"Unable to bind to interrupt\n" ); - goto disable_clk; + goto put_host; } dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n",
@@ -402,13 +396,11 @@ static int sifive_spi_probe(struct platf ret =devm_spi_register_controller (&pdev->dev, host);if (ret <0 ) {dev_err (&pdev->dev,"spi_register_host failed\n" ); - goto disable_clk; + goto put_host; }return 0 ; -disable_clk: -clk_disable_unprepare (spi->clk); put_host:spi_controller_put (host);
@@ -422,7 +414,6 @@ static void sifive_spi_remove(struct pla/* Disable all the interrupts just in case */ sifive_spi_write (spi,SIFIVE_SPI_REG_IE ,0 ); -clk_disable_unprepare (spi->clk); }static int sifive_spi_suspend (struct device *dev)
Greg Kroah-Hartman
maintainerPATCH 957/957 spi: sifive: fix controller deregistration
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit 0f25236694a2854627c1597465a071e6bb6fe572 ]
Make sure to deregister the controller before disabling underlying resources like interrupts during driver unbind.
Note that clocks were also disabled before the recent commit 140039c23aca ("spi: sifive: Simplify clock handling with devm_clk_get_enabled()").
--- drivers/spi/spi-sifive.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/spi/spi-sifive.c +7 -1
@@ -393,7 +393,7 @@ static int sifive_spi_probe(struct platfdev_info (&pdev->dev,"mapped; irq=%d, cs=%d\n" , irq, host->num_chipselect); - ret =devm_spi_register_controller (&pdev->dev, host); + ret =spi_register_controller (host);if (ret <0 ) {dev_err (&pdev->dev,"spi_register_host failed\n" ); goto put_host;
@@ -412,8 +412,14 @@ static void sifive_spi_remove(struct plastruct spi_controller *host =platform_get_drvdata (pdev);struct sifive_spi *spi =spi_controller_get_devdata (host); +spi_controller_get (host); + +spi_unregister_controller (host); +/* Disable all the interrupts just in case */ sifive_spi_write (spi,SIFIVE_SPI_REG_IE ,0 ); + +spi_controller_put (host); }static int sifive_spi_suspend (struct device *dev)
Build tested in our x86,arm64,loongarch,riscv config successfully without error.
BRs
Wentao Guan
defconfigs:
https://gist.github.com/opsiff/a840ae9e3d6857f5b7bacb9cdc49f8e9
I means that 6.18.32-rc1 is 6.18.33-rc1.
Log:
Linux version 6.18.32-rc1-gb7adc4ce3f26 (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
Linux version 6.18.32-rc1-gb7adc4ce3f26 (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 Thu May 21 12:18:48 CST 2026 Linux version 6.18.32-rc1-gb7adc4ce3f26 (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.32-rc1-gb7adc4ce3f26 (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 Thu May 21 12:33:52 CST 2026 Linux version 6.18.32-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
Linux version 6.18.32-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 Thu May 21 12:49:11 CST 2026 Linux version 6.18.32-rc1-gb7adc4ce3f26 (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.32-rc1-gb7adc4ce3f26 (guanwentao@uos-PC) (gcc (Deepin 12.3.0-17deepin15) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #1 SMP PREEMPT_DYNAMIC Thu May 21 12:01:24 CST 2026
Hi Greg,
Am 20.05.2026 um 18:08 schrieb Greg Kroah-Hartman:
Quoted 1 line
This is the start of the stable review cycle for the 6.18.32 release.
Now I'm severely confused. You released 6.18.32 on May 17th, if I'm not mistaken.
Shouldn't this new 6.18 RC be subversion 33? Did you miss to increment the version number?
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]
Greg Kroah-Hartman
maintainerQuoted 10 lines · Peter Schneider
Hi Greg,
Am 20.05.2026 um 18:08 schrieb Greg Kroah-Hartman:
Quoted 1 line
This is the start of the stable review cycle for the 6.18.32 release.
Now I'm severely confused. You released 6.18.32 on May 17th, if I'm not mistaken.
Shouldn't this new 6.18 RC be subversion 33? Did you miss to increment the version number?
Ah crap, yes, I had to do it "by hand" due to some mess on my side and I forgot to bump that number. I should rely on my scripts to do it instead, as that's the correct way forward.
When this is released, it will have the correct number.
thanks,
greg k-h
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.18.32 release. There are 957 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
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.32 release. There are 957 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 22 May 2026 16:20:16 +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.32-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
All tests passing for Tegra ...
Test results for stable-v6.18:
10 builds: 10 pass, 0 fail
28 boots: 28 pass, 0 fail
158 tests: 158 pass, 0 failLinux version: 6.18.32-rc1-gb7adc4ce3f26
Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000,
tegra186-p3509-0000+p3636-0001, tegra194-p2972-0000,
tegra194-p3509-0000+p3668-0000, tegra20-ventana,
tegra210-p2371-2180, tegra210-p3450-0000,
tegra234-p3737-0000+p3701-0000,
tegra234-p3768-0000+p3767-0005, tegra30-cardhu-a04Jon
Signature · 1 line
nvpublic
Am 20.05.2026 um 18:08 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.18.32 release. There are 957 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.
6.18.33-rc1 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]
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.32 release. There are 957 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.
Re: [PATCH 6.18 000/957] 6.18.32-rc1 review (actually 6.18.33-rc1)
In reply to Greg Kroah-Hartman# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 6.18.32-rc1-gb7adc4ce3f26 #1 SMP PREEMPT_DYNAMIC Thu May 21 14:55:30 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Hi,
Quoted 17 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.32 release. There are 957 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 22 May 2026 16:20:16 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.18.32-rc1.g
z
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-
rc.git linux-6.18.y
and the diffstat can be found below.
Quoted 3 lines
thanks,
greg k-h
kernel builds and boots with no regressions. Tested on x86_64 (13th Gen Intel(R) Core(TM) i9-13900H).
Best regards,
Enrico
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.32 release. There are 957 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 22 May 2026 16:20:16 +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.32-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).